From 2da99e81e641ef9befbf101e45bd0c6960cdb3c2 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 4 Aug 2022 15:31:09 +0100 Subject: [PATCH] Added missing char_traits unit tests and char_traits bug fixes --- include/etl/char_traits.h | 37 +++-- test/test_char_traits.cpp | 291 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 309 insertions(+), 19 deletions(-) create mode 100644 test/test_char_traits.cpp diff --git a/include/etl/char_traits.h b/include/etl/char_traits.h index 718b5421..3cf2ed45 100644 --- a/include/etl/char_traits.h +++ b/include/etl/char_traits.h @@ -130,7 +130,7 @@ namespace etl } //************************************************************************* - static char_type* assign(char_type* p, size_t n, char_type c) + static ETL_CONSTEXPR char_type* assign(char_type* p, size_t n, char_type c) { if (p != 0) { @@ -141,32 +141,32 @@ namespace etl } //************************************************************************* - static char_type* move(char_type* dest, const char_type* src, size_t count) + static ETL_CONSTEXPR char_type* move(char_type* dst, const char_type* src, size_t count) { - if ((dest < src) || (dest > (src + count))) + if ((dst < src) || (dst > (src + count))) { - etl::copy_n(src, src + count, dest); + etl::copy_n(src, count, dst); } else { - etl::copy_n(ETL_OR_STD::reverse_iterator(src + count), + etl::copy_n(ETL_OR_STD::reverse_iterator(src + count), count, - ETL_OR_STD::reverse_iterator(dest + count)); + ETL_OR_STD::reverse_iterator(dst + count)); } - return dest; + return dst; } //************************************************************************* - static char_type* copy(char_type* dest, const char_type* src, size_t count) + static ETL_CONSTEXPR char_type* copy(char_type* dst, const char_type* src, size_t count) { - etl::copy_n(src, src + count, dest); + etl::copy_n(src, count, dst); - return dest; + return dst; } //************************************************************************* - static int compare(const char_type* s1, const char_type* s2, size_t count) + static ETL_CONSTEXPR14 int compare(const char_type* s1, const char_type* s2, size_t count) { for (size_t i = 0UL; i < count; ++i) { @@ -187,7 +187,7 @@ namespace etl } //************************************************************************* - static const char_type* find(const char_type* p, size_t count, const char_type& ch) + static ETL_CONSTEXPR14 const char_type* find(const char_type* p, size_t count, const char_type& ch) { for (size_t i = 0UL; i < count; ++i) { @@ -203,42 +203,41 @@ namespace etl } //************************************************************************* - static char_type to_char_type(int_type c) + static ETL_CONSTEXPR char_type to_char_type(int_type c) { return static_cast(c); } //************************************************************************* - static int_type to_int_type(char_type c) + static ETL_CONSTEXPR int_type to_int_type(char_type c) { return static_cast(c); } //************************************************************************* - static bool eq_int_type(int_type c1, int_type c2) + static ETL_CONSTEXPR bool eq_int_type(int_type c1, int_type c2) { return (c1 == c2); } //************************************************************************* - static int_type eof() + static ETL_CONSTEXPR int_type eof() { return -1; } //************************************************************************* - static int_type not_eof(int_type e) + static ETL_CONSTEXPR int_type not_eof(int_type e) { return (e == eof()) ? eof() - 1 : e; } }; - //*************************************************************************** /// Alternative strlen for all character types. //*************************************************************************** template - size_t strlen(const T* t) + ETL_CONSTEXPR size_t strlen(const T* t) { return etl::char_traits::length(t); } diff --git a/test/test_char_traits.cpp b/test/test_char_traits.cpp new file mode 100644 index 00000000..fd517c62 --- /dev/null +++ b/test/test_char_traits.cpp @@ -0,0 +1,291 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2022 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/char_traits.h" + +namespace +{ + template + size_t length(const T* text) + { + size_t count = 0U; + + while (*text != 0U) + { + ++text; + ++count; + } + + return count; + } + + SUITE(test_char_traits) + { + //************************************************************************* + TEST(test_strlen) + { + char data1[etl::strlen("qwerty")]; + char data2[etl::strlen(L"qwerty")]; + char data3[etl::strlen(u"qwerty")]; + char data4[etl::strlen(U"qwerty")]; + + CHECK_EQUAL(6U, sizeof(data1)); + CHECK_EQUAL(6U, sizeof(data2)); + CHECK_EQUAL(6U, sizeof(data3)); + CHECK_EQUAL(6U, sizeof(data4)); + } + + //************************************************************************* + TEST(test_char_traits_char_template) + { + using char_traits = etl::char_traits; + using char_type = char_traits::char_type; + using int_type = char_traits::int_type; + + char_type r = 'A'; + char_type c = 'B'; + char_type src[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + char_type dst[etl::size(src)]; + char_type filled[] = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 }; + const char_type* p_src; + char_type* p_dst; + + char_traits::assign(r, c); + CHECK_EQUAL(r, 'B'); + + CHECK(char_traits::eq(1, 1)); + CHECK(!char_traits::eq(1, 2)); + CHECK(!char_traits::eq(2, 1)); + + CHECK(!char_traits::lt(1, 1)); + CHECK(char_traits::lt(1, 2)); + CHECK(!char_traits::lt(2, 1)); + + CHECK_EQUAL(length("ABCDEF"), char_traits::length("ABCDEF")); + + CHECK_EQUAL(0, char_traits::compare("ABCDEF", "ABCDEF", 6U)); + CHECK_EQUAL(-1, char_traits::compare("ABCDEE", "ABCDEF", 6U)); + CHECK_EQUAL(1, char_traits::compare("ABCDEF", "ABCDEE", 6U)); + + p_dst = char_traits::assign(dst, etl::size(dst), 9); + CHECK_ARRAY_EQUAL(filled, p_dst, etl::size(filled)); + + std::fill_n(dst, etl::size(dst), 0); + p_dst = char_traits::copy(dst, src, etl::size(src)); + CHECK_ARRAY_EQUAL(src, p_dst, etl::size(src)); + + std::fill_n(dst, etl::size(dst), 0); + p_dst = char_traits::move(dst, src, etl::size(src)); + CHECK_ARRAY_EQUAL(src, p_dst, etl::size(src)); + + p_src = char_traits::find(src, etl::size(src), 4); + CHECK_EQUAL(src[4], *p_src); + + CHECK_EQUAL(127, char_traits::to_char_type(int_type(127))); + CHECK_EQUAL(127, char_traits::to_int_type(char_type(127))); + + CHECK(!char_traits::eq_int_type(0, 1)); + CHECK(char_traits::eq_int_type(1, 1)); + + CHECK(int_type(char_traits::eof()) != char_traits::not_eof(char_traits::eof())); + CHECK(int_type(char_traits::eof() + 1) == char_traits::not_eof(char_traits::eof() + 1)); + } + + //************************************************************************* + TEST(test_char_traits_wchar_t_template) + { + using char_traits = etl::char_traits; + using char_type = char_traits::char_type; + using int_type = char_traits::int_type; + + char_type r = L'A'; + char_type c = L'B'; + char_type src[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + char_type dst[etl::size(src)]; + char_type filled[] = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 }; + const char_type* p_src; + char_type* p_dst; + + char_traits::assign(r, c); + CHECK_EQUAL(r, 'B'); + + CHECK(char_traits::eq(1, 1)); + CHECK(!char_traits::eq(1, 2)); + CHECK(!char_traits::eq(2, 1)); + + CHECK(!char_traits::lt(1, 1)); + CHECK(char_traits::lt(1, 2)); + CHECK(!char_traits::lt(2, 1)); + + CHECK_EQUAL(length(L"ABCDEF"), char_traits::length(L"ABCDEF")); + + CHECK_EQUAL(0, char_traits::compare(L"ABCDEF", L"ABCDEF", 6U)); + CHECK_EQUAL(-1, char_traits::compare(L"ABCDEE", L"ABCDEF", 6U)); + CHECK_EQUAL(1, char_traits::compare(L"ABCDEF", L"ABCDEE", 6U)); + + p_dst = char_traits::assign(dst, etl::size(dst), 9); + CHECK_ARRAY_EQUAL(filled, p_dst, etl::size(filled)); + + std::fill_n(dst, etl::size(dst), 0); + p_dst = char_traits::copy(dst, src, etl::size(src)); + CHECK_ARRAY_EQUAL(src, p_dst, etl::size(src)); + + std::fill_n(dst, etl::size(dst), 0); + p_dst = char_traits::move(dst, src, etl::size(src)); + CHECK_ARRAY_EQUAL(src, p_dst, etl::size(src)); + + p_src = char_traits::find(src, etl::size(src), 4); + CHECK_EQUAL(src[4], *p_src); + + CHECK_EQUAL(127, char_traits::to_char_type(int_type(127))); + CHECK_EQUAL(127, char_traits::to_int_type(char_type(127))); + + CHECK(!char_traits::eq_int_type(0, 1)); + CHECK(char_traits::eq_int_type(1, 1)); + + CHECK(int_type(char_traits::eof()) != char_traits::not_eof(char_traits::eof())); + CHECK(int_type(char_traits::eof() + 1) == char_traits::not_eof(char_traits::eof() + 1)); + } + + //************************************************************************* + TEST(test_char_traits_char16_t_template) + { + using char_traits = etl::char_traits; + using char_type = char_traits::char_type; + using int_type = char_traits::int_type; + + char_type r = u'A'; + char_type c = u'B'; + char_type src[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + char_type dst[etl::size(src)]; + char_type filled[] = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 }; + const char_type* p_src; + char_type* p_dst; + + char_traits::assign(r, c); + CHECK_EQUAL(r, 'B'); + + CHECK(char_traits::eq(1, 1)); + CHECK(!char_traits::eq(1, 2)); + CHECK(!char_traits::eq(2, 1)); + + CHECK(!char_traits::lt(1, 1)); + CHECK(char_traits::lt(1, 2)); + CHECK(!char_traits::lt(2, 1)); + + CHECK_EQUAL(length(u"ABCDEF"), char_traits::length(u"ABCDEF")); + + CHECK_EQUAL(0, char_traits::compare(u"ABCDEF", u"ABCDEF", 6U)); + CHECK_EQUAL(-1, char_traits::compare(u"ABCDEE", u"ABCDEF", 6U)); + CHECK_EQUAL(1, char_traits::compare(u"ABCDEF", u"ABCDEE", 6U)); + + p_dst = char_traits::assign(dst, etl::size(dst), 9); + CHECK_ARRAY_EQUAL(filled, p_dst, etl::size(filled)); + + std::fill_n(dst, etl::size(dst), 0); + p_dst = char_traits::copy(dst, src, etl::size(src)); + CHECK_ARRAY_EQUAL(src, p_dst, etl::size(src)); + + std::fill_n(dst, etl::size(dst), 0); + p_dst = char_traits::move(dst, src, etl::size(src)); + CHECK_ARRAY_EQUAL(src, p_dst, etl::size(src)); + + p_src = char_traits::find(src, etl::size(src), 4); + CHECK_EQUAL(src[4], *p_src); + + CHECK_EQUAL(127, char_traits::to_char_type(int_type(127))); + CHECK_EQUAL(127, char_traits::to_int_type(char_type(127))); + + CHECK(!char_traits::eq_int_type(0, 1)); + CHECK(char_traits::eq_int_type(1, 1)); + + CHECK(int_type(char_traits::eof()) != char_traits::not_eof(char_traits::eof())); + CHECK(int_type(char_traits::eof() + 1) == char_traits::not_eof(char_traits::eof() + 1)); + } + + //************************************************************************* + TEST(test_char_traits_char32_t_template) + { + using char_traits = etl::char_traits; + using char_type = char_traits::char_type; + using int_type = char_traits::int_type; + + char_type r = U'A'; + char_type c = U'B'; + char_type src[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 }; + char_type dst[etl::size(src)]; + char_type filled[] = { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 }; + const char_type* p_src; + char_type* p_dst; + + char_traits::assign(r, c); + CHECK_EQUAL(r, 'B'); + + CHECK(char_traits::eq(1, 1)); + CHECK(!char_traits::eq(1, 2)); + CHECK(!char_traits::eq(2, 1)); + + CHECK(!char_traits::lt(1, 1)); + CHECK(char_traits::lt(1, 2)); + CHECK(!char_traits::lt(2, 1)); + + CHECK_EQUAL(length(U"ABCDEF"), char_traits::length(U"ABCDEF")); + + CHECK_EQUAL(0, char_traits::compare(U"ABCDEF", U"ABCDEF", 6U)); + CHECK_EQUAL(-1, char_traits::compare(U"ABCDEE", U"ABCDEF", 6U)); + CHECK_EQUAL(1, char_traits::compare(U"ABCDEF", U"ABCDEE", 6U)); + + p_dst = char_traits::assign(dst, etl::size(dst), 9); + CHECK_ARRAY_EQUAL(filled, p_dst, etl::size(filled)); + + std::fill_n(dst, etl::size(dst), 0); + p_dst = char_traits::copy(dst, src, etl::size(src)); + CHECK_ARRAY_EQUAL(src, p_dst, etl::size(src)); + + std::fill_n(dst, etl::size(dst), 0); + p_dst = char_traits::move(dst, src, etl::size(src)); + CHECK_ARRAY_EQUAL(src, p_dst, etl::size(src)); + + p_src = char_traits::find(src, etl::size(src), 4); + CHECK_EQUAL(src[4], *p_src); + + CHECK_EQUAL(127, char_traits::to_char_type(int_type(127))); + CHECK_EQUAL(127, char_traits::to_int_type(char_type(127))); + + CHECK(!char_traits::eq_int_type(0, 1)); + CHECK(char_traits::eq_int_type(1, 1)); + + CHECK(int_type(char_traits::eof()) != char_traits::not_eof(char_traits::eof())); + CHECK(int_type(char_traits::eof() + 1) == char_traits::not_eof(char_traits::eof() + 1)); + } + }; +}