Skip to content

Commit

Permalink
Add operator=self_type
Browse files Browse the repository at this point in the history
  • Loading branch information
Hind-M committed Jul 1, 2024
1 parent 34346e7 commit ac4e195
Show file tree
Hide file tree
Showing 2 changed files with 89 additions and 14 deletions.
56 changes: 52 additions & 4 deletions include/sparrow/variable_size_binary_layout.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,10 @@ namespace sparrow

vs_binary_reference(L* layout, size_type index);

// template <class N = std::string>
self_type& operator=(std::string&& new_inner_val);
template <class N = std::string>
self_type& operator=(N&& new_inner_val);

self_type& operator=(self_type&& new_inner_val);

template <class N = std::string>
bool operator==(const N& rhs) const;
Expand Down Expand Up @@ -297,8 +299,8 @@ namespace sparrow
**************************************/

template <class L>
// template <class N>
auto vs_binary_reference<L>::operator=(std::string&& new_inner_val) -> self_type&
template <class N>
auto vs_binary_reference<L>::operator=(N&& new_inner_val) -> self_type&
{
buffer_type& offset_buffer = p_layout->data_ref().buffers[0];
buffer_type& data_buffer = p_layout->data_ref().buffers[1];
Expand Down Expand Up @@ -337,6 +339,51 @@ namespace sparrow
return *this;
}

template <class L>
auto vs_binary_reference<L>::operator=(self_type&& new_inner_val) -> self_type&
{
buffer_type& offset_buffer = p_layout->data_ref().buffers[0];
buffer_type& data_buffer = p_layout->data_ref().buffers[1];
const auto layout_data_length = p_layout->data_ref().length;

const buffer_type& new_offset_buffer = new_inner_val.p_layout->data_ref().buffers[0];
const buffer_type& new_data_buffer = new_inner_val.p_layout->data_ref().buffers[1];
const auto new_idx = new_inner_val.m_index;

auto initial_value_length = static_cast<size_type>(offset_buffer.template data<offset_type>()[m_index + 1] - offset_buffer.template data<offset_type>()[m_index]);
auto new_value_length = static_cast<size_type>(new_offset_buffer.template data<offset_type>()[new_idx + 1] - new_offset_buffer.template data<offset_type>()[new_idx]);

if (new_value_length > initial_value_length)
{
auto shift_val = new_value_length - initial_value_length;
// Allocate tmp buffer for data
buffer_type tmp_data_buf;
tmp_data_buf.resize(data_buffer.size() + shift_val);
// Copy initial elements
std::copy(data_buffer.cbegin(), data_buffer.cbegin() + offset_buffer.template data<offset_type>()[m_index], tmp_data_buf.begin());
// Copy new value
std::copy(new_data_buffer.cbegin() + new_offset_buffer.template data<offset_type>()[new_idx], new_data_buffer.cbegin() + new_offset_buffer.template data<offset_type>()[new_idx + 1], tmp_data_buf.begin() + offset_buffer.template data<offset_type>()[m_index]);
// Copy the elements left
std::copy(data_buffer.cbegin() + offset_buffer.template data<offset_type>()[m_index + 1], data_buffer.cend(), tmp_data_buf.begin() + offset_buffer.template data<offset_type>()[m_index] + static_cast<difference_type>(new_value_length));
std::swap(data_buffer, tmp_data_buf);
// Update offsets
std::for_each(offset_buffer.template data<offset_type>() + static_cast<difference_type>(m_index) + 1, offset_buffer.template data<offset_type>() + layout_data_length + 1, [shift_val](auto& offset){ offset += static_cast<offset_type>(shift_val); });
}
else
{
std::copy(new_data_buffer.cbegin() + new_offset_buffer.template data<offset_type>()[new_idx], new_data_buffer.cbegin() + new_offset_buffer.template data<offset_type>()[new_idx + 1], data_buffer.begin() + offset_buffer.template data<offset_type>()[m_index]);
if (new_value_length < initial_value_length)
{
std::size_t shift_val = initial_value_length - new_value_length;
// Shift values
std::copy( data_buffer.cbegin() + offset_buffer.template data<offset_type>()[m_index + 1], data_buffer.cend(), data_buffer.begin() + offset_buffer.template data<offset_type>()[m_index] + static_cast<difference_type>(new_value_length));
// Update offsets
std::for_each(offset_buffer.template data<offset_type>() + static_cast<difference_type>(m_index) + 1, offset_buffer.template data<offset_type>() + layout_data_length + 1, [shift_val](auto& offset){ offset -= static_cast<offset_type>(shift_val); });
}
}
return *this;
}

template <class L>
template <class N>
bool vs_binary_reference<L>::operator==(const N& rhs) const
Expand All @@ -351,6 +398,7 @@ namespace sparrow
// Add overloads for:
// L::inner_value_type, L::inner_const_reference
// TODO Add corresponding prototypes
// TODO use concepts

template <class L>
bool vs_binary_reference<L>::operator==(const self_type& rhs) const
Expand Down
47 changes: 37 additions & 10 deletions test/test_variable_size_binary_layout.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,15 @@ namespace sparrow
CHECK(!cref1.has_value());
CHECK_EQ(cref2.value(), words[3]);

l[0].value() = "is";
l[2].value() = "unpreparedandmore";
l[0].value() = std::string("is");
l[2].value() = std::string("unpreparedandmore");

CHECK_EQ(cref0.value(), std::string("is"));
CHECK(!cref1.has_value());
CHECK_EQ(cref2.value(), std::string("unpreparedandmore"));

l[0].value() = "are";
l[2].value() = "ok";
l[0].value() = std::string("are");
l[2].value() = std::string("ok");

CHECK_EQ(cref0.value(), std::string("are"));
CHECK(!cref1.has_value());
Expand Down Expand Up @@ -156,7 +156,7 @@ namespace sparrow
// CHECK_EQ(iter, l.cbegin());
// }

TEST_CASE("basic_vsbl")
TEST_CASE("vs_binary_reference")
{
using layout_type = variable_size_binary_layout<std::string, std::string_view>;

Expand Down Expand Up @@ -184,31 +184,58 @@ namespace sparrow

SUBCASE("inner_reference")
{
cref3.value() = "unpreparedandmore";
cref3.value() = std::string("unpreparedandmore");

CHECK_EQ(cref0.value(), words[0]);
CHECK_EQ(cref1.value(), words[1]);
CHECK_EQ(cref2.value(), words[2]);
CHECK_EQ(cref3.value(), std::string("unpreparedandmore"));

cref0.value() = "he";
cref1.value() = "is";
cref2.value() = "";
cref0.value() = std::string("he");
cref1.value() = std::string("is");
cref2.value() = std::string("");

CHECK_EQ(cref0.value(), std::string("he"));
CHECK_EQ(cref1.value(), std::string("is"));
CHECK_EQ(cref2.value(), std::string(""));
CHECK_EQ(cref3.value(), std::string("unpreparedandmore"));
}

SUBCASE("operator==with_self_type")
SUBCASE("operator==self_type")
{
vs_binary_reference<layout_type> vs_ref0(&l, 0);
CHECK_EQ(cref0.value(), vs_ref0);

vs_binary_reference<layout_type> vs_ref3(&l, 3);
CHECK_EQ(cref3.value(), vs_ref3);
}

SUBCASE("operator=self_type")
{
constexpr std::array<std::string_view, 4> replacement_words = {"this", "is", "a", "replacement"};

array_data::bitmap_type rpl_bitmap{replacement_words.size(), true};
array_data rpl_vs_data = make_default_array_data<layout_type>(replacement_words, rpl_bitmap, 0);

layout_type rpl_l(rpl_vs_data);
CHECK_EQ(rpl_l.size(), rpl_vs_data.length - rpl_vs_data.offset);

vs_binary_reference<layout_type> rpl_vs_ref0(&rpl_l, 0);
vs_binary_reference<layout_type> rpl_vs_ref1(&rpl_l, 1);
vs_binary_reference<layout_type> rpl_vs_ref2(&rpl_l, 2);
vs_binary_reference<layout_type> rpl_vs_ref3(&rpl_l, 3);

cref0.value() = std::move(rpl_vs_ref0);
cref1.value() = std::move(rpl_vs_ref1);
cref2.value() = std::move(rpl_vs_ref2);
cref3.value() = std::move(rpl_vs_ref3);

CHECK_EQ(cref0.value(), std::string("this"));
CHECK_EQ(cref1.value(), std::string("is"));
CHECK_EQ(cref2.value(), std::string("a"));
CHECK_EQ(cref3.value(), std::string("replacement"));
}

// TODO add tests for the different overloads of operator = and ==
}
}
Expand Down

0 comments on commit ac4e195

Please sign in to comment.