From 65bf6e7a3a2b1b477c07b0c15cf505a75a41633f Mon Sep 17 00:00:00 2001 From: Hind Montassif Date: Mon, 1 Jul 2024 13:39:04 +0200 Subject: [PATCH] Add operator=self_type --- .../sparrow/variable_size_binary_layout.hpp | 56 +++++++++++++++++-- test/test_variable_size_binary_layout.cpp | 47 ++++++++++++---- 2 files changed, 89 insertions(+), 14 deletions(-) diff --git a/include/sparrow/variable_size_binary_layout.hpp b/include/sparrow/variable_size_binary_layout.hpp index 64cda0a6..6e2e9423 100644 --- a/include/sparrow/variable_size_binary_layout.hpp +++ b/include/sparrow/variable_size_binary_layout.hpp @@ -96,8 +96,10 @@ namespace sparrow vs_binary_reference(L* layout, size_type index); -// template - self_type& operator=(std::string&& new_inner_val); + template + self_type& operator=(N&& new_inner_val); + + self_type& operator=(self_type&& new_inner_val); template bool operator==(const N& rhs) const; @@ -302,8 +304,8 @@ namespace sparrow **************************************/ template -// template - auto vs_binary_reference::operator=(std::string&& new_inner_val) -> self_type& + template + auto vs_binary_reference::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]; @@ -342,6 +344,51 @@ namespace sparrow return *this; } + template + auto vs_binary_reference::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(offset_buffer.template data()[m_index + 1] - offset_buffer.template data()[m_index]); + auto new_value_length = static_cast(new_offset_buffer.template data()[new_idx + 1] - new_offset_buffer.template data()[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()[m_index], tmp_data_buf.begin()); + // Copy new value + std::copy(new_data_buffer.cbegin() + new_offset_buffer.template data()[new_idx], new_data_buffer.cbegin() + new_offset_buffer.template data()[new_idx + 1], tmp_data_buf.begin() + offset_buffer.template data()[m_index]); + // Copy the elements left + std::copy(data_buffer.cbegin() + offset_buffer.template data()[m_index + 1], data_buffer.cend(), tmp_data_buf.begin() + offset_buffer.template data()[m_index] + static_cast(new_value_length)); + std::swap(data_buffer, tmp_data_buf); + // Update offsets + std::for_each(offset_buffer.template data() + static_cast(m_index) + 1, offset_buffer.template data() + layout_data_length + 1, [shift_val](auto& offset){ offset += static_cast(shift_val); }); + } + else + { + std::copy(new_data_buffer.cbegin() + new_offset_buffer.template data()[new_idx], new_data_buffer.cbegin() + new_offset_buffer.template data()[new_idx + 1], data_buffer.begin() + offset_buffer.template data()[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()[m_index + 1], data_buffer.cend(), data_buffer.begin() + offset_buffer.template data()[m_index] + static_cast(new_value_length)); + // Update offsets + std::for_each(offset_buffer.template data() + static_cast(m_index) + 1, offset_buffer.template data() + layout_data_length + 1, [shift_val](auto& offset){ offset -= static_cast(shift_val); }); + } + } + return *this; + } + template template bool vs_binary_reference::operator==(const N& rhs) const @@ -356,6 +403,7 @@ namespace sparrow // Add overloads for: // L::inner_value_type, L::inner_const_reference // TODO Add corresponding prototypes + // TODO use concepts template bool vs_binary_reference::operator==(const self_type& rhs) const diff --git a/test/test_variable_size_binary_layout.cpp b/test/test_variable_size_binary_layout.cpp index 081d75f0..568abba6 100644 --- a/test/test_variable_size_binary_layout.cpp +++ b/test/test_variable_size_binary_layout.cpp @@ -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()); @@ -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; @@ -184,16 +184,16 @@ 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")); @@ -201,7 +201,7 @@ namespace sparrow CHECK_EQ(cref3.value(), std::string("unpreparedandmore")); } - SUBCASE("operator==with_self_type") + SUBCASE("operator==self_type") { vs_binary_reference vs_ref0(&l, 0); CHECK_EQ(cref0.value(), vs_ref0); @@ -209,6 +209,33 @@ namespace sparrow vs_binary_reference vs_ref3(&l, 3); CHECK_EQ(cref3.value(), vs_ref3); } + + SUBCASE("operator=self_type") + { + constexpr std::array 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(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 rpl_vs_ref0(&rpl_l, 0); + vs_binary_reference rpl_vs_ref1(&rpl_l, 1); + vs_binary_reference rpl_vs_ref2(&rpl_l, 2); + vs_binary_reference 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 == } }