diff --git a/include/etl/basic_string.h b/include/etl/basic_string.h index 8467fc91..8818c0ae 100644 --- a/include/etl/basic_string.h +++ b/include/etl/basic_string.h @@ -1296,31 +1296,31 @@ namespace etl //********************************************************************* /// Copies a portion of a string. - ///\param s Pointer to the string to copy. - ///\param len The number of characters to copy. - ///\param pos The position to start copying from. + ///\param s Pointer to the string to copy. + ///\param count The number of characters to copy. + ///\param pos The position to start copying from. //********************************************************************* - size_type copy(pointer s, size_type len, size_type pos = 0) + size_type copy(pointer dest, size_type count, size_type pos = 0) const { - if ((pos + len > size())) + if (pos < size()) { -#if ETL_STRING_TRUNCATION_CHECKS_ENABLED - set_truncated(true); + if (count != npos) + { + count = etl::min(count, size() - pos); + } + else + { + count = size() - pos; + } -#if defined(ETL_STRING_TRUNCATION_IS_ERROR) - ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation)); -#endif -#endif + etl::copy_n(p_buffer + pos, count, dest); + + return count; } - - size_type endpos = etl::min(pos + len, size()); - - for (size_type i = pos; i < endpos; ++i) + else { - *s++ = p_buffer[i]; + return 0U; } - - return endpos - pos; } //********************************************************************* diff --git a/test/test_string_char.cpp b/test/test_string_char.cpp index dab48f9b..840c3855 100644 --- a/test/test_string_char.cpp +++ b/test/test_string_char.cpp @@ -3000,6 +3000,73 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_start_pos_too_large) + { + Text text(initial_text.c_str()); + + value_t buffer1[SIZE]; + + size_t length1 = text.copy(buffer1, 5, SIZE); + + CHECK_EQUAL(0U, length1); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_count_equals_npos) + { + Compare_Text compare_text(initial_text.c_str()); + Text text(initial_text.c_str()); + + value_t buffer1[SIZE]; + value_t buffer2[SIZE]; + + size_t length1 = compare_text.copy(buffer1, Compare_Text::npos, 2); + buffer1[length1] = STR('\0'); + + size_t length2 = text.copy(buffer2, Text::npos, 2); + buffer2[length2] = STR('\0'); + + CHECK_EQUAL(length1, length2); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + + bool is_equal = std::equal(buffer1, + buffer1 + length1, + buffer2); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_count_too_large) + { + Compare_Text compare_text(initial_text.c_str()); + Text text(initial_text.c_str()); + + value_t buffer1[SIZE]; + value_t buffer2[SIZE]; + + size_t length1 = compare_text.copy(buffer1, SIZE, 2); + buffer1[length1] = STR('\0'); + + size_t length2 = text.copy(buffer2, SIZE, 2); + buffer2[length2] = STR('\0'); + + CHECK_EQUAL(length1, length2); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + + bool is_equal = std::equal(buffer1, + buffer1 + length1, + buffer2); + CHECK(is_equal); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_find_string) { diff --git a/test/test_string_char_external_buffer.cpp b/test/test_string_char_external_buffer.cpp index 7fe729b1..63017019 100644 --- a/test/test_string_char_external_buffer.cpp +++ b/test/test_string_char_external_buffer.cpp @@ -3290,7 +3290,7 @@ namespace TEST_FIXTURE(SetupFixture, test_copy) { Compare_Text compare_text(initial_text.c_str()); - + TextBuffer buffer; Text text(initial_text.c_str(), buffer.data(), buffer.size()); @@ -3314,6 +3314,78 @@ namespace CHECK(is_equal); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_start_pos_too_large) + { + TextBuffer buffer; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + value_t buffer1[SIZE]; + + size_t length1 = text.copy(buffer1, 5, SIZE); + + CHECK_EQUAL(0U, length1); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_count_equals_npos) + { + Compare_Text compare_text(initial_text.c_str()); + + TextBuffer buffer; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + value_t buffer1[SIZE]; + value_t buffer2[SIZE]; + + size_t length1 = compare_text.copy(buffer1, Compare_Text::npos, 2); + buffer1[length1] = STR('\0'); + + size_t length2 = text.copy(buffer2, Text::npos, 2); + buffer2[length2] = STR('\0'); + + CHECK_EQUAL(length1, length2); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + + bool is_equal = std::equal(buffer1, + buffer1 + length1, + buffer2); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_count_too_large) + { + Compare_Text compare_text(initial_text.c_str()); + + TextBuffer buffer; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + value_t buffer1[SIZE]; + value_t buffer2[SIZE]; + + size_t length1 = compare_text.copy(buffer1, SIZE, 2); + buffer1[length1] = STR('\0'); + + size_t length2 = text.copy(buffer2, SIZE, 2); + buffer2[length2] = STR('\0'); + + CHECK_EQUAL(length1, length2); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + + bool is_equal = std::equal(buffer1, + buffer1 + length1, + buffer2); + CHECK(is_equal); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_find_string) { diff --git a/test/test_string_u16.cpp b/test/test_string_u16.cpp index 15703e12..2bf49875 100644 --- a/test/test_string_u16.cpp +++ b/test/test_string_u16.cpp @@ -2995,8 +2995,75 @@ namespace #endif bool is_equal = std::equal(buffer1, - buffer1 + length1, - buffer2); + buffer1 + length1, + buffer2); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_start_pos_too_large) + { + Text text(initial_text.c_str()); + + value_t buffer1[SIZE]; + + size_t length1 = text.copy(buffer1, 5, SIZE); + + CHECK_EQUAL(0U, length1); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_count_equals_npos) + { + Compare_Text compare_text(initial_text.c_str()); + Text text(initial_text.c_str()); + + value_t buffer1[SIZE]; + value_t buffer2[SIZE]; + + size_t length1 = compare_text.copy(buffer1, Compare_Text::npos, 2); + buffer1[length1] = STR('\0'); + + size_t length2 = text.copy(buffer2, Text::npos, 2); + buffer2[length2] = STR('\0'); + + CHECK_EQUAL(length1, length2); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + + bool is_equal = std::equal(buffer1, + buffer1 + length1, + buffer2); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_count_too_large) + { + Compare_Text compare_text(initial_text.c_str()); + Text text(initial_text.c_str()); + + value_t buffer1[SIZE]; + value_t buffer2[SIZE]; + + size_t length1 = compare_text.copy(buffer1, SIZE, 2); + buffer1[length1] = STR('\0'); + + size_t length2 = text.copy(buffer2, SIZE, 2); + buffer2[length2] = STR('\0'); + + CHECK_EQUAL(length1, length2); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + + bool is_equal = std::equal(buffer1, + buffer1 + length1, + buffer2); CHECK(is_equal); } diff --git a/test/test_string_u16_external_buffer.cpp b/test/test_string_u16_external_buffer.cpp index c62639cd..13128983 100644 --- a/test/test_string_u16_external_buffer.cpp +++ b/test/test_string_u16_external_buffer.cpp @@ -3290,7 +3290,7 @@ namespace TEST_FIXTURE(SetupFixture, test_copy) { Compare_Text compare_text(initial_text.c_str()); - + TextBuffer buffer; Text text(initial_text.c_str(), buffer.data(), buffer.size()); @@ -3309,8 +3309,80 @@ namespace #endif bool is_equal = std::equal(buffer1, - buffer1 + length1, - buffer2); + buffer1 + length1, + buffer2); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_start_pos_too_large) + { + TextBuffer buffer; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + value_t buffer1[SIZE]; + + size_t length1 = text.copy(buffer1, 5, SIZE); + + CHECK_EQUAL(0U, length1); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_count_equals_npos) + { + Compare_Text compare_text(initial_text.c_str()); + + TextBuffer buffer; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + value_t buffer1[SIZE]; + value_t buffer2[SIZE]; + + size_t length1 = compare_text.copy(buffer1, Compare_Text::npos, 2); + buffer1[length1] = STR('\0'); + + size_t length2 = text.copy(buffer2, Text::npos, 2); + buffer2[length2] = STR('\0'); + + CHECK_EQUAL(length1, length2); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + + bool is_equal = std::equal(buffer1, + buffer1 + length1, + buffer2); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_count_too_large) + { + Compare_Text compare_text(initial_text.c_str()); + + TextBuffer buffer; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + value_t buffer1[SIZE]; + value_t buffer2[SIZE]; + + size_t length1 = compare_text.copy(buffer1, SIZE, 2); + buffer1[length1] = STR('\0'); + + size_t length2 = text.copy(buffer2, SIZE, 2); + buffer2[length2] = STR('\0'); + + CHECK_EQUAL(length1, length2); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + + bool is_equal = std::equal(buffer1, + buffer1 + length1, + buffer2); CHECK(is_equal); } diff --git a/test/test_string_u32.cpp b/test/test_string_u32.cpp index f5c2dfb3..75a827a5 100644 --- a/test/test_string_u32.cpp +++ b/test/test_string_u32.cpp @@ -2995,8 +2995,75 @@ namespace #endif bool is_equal = std::equal(buffer1, - buffer1 + length1, - buffer2); + buffer1 + length1, + buffer2); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_start_pos_too_large) + { + Text text(initial_text.c_str()); + + value_t buffer1[SIZE]; + + size_t length1 = text.copy(buffer1, 5, SIZE); + + CHECK_EQUAL(0U, length1); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_count_equals_npos) + { + Compare_Text compare_text(initial_text.c_str()); + Text text(initial_text.c_str()); + + value_t buffer1[SIZE]; + value_t buffer2[SIZE]; + + size_t length1 = compare_text.copy(buffer1, Compare_Text::npos, 2); + buffer1[length1] = STR('\0'); + + size_t length2 = text.copy(buffer2, Text::npos, 2); + buffer2[length2] = STR('\0'); + + CHECK_EQUAL(length1, length2); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + + bool is_equal = std::equal(buffer1, + buffer1 + length1, + buffer2); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_count_too_large) + { + Compare_Text compare_text(initial_text.c_str()); + Text text(initial_text.c_str()); + + value_t buffer1[SIZE]; + value_t buffer2[SIZE]; + + size_t length1 = compare_text.copy(buffer1, SIZE, 2); + buffer1[length1] = STR('\0'); + + size_t length2 = text.copy(buffer2, SIZE, 2); + buffer2[length2] = STR('\0'); + + CHECK_EQUAL(length1, length2); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + + bool is_equal = std::equal(buffer1, + buffer1 + length1, + buffer2); CHECK(is_equal); } diff --git a/test/test_string_u32_external_buffer.cpp b/test/test_string_u32_external_buffer.cpp index b210efdd..a1f62f2e 100644 --- a/test/test_string_u32_external_buffer.cpp +++ b/test/test_string_u32_external_buffer.cpp @@ -3290,7 +3290,7 @@ namespace TEST_FIXTURE(SetupFixture, test_copy) { Compare_Text compare_text(initial_text.c_str()); - + TextBuffer buffer; Text text(initial_text.c_str(), buffer.data(), buffer.size()); @@ -3309,8 +3309,80 @@ namespace #endif bool is_equal = std::equal(buffer1, - buffer1 + length1, - buffer2); + buffer1 + length1, + buffer2); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_start_pos_too_large) + { + TextBuffer buffer; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + value_t buffer1[SIZE]; + + size_t length1 = text.copy(buffer1, 5, SIZE); + + CHECK_EQUAL(0U, length1); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_count_equals_npos) + { + Compare_Text compare_text(initial_text.c_str()); + + TextBuffer buffer; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + value_t buffer1[SIZE]; + value_t buffer2[SIZE]; + + size_t length1 = compare_text.copy(buffer1, Compare_Text::npos, 2); + buffer1[length1] = STR('\0'); + + size_t length2 = text.copy(buffer2, Text::npos, 2); + buffer2[length2] = STR('\0'); + + CHECK_EQUAL(length1, length2); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + + bool is_equal = std::equal(buffer1, + buffer1 + length1, + buffer2); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_count_too_large) + { + Compare_Text compare_text(initial_text.c_str()); + + TextBuffer buffer; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + value_t buffer1[SIZE]; + value_t buffer2[SIZE]; + + size_t length1 = compare_text.copy(buffer1, SIZE, 2); + buffer1[length1] = STR('\0'); + + size_t length2 = text.copy(buffer2, SIZE, 2); + buffer2[length2] = STR('\0'); + + CHECK_EQUAL(length1, length2); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + + bool is_equal = std::equal(buffer1, + buffer1 + length1, + buffer2); CHECK(is_equal); } diff --git a/test/test_string_wchar_t.cpp b/test/test_string_wchar_t.cpp index a6d0b7fb..3521b278 100644 --- a/test/test_string_wchar_t.cpp +++ b/test/test_string_wchar_t.cpp @@ -2995,8 +2995,75 @@ namespace #endif bool is_equal = std::equal(buffer1, - buffer1 + length1, - buffer2); + buffer1 + length1, + buffer2); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_start_pos_too_large) + { + Text text(initial_text.c_str()); + + value_t buffer1[SIZE]; + + size_t length1 = text.copy(buffer1, 5, SIZE); + + CHECK_EQUAL(0U, length1); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_count_equals_npos) + { + Compare_Text compare_text(initial_text.c_str()); + Text text(initial_text.c_str()); + + value_t buffer1[SIZE]; + value_t buffer2[SIZE]; + + size_t length1 = compare_text.copy(buffer1, Compare_Text::npos, 2); + buffer1[length1] = STR('\0'); + + size_t length2 = text.copy(buffer2, Text::npos, 2); + buffer2[length2] = STR('\0'); + + CHECK_EQUAL(length1, length2); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + + bool is_equal = std::equal(buffer1, + buffer1 + length1, + buffer2); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_count_too_large) + { + Compare_Text compare_text(initial_text.c_str()); + Text text(initial_text.c_str()); + + value_t buffer1[SIZE]; + value_t buffer2[SIZE]; + + size_t length1 = compare_text.copy(buffer1, SIZE, 2); + buffer1[length1] = STR('\0'); + + size_t length2 = text.copy(buffer2, SIZE, 2); + buffer2[length2] = STR('\0'); + + CHECK_EQUAL(length1, length2); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + + bool is_equal = std::equal(buffer1, + buffer1 + length1, + buffer2); CHECK(is_equal); } diff --git a/test/test_string_wchar_t_external_buffer.cpp b/test/test_string_wchar_t_external_buffer.cpp index f2fb7a70..1c736862 100644 --- a/test/test_string_wchar_t_external_buffer.cpp +++ b/test/test_string_wchar_t_external_buffer.cpp @@ -3290,7 +3290,7 @@ namespace TEST_FIXTURE(SetupFixture, test_copy) { Compare_Text compare_text(initial_text.c_str()); - + TextBuffer buffer; Text text(initial_text.c_str(), buffer.data(), buffer.size()); @@ -3309,8 +3309,80 @@ namespace #endif bool is_equal = std::equal(buffer1, - buffer1 + length1, - buffer2); + buffer1 + length1, + buffer2); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_start_pos_too_large) + { + TextBuffer buffer; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + value_t buffer1[SIZE]; + + size_t length1 = text.copy(buffer1, 5, SIZE); + + CHECK_EQUAL(0U, length1); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_count_equals_npos) + { + Compare_Text compare_text(initial_text.c_str()); + + TextBuffer buffer; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + value_t buffer1[SIZE]; + value_t buffer2[SIZE]; + + size_t length1 = compare_text.copy(buffer1, Compare_Text::npos, 2); + buffer1[length1] = STR('\0'); + + size_t length2 = text.copy(buffer2, Text::npos, 2); + buffer2[length2] = STR('\0'); + + CHECK_EQUAL(length1, length2); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + + bool is_equal = std::equal(buffer1, + buffer1 + length1, + buffer2); + CHECK(is_equal); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_copy_count_too_large) + { + Compare_Text compare_text(initial_text.c_str()); + + TextBuffer buffer; + Text text(initial_text.c_str(), buffer.data(), buffer.size()); + + value_t buffer1[SIZE]; + value_t buffer2[SIZE]; + + size_t length1 = compare_text.copy(buffer1, SIZE, 2); + buffer1[length1] = STR('\0'); + + size_t length2 = text.copy(buffer2, SIZE, 2); + buffer2[length2] = STR('\0'); + + CHECK_EQUAL(length1, length2); +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + CHECK(!text.is_truncated()); +#endif + + bool is_equal = std::equal(buffer1, + buffer1 + length1, + buffer2); CHECK(is_equal); }