From ede5a919028c5c328ef0791fece3fe9ed517651d Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 22 Feb 2021 09:33:12 +0000 Subject: [PATCH] Added uninitialized_resize() --- include/etl/basic_string.h | 13 ++++ include/etl/private/ivectorpointer.h | 18 +++++ include/etl/private/pvoidvector.h | 11 +++ include/etl/vector.h | 22 ++++++ test/test_string_char.cpp | 73 +++++++++++++++++++- test/test_string_char_external_buffer.cpp | 4 +- test/test_string_u16.cpp | 73 +++++++++++++++++++- test/test_string_u16_external_buffer.cpp | 4 +- test/test_string_u32.cpp | 73 +++++++++++++++++++- test/test_string_u32_external_buffer.cpp | 4 +- test/test_string_wchar_t.cpp | 73 +++++++++++++++++++- test/test_string_wchar_t_external_buffer.cpp | 4 +- test/test_vector.cpp | 72 +++++++++++++++++++ 13 files changed, 428 insertions(+), 16 deletions(-) diff --git a/include/etl/basic_string.h b/include/etl/basic_string.h index 5857ccd3..f4337b06 100644 --- a/include/etl/basic_string.h +++ b/include/etl/basic_string.h @@ -484,6 +484,19 @@ namespace etl cleanup(); } + //********************************************************************* + /// Resizes the string, but doesn't initialise the free space + /// except for a terminator null. + ///\param new_size The new size. + //********************************************************************* + void uninitialized_resize(size_type new_size) + { + new_size = etl::min(new_size, CAPACITY); + + current_size = new_size; + p_buffer[new_size] = 0; + } + //********************************************************************* /// Returns a reference to the value at index 'i' ///\param i The index. diff --git a/include/etl/private/ivectorpointer.h b/include/etl/private/ivectorpointer.h index b34a75e7..3d319cbc 100644 --- a/include/etl/private/ivectorpointer.h +++ b/include/etl/private/ivectorpointer.h @@ -202,6 +202,15 @@ namespace etl base_t::resize(new_size, value); } + //********************************************************************* + /// Resizes the vector, but does not initialise new entries. + ///\param new_size The new size. + //********************************************************************* + void uninitialized_resize(size_t new_size) + { + base_t::uninitialized_resize(new_size); + } + //********************************************************************* /// Returns a reference to the value at index 'i' ///\param i The index. @@ -624,6 +633,15 @@ namespace etl base_t::resize(new_size, const_cast(value)); } + //********************************************************************* + /// Resizes the vector, but does not initialise new entries. + ///\param new_size The new size. + //********************************************************************* + void uninitialized_resize(size_t new_size) + { + base_t::uninitialized_resize(new_size); + } + //********************************************************************* /// Returns a reference to the value at index 'i' ///\param i The index. diff --git a/include/etl/private/pvoidvector.h b/include/etl/private/pvoidvector.h index 835cc463..a320109c 100644 --- a/include/etl/private/pvoidvector.h +++ b/include/etl/private/pvoidvector.h @@ -217,6 +217,17 @@ namespace etl p_end = p_new_end; } + //********************************************************************* + /// Resizes the vector, but does not initialise new entries. + ///\param new_size The new size. + //********************************************************************* + void uninitialized_resize(size_t new_size) + { + ETL_ASSERT(new_size <= CAPACITY, ETL_ERROR(vector_full)); + + p_end = p_buffer + new_size; + } + //********************************************************************* /// Returns a reference to the value at index 'i' ///\param i The index. diff --git a/include/etl/vector.h b/include/etl/vector.h index babdd895..863bad50 100644 --- a/include/etl/vector.h +++ b/include/etl/vector.h @@ -248,6 +248,28 @@ namespace etl p_end = p_buffer + new_size; } + //********************************************************************* + /// Resizes the vector, but does not initialise new entries. + ///\param new_size The new size. + //********************************************************************* + void uninitialized_resize(size_t new_size) + { + ETL_ASSERT(new_size <= CAPACITY, ETL_ERROR(vector_full)); + +#if defined(ETL_DEBUG_COUNT) + if (size() < new_size) + { + ETL_ADD_DEBUG_COUNT(new_size - size()) + } + else + { + ETL_SUBTRACT_DEBUG_COUNT(size() - new_size) + } +#endif + + p_end = p_buffer + new_size; + } + //********************************************************************* /// Does nothing. //********************************************************************* diff --git a/test/test_string_char.cpp b/test/test_string_char.cpp index 91d02fa8..0298b76d 100644 --- a/test/test_string_char.cpp +++ b/test/test_string_char.cpp @@ -617,7 +617,7 @@ namespace Text text(INITIAL_SIZE, INITIAL_VALUE); text.resize(NEW_SIZE, INITIAL_VALUE); - std::array compare_text; + std::array compare_text; compare_text.fill(INITIAL_VALUE); bool is_equal = Equal(compare_text, text); @@ -669,7 +669,7 @@ namespace CHECK_EQUAL(text.size(), NEW_SIZE); - std::array compare_text; + std::array compare_text; compare_text.fill(INITIAL_VALUE); bool is_equal = Equal(compare_text, text); @@ -679,6 +679,75 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_uninitialized_resize_up) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = 8; + const value_t INITIAL_VALUE = STR('A'); + const value_t FILL_VALUE = STR('B'); + + Text text(INITIAL_SIZE, INITIAL_VALUE); + + Text::pointer pbegin = &text.front(); + Text::pointer pend = &text.back() + 1; + Text::pointer pmax = pbegin + text.max_size(); + + // Fill free space with a pattern. + std::fill(pend, pmax, FILL_VALUE); + + text.uninitialized_resize(NEW_SIZE); + + std::array compare_text; + compare_text.fill(FILL_VALUE); + std::fill(compare_text.begin(), compare_text.begin() + INITIAL_SIZE, INITIAL_VALUE); + + bool is_equal = Equal(compare_text, text); + CHECK(is_equal); + + CHECK_EQUAL(text.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_uninitialized_resize_up_excess) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = SIZE + 1; + + Text text(INITIAL_SIZE, STR('A')); + + text.uninitialized_resize(NEW_SIZE); + + CHECK_EQUAL(text.size(), SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_uninitialized_resize_down) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = 2; + const value_t INITIAL_VALUE = STR('A'); + const value_t FILL_VALUE = STR('B'); + + Text text(INITIAL_SIZE, INITIAL_VALUE); + + Text::pointer pbegin = &text.front(); + Text::pointer pend = &text.back() + 1; + Text::pointer pmax = pbegin + text.max_size(); + + // Fill free space with a pattern. + std::fill(pend, pmax, FILL_VALUE); + + text.uninitialized_resize(NEW_SIZE); + + std::array compare_text; + compare_text.fill(INITIAL_VALUE); + + bool is_equal = Equal(compare_text, text); + CHECK(is_equal); + + CHECK_EQUAL(text.size(), NEW_SIZE); + } //************************************************************************* TEST_FIXTURE(SetupFixture, test_empty_full) diff --git a/test/test_string_char_external_buffer.cpp b/test/test_string_char_external_buffer.cpp index 46c29643..2d590e94 100644 --- a/test/test_string_char_external_buffer.cpp +++ b/test/test_string_char_external_buffer.cpp @@ -760,7 +760,7 @@ namespace Text text(INITIAL_SIZE, INITIAL_VALUE, buffer.data(), buffer.size()); text.resize(NEW_SIZE, INITIAL_VALUE); - std::array compare_text; + std::array compare_text; compare_text.fill(INITIAL_VALUE); bool is_equal = Equal(compare_text, text); @@ -815,7 +815,7 @@ namespace CHECK_EQUAL(text.size(), NEW_SIZE); - std::array compare_text; + std::array compare_text; compare_text.fill(INITIAL_VALUE); bool is_equal = Equal(compare_text, text); diff --git a/test/test_string_u16.cpp b/test/test_string_u16.cpp index 477014be..cca9ec3f 100644 --- a/test/test_string_u16.cpp +++ b/test/test_string_u16.cpp @@ -617,7 +617,7 @@ namespace Text text(INITIAL_SIZE, INITIAL_VALUE); text.resize(NEW_SIZE, INITIAL_VALUE); - std::array compare_text; + std::array compare_text; compare_text.fill(INITIAL_VALUE); bool is_equal = Equal(compare_text, text); @@ -669,7 +669,7 @@ namespace CHECK_EQUAL(text.size(), NEW_SIZE); - std::array compare_text; + std::array compare_text; compare_text.fill(INITIAL_VALUE); bool is_equal = Equal(compare_text, text); @@ -679,6 +679,75 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_uninitialized_resize_up) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = 8; + const value_t INITIAL_VALUE = STR('A'); + const value_t FILL_VALUE = STR('B'); + + Text text(INITIAL_SIZE, INITIAL_VALUE); + + Text::pointer pbegin = &text.front(); + Text::pointer pend = &text.back() + 1; + Text::pointer pmax = pbegin + text.max_size(); + + // Fill free space with a pattern. + std::fill(pend, pmax, FILL_VALUE); + + text.uninitialized_resize(NEW_SIZE); + + std::array compare_text; + compare_text.fill(FILL_VALUE); + std::fill(compare_text.begin(), compare_text.begin() + INITIAL_SIZE, INITIAL_VALUE); + + bool is_equal = Equal(compare_text, text); + CHECK(is_equal); + + CHECK_EQUAL(text.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_uninitialized_resize_up_excess) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = SIZE + 1; + + Text text(INITIAL_SIZE, STR('A')); + + text.uninitialized_resize(NEW_SIZE); + + CHECK_EQUAL(text.size(), SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_uninitialized_resize_down) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = 2; + const value_t INITIAL_VALUE = STR('A'); + const value_t FILL_VALUE = STR('B'); + + Text text(INITIAL_SIZE, INITIAL_VALUE); + + Text::pointer pbegin = &text.front(); + Text::pointer pend = &text.back() + 1; + Text::pointer pmax = pbegin + text.max_size(); + + // Fill free space with a pattern. + std::fill(pend, pmax, FILL_VALUE); + + text.uninitialized_resize(NEW_SIZE); + + std::array compare_text; + compare_text.fill(INITIAL_VALUE); + + bool is_equal = Equal(compare_text, text); + CHECK(is_equal); + + CHECK_EQUAL(text.size(), NEW_SIZE); + } //************************************************************************* TEST_FIXTURE(SetupFixture, test_empty_full) diff --git a/test/test_string_u16_external_buffer.cpp b/test/test_string_u16_external_buffer.cpp index 9098efb7..77a3b64d 100644 --- a/test/test_string_u16_external_buffer.cpp +++ b/test/test_string_u16_external_buffer.cpp @@ -760,7 +760,7 @@ namespace Text text(INITIAL_SIZE, INITIAL_VALUE, buffer.data(), buffer.size()); text.resize(NEW_SIZE, INITIAL_VALUE); - std::array compare_text; + std::array compare_text; compare_text.fill(INITIAL_VALUE); bool is_equal = Equal(compare_text, text); @@ -815,7 +815,7 @@ namespace CHECK_EQUAL(text.size(), NEW_SIZE); - std::array compare_text; + std::array compare_text; compare_text.fill(INITIAL_VALUE); bool is_equal = Equal(compare_text, text); diff --git a/test/test_string_u32.cpp b/test/test_string_u32.cpp index b52aa8b3..52c3064b 100644 --- a/test/test_string_u32.cpp +++ b/test/test_string_u32.cpp @@ -617,7 +617,7 @@ namespace Text text(INITIAL_SIZE, INITIAL_VALUE); text.resize(NEW_SIZE, INITIAL_VALUE); - std::array compare_text; + std::array compare_text; compare_text.fill(INITIAL_VALUE); bool is_equal = Equal(compare_text, text); @@ -669,7 +669,7 @@ namespace CHECK_EQUAL(text.size(), NEW_SIZE); - std::array compare_text; + std::array compare_text; compare_text.fill(INITIAL_VALUE); bool is_equal = Equal(compare_text, text); @@ -679,6 +679,75 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_uninitialized_resize_up) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = 8; + const value_t INITIAL_VALUE = STR('A'); + const value_t FILL_VALUE = STR('B'); + + Text text(INITIAL_SIZE, INITIAL_VALUE); + + Text::pointer pbegin = &text.front(); + Text::pointer pend = &text.back() + 1; + Text::pointer pmax = pbegin + text.max_size(); + + // Fill free space with a pattern. + std::fill(pend, pmax, FILL_VALUE); + + text.uninitialized_resize(NEW_SIZE); + + std::array compare_text; + compare_text.fill(FILL_VALUE); + std::fill(compare_text.begin(), compare_text.begin() + INITIAL_SIZE, INITIAL_VALUE); + + bool is_equal = Equal(compare_text, text); + CHECK(is_equal); + + CHECK_EQUAL(text.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_uninitialized_resize_up_excess) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = SIZE + 1; + + Text text(INITIAL_SIZE, STR('A')); + + text.uninitialized_resize(NEW_SIZE); + + CHECK_EQUAL(text.size(), SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_uninitialized_resize_down) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = 2; + const value_t INITIAL_VALUE = STR('A'); + const value_t FILL_VALUE = STR('B'); + + Text text(INITIAL_SIZE, INITIAL_VALUE); + + Text::pointer pbegin = &text.front(); + Text::pointer pend = &text.back() + 1; + Text::pointer pmax = pbegin + text.max_size(); + + // Fill free space with a pattern. + std::fill(pend, pmax, FILL_VALUE); + + text.uninitialized_resize(NEW_SIZE); + + std::array compare_text; + compare_text.fill(INITIAL_VALUE); + + bool is_equal = Equal(compare_text, text); + CHECK(is_equal); + + CHECK_EQUAL(text.size(), NEW_SIZE); + } //************************************************************************* TEST_FIXTURE(SetupFixture, test_empty_full) diff --git a/test/test_string_u32_external_buffer.cpp b/test/test_string_u32_external_buffer.cpp index 6e3a3b90..b4d1f3d2 100644 --- a/test/test_string_u32_external_buffer.cpp +++ b/test/test_string_u32_external_buffer.cpp @@ -760,7 +760,7 @@ namespace Text text(INITIAL_SIZE, INITIAL_VALUE, buffer.data(), buffer.size()); text.resize(NEW_SIZE, INITIAL_VALUE); - std::array compare_text; + std::array compare_text; compare_text.fill(INITIAL_VALUE); bool is_equal = Equal(compare_text, text); @@ -815,7 +815,7 @@ namespace CHECK_EQUAL(text.size(), NEW_SIZE); - std::array compare_text; + std::array compare_text; compare_text.fill(INITIAL_VALUE); bool is_equal = Equal(compare_text, text); diff --git a/test/test_string_wchar_t.cpp b/test/test_string_wchar_t.cpp index d8b7853f..8b2794b4 100644 --- a/test/test_string_wchar_t.cpp +++ b/test/test_string_wchar_t.cpp @@ -617,7 +617,7 @@ namespace Text text(INITIAL_SIZE, INITIAL_VALUE); text.resize(NEW_SIZE, INITIAL_VALUE); - std::array compare_text; + std::array compare_text; compare_text.fill(INITIAL_VALUE); bool is_equal = Equal(compare_text, text); @@ -669,7 +669,7 @@ namespace CHECK_EQUAL(text.size(), NEW_SIZE); - std::array compare_text; + std::array compare_text; compare_text.fill(INITIAL_VALUE); bool is_equal = Equal(compare_text, text); @@ -679,6 +679,75 @@ namespace #endif } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_uninitialized_resize_up) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = 8; + const value_t INITIAL_VALUE = STR('A'); + const value_t FILL_VALUE = STR('B'); + + Text text(INITIAL_SIZE, INITIAL_VALUE); + + Text::pointer pbegin = &text.front(); + Text::pointer pend = &text.back() + 1; + Text::pointer pmax = pbegin + text.max_size(); + + // Fill free space with a pattern. + std::fill(pend, pmax, FILL_VALUE); + + text.uninitialized_resize(NEW_SIZE); + + std::array compare_text; + compare_text.fill(FILL_VALUE); + std::fill(compare_text.begin(), compare_text.begin() + INITIAL_SIZE, INITIAL_VALUE); + + bool is_equal = Equal(compare_text, text); + CHECK(is_equal); + + CHECK_EQUAL(text.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_uninitialized_resize_up_excess) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = SIZE + 1; + + Text text(INITIAL_SIZE, STR('A')); + + text.uninitialized_resize(NEW_SIZE); + + CHECK_EQUAL(text.size(), SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_uninitialized_resize_down) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = 2; + const value_t INITIAL_VALUE = STR('A'); + const value_t FILL_VALUE = STR('B'); + + Text text(INITIAL_SIZE, INITIAL_VALUE); + + Text::pointer pbegin = &text.front(); + Text::pointer pend = &text.back() + 1; + Text::pointer pmax = pbegin + text.max_size(); + + // Fill free space with a pattern. + std::fill(pend, pmax, FILL_VALUE); + + text.uninitialized_resize(NEW_SIZE); + + std::array compare_text; + compare_text.fill(INITIAL_VALUE); + + bool is_equal = Equal(compare_text, text); + CHECK(is_equal); + + CHECK_EQUAL(text.size(), NEW_SIZE); + } //************************************************************************* TEST_FIXTURE(SetupFixture, test_empty_full) diff --git a/test/test_string_wchar_t_external_buffer.cpp b/test/test_string_wchar_t_external_buffer.cpp index 4202ea21..0221a849 100644 --- a/test/test_string_wchar_t_external_buffer.cpp +++ b/test/test_string_wchar_t_external_buffer.cpp @@ -760,7 +760,7 @@ namespace Text text(INITIAL_SIZE, INITIAL_VALUE, buffer.data(), buffer.size()); text.resize(NEW_SIZE, INITIAL_VALUE); - std::array compare_text; + std::array compare_text; compare_text.fill(INITIAL_VALUE); bool is_equal = Equal(compare_text, text); @@ -815,7 +815,7 @@ namespace CHECK_EQUAL(text.size(), NEW_SIZE); - std::array compare_text; + std::array compare_text; compare_text.fill(INITIAL_VALUE); bool is_equal = Equal(compare_text, text); diff --git a/test/test_vector.cpp b/test/test_vector.cpp index a21b76cc..cdf37e98 100644 --- a/test/test_vector.cpp +++ b/test/test_vector.cpp @@ -342,6 +342,78 @@ namespace CHECK_EQUAL(data.size(), NEW_SIZE); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_uninitialized_resize_up) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = 8; + + Data data(INITIAL_SIZE); + + int* pbegin = &data.front(); + int* pend = &data.back() + 1; + int* pmax = pbegin + data.max_size(); + + constexpr int Pattern = 0x12345678; + + // Fill free space with a pattern. + std::fill(pend, pmax, Pattern); + + data.uninitialized_resize(NEW_SIZE); + + for (int* p = pbegin; p != pend; ++p) + { + CHECK_EQUAL(*p, 0); + } + + for (int* p = pend; p != pmax; ++p) + { + CHECK_EQUAL(*p, Pattern); + } + + CHECK_EQUAL(data.size(), NEW_SIZE); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_uninitialized_resize_up_excess) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = SIZE + 1; + + Data data(INITIAL_SIZE); + + CHECK_THROW(data.resize(NEW_SIZE), etl::vector_full); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_uninitialized_resize_down) + { + const size_t INITIAL_SIZE = 5; + const size_t NEW_SIZE = 2; + + Data data(INITIAL_SIZE); + + int* pbegin = &data.front(); + int* pend = &data.back() + 1; + int* pmax = pbegin + data.max_size(); + + constexpr int Pattern = 0x12345678; + + // Fill free space with a pattern. + std::fill(pend, pmax, Pattern); + + data.uninitialized_resize(NEW_SIZE); + + pend = &data.back() + 1; + + for (int* p = pbegin; p < pend; ++p) + { + CHECK_EQUAL(*p, 0); + } + + CHECK_EQUAL(data.size(), NEW_SIZE); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_empty) {