diff --git a/include/etl/algorithm.h b/include/etl/algorithm.h index 5a3bd4ff..bff512b8 100644 --- a/include/etl/algorithm.h +++ b/include/etl/algorithm.h @@ -104,8 +104,15 @@ namespace etl //*************************************************************************** // copy - - // Other iterator +#if ETL_USING_STL && !(ETL_CPP20_NOT_SUPPORTED && defined(ETL_FORCE_CONSTEXPR_ALGORITHMS)) + // Use the STL implementation + template + ETL_CONSTEXPR20 TIterator2 copy(TIterator1 sb, TIterator1 se, TIterator2 db) + { + return std::copy(sb, se, db); + } +#else + // Non-pointer template ETL_CONSTEXPR14 typename etl::enable_if ETL_CONSTEXPR14 typename etl::enable_if ETL_CONSTEXPR14 typename etl::enable_if + ETL_CONSTEXPR20 TIterator2 reverse_copy(TIterator1 sb, TIterator1 se, TIterator2 db) + { + return std::reverse_copy(sb, se, db); + } +#else template ETL_CONSTEXPR14 TIterator2 reverse_copy(TIterator1 sb, TIterator1 se, TIterator2 db) @@ -185,11 +200,19 @@ namespace etl return db; } +#endif // ETL_USING_STL && !(ETL_CPP20_NOT_SUPPORTED && defined(ETL_FORCE_CONSTEXPR_ALGORITHMS)) //*************************************************************************** // copy_n - - // Normal iterator +#if ETL_USING_STL && ETL_CPP11_SUPPORTED && !(ETL_CPP20_NOT_SUPPORTED && defined(ETL_FORCE_CONSTEXPR_ALGORITHMS)) + // Use the STL implementation + template + ETL_CONSTEXPR20 TIterator2 copy_n(TIterator1 sb, TSize count, TIterator2 db) + { + return std::copy_n(sb, count, db); + } +#else + // Non-pointer template ETL_CONSTEXPR14 typename etl::enable_if ETL_CONSTEXPR14 typename etl::enable_if::value_type value_t; - return TIterator2(__builtin_memmove(db, sb, sizeof(value_t) * count)) + count; + return TIterator2(__builtin_memcpy(db, sb, sizeof(value_t) * count)) + count; } #elif defined(ETL_FORCE_CONSTEXPR_ALGORITHMS) template @@ -248,13 +271,36 @@ namespace etl { typedef typename etl::iterator_traits::value_type value_t; - return TIterator2(memmove(db, sb, sizeof(value_t) * count)) + count; + return TIterator2(memcpy(db, sb, sizeof(value_t) * count)) + count; } #endif +#endif // ETL_USING_STL && !(ETL_CPP20_NOT_SUPPORTED && defined(ETL_FORCE_CONSTEXPR_ALGORITHMS)) -#if ETL_NOT_USING_STL //*************************************************************************** // copy_backward +#if ETL_USING_STL && !(ETL_CPP20_NOT_SUPPORTED && defined(ETL_FORCE_CONSTEXPR_ALGORITHMS)) + template + ETL_CONSTEXPR20 TIterator2 copy_backward(TIterator1 sb, TIterator1 se, TIterator2 de) + { + return std::copy_backward(sb, se, de); + } +#else + // Non-pointer + template + ETL_CONSTEXPR14 + typename etl::enable_if::type + copy_backward(TIterator1 sb, TIterator1 se, TIterator2 de) + { + while (se != sb) + { + *(--de) = *(--se); + } + + return de; + } + // Pointer #if ETL_USE_BUILTIN_MEMMOVE template @@ -284,36 +330,26 @@ namespace etl return TIterator2(memmove(de - length, sb, sizeof(value_t) * length)); } #endif +#endif // ETL_USING_STL && !(ETL_CPP20_NOT_SUPPORTED && defined(ETL_FORCE_CONSTEXPR_ALGORITHMS)) - // Other iterator - template - ETL_CONSTEXPR14 - typename etl::enable_if::type - copy_backward(TIterator1 sb, TIterator1 se, TIterator2 de) - { - while (se != sb) - { - *(--de) = *(--se); - } - - return de; - } -#else - //*************************************************************************** - // copy_backward - template - TIterator2 copy_backward(TIterator1 sb, TIterator1 se, TIterator2 de) - { - return std::copy_backward(sb, se, de); - } -#endif - -#if ETL_CPP11_SUPPORTED -#if ETL_NOT_USING_STL //*************************************************************************** // move +#if ETL_USING_STL && !(ETL_CPP20_NOT_SUPPORTED && defined(ETL_FORCE_CONSTEXPR_ALGORITHMS)) +#if ETL_CPP11_SUPPORTED + template + ETL_CONSTEXPR20 TIterator2 move(TIterator1 sb, TIterator1 se, TIterator2 db) + { + return std::move(sb, se, db); + } +#else + template + TIterator2 move(TIterator1 sb, TIterator1 se, TIterator2 db) + { + // Move not supported. Defer to copy. + return std::copy(sb, se, db); + } +#endif +#else // non-pointer or not trivially copyable template ETL_CONSTEXPR14 @@ -362,31 +398,27 @@ namespace etl return TIterator2(memmove(db, sb, sizeof(value_t) * count)) + count; } #endif -#else - //*************************************************************************** - // move - template - ETL_CONSTEXPR20 TIterator2 move(TIterator1 sb, TIterator1 se, TIterator2 db) - { - return std::move(sb, se, db); - } -#endif -#else - // C++03 - //*************************************************************************** - // move - template - TIterator2 move(TIterator1 sb, TIterator1 se, TIterator2 db) - { - // Move not supported. Defer to copy. - return etl::copy(sb, se, db); - } -#endif +#endif // ETL_USING_STL && !(ETL_CPP20_NOT_SUPPORTED && defined(ETL_FORCE_CONSTEXPR_ALGORITHMS)) -#if ETL_CPP11_SUPPORTED -#if ETL_NOT_USING_STL //*************************************************************************** // move_backward +#if ETL_USING_STL && !(ETL_CPP20_NOT_SUPPORTED && defined(ETL_FORCE_CONSTEXPR_ALGORITHMS)) +#if ETL_CPP11_SUPPORTED + template + ETL_CONSTEXPR20 + TIterator2 move_backward(TIterator1 sb, TIterator1 se, TIterator2 de) + { + return std::move_backward(sb, se, de); + } +#else + template + TIterator2 move_backward(TIterator1 sb, TIterator1 se, TIterator2 de) + { + // Move not supported. Defer to copy_backward. + return std::copy_backward(sb, se, de); + } +#endif +#else // non-pointer, non-pod template ETL_CONSTEXPR14 @@ -437,33 +469,13 @@ namespace etl return TIterator2(memmove(db, sb, sizeof(value_t) * count)) + count; } #endif -#else - //*************************************************************************** - // move_backward - template - ETL_CONSTEXPR20 - TIterator2 move_backward(TIterator1 sb, TIterator1 se, TIterator2 de) - { - return std::move_backward(sb, se, de); - } -#endif -#else - // C++03 - //*************************************************************************** - // move_backward - template - TIterator2 move_backward(TIterator1 sb, TIterator1 se, TIterator2 de) - { - // Move not supported. Defer to copy_backward. - return ETL_OR_STD::copy_backward(sb, se, de); - } -#endif +#endif // ETL_USING_STL && !(ETL_CPP20_NOT_SUPPORTED && defined(ETL_FORCE_CONSTEXPR_ALGORITHMS)) -#if ETL_NOT_USING_STL //*************************************************************************** // reverse // Pointers template + ETL_CONSTEXPR14 typename etl::enable_if::value, void>::type reverse(TIterator b, TIterator e) { @@ -477,8 +489,9 @@ namespace etl } } - // Other + // Non-pointers template + ETL_CONSTEXPR14 typename etl::enable_if::value, void>::type reverse(TIterator b, TIterator e) { @@ -487,15 +500,6 @@ namespace etl etl::iter_swap(b++, e); } } -#else - //*************************************************************************** - // reverse - template - void reverse(TIterator b, TIterator e) - { - std::reverse(b, e); - } -#endif //*************************************************************************** // lower_bound @@ -644,6 +648,13 @@ namespace etl //*************************************************************************** // fill +#if ETL_USING_STL && !(ETL_CPP20_NOT_SUPPORTED && defined(ETL_FORCE_CONSTEXPR_ALGORITHMS)) + template + ETL_CONSTEXPR20 void fill(TIterator first, TIterator last, const TValue& value) + { + std::fill(first, last, value); + } +#else template ETL_CONSTEXPR14 typename etl::enable_if::type @@ -682,9 +693,17 @@ namespace etl memset(first, value, last - first); } #endif +#endif // ETL_USING_STL && !(ETL_CPP20_NOT_SUPPORTED && defined(ETL_FORCE_CONSTEXPR_ALGORITHMS)) //*************************************************************************** // fill_n +#if ETL_USING_STL && !(ETL_CPP20_NOT_SUPPORTED && defined(ETL_FORCE_CONSTEXPR_ALGORITHMS)) + template + ETL_CONSTEXPR20 TIterator fill_n(TIterator first, TSize count, const TValue& value) + { + return std::fill_n(first, count, value); + } +#else template ETL_CONSTEXPR14 typename etl::enable_if::type @@ -729,6 +748,7 @@ namespace etl return TIterator(memset(first, value, count)); } #endif +#endif // ETL_USING_STL && !(ETL_CPP20_NOT_SUPPORTED && defined(ETL_FORCE_CONSTEXPR_ALGORITHMS)) //*************************************************************************** // count @@ -777,6 +797,23 @@ namespace etl //*************************************************************************** // equal +#if ETL_USING_STL && !(ETL_CPP20_NOT_SUPPORTED && defined(ETL_FORCE_CONSTEXPR_ALGORITHMS)) + template + ETL_NODISCARD + ETL_CONSTEXPR20 + bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2) + { + return std::equal(first1, last1, first2); + } + + template + ETL_NODISCARD + ETL_CONSTEXPR20 + bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2, TPredicate predicate) + { + return std::equal(first1, last1, first2, predicate); + } +#else // Not pointer types or not trivially copyable. template ETL_NODISCARD @@ -814,7 +851,7 @@ namespace etl return (__builtin_memcmp(first1, first2, sizeof(value_t) * (last1 - first1)) == 0); } -#elif ETL_FORCE_CONSTEXPR_ALGORITHMS +#elif defined(ETL_FORCE_CONSTEXPR_ALGORITHMS) // Forced constexpr. // Not pointer types or not trivially copyable. template @@ -852,7 +889,24 @@ namespace etl } #endif - // + // Predicate + template + ETL_NODISCARD + ETL_CONSTEXPR14 + bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2, TPredicate predicate) + { + while (first1 != last1) + { + if (!predicate(*first1++, *first2++)) + { + return false; + } + } + + return true; + } + + // Four parameter template ETL_NODISCARD ETL_CONSTEXPR14 @@ -869,6 +923,24 @@ namespace etl return (first1 == last1) && (first2 == last2); } + // Four parameter, Predicate + template + ETL_NODISCARD + ETL_CONSTEXPR14 + bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2, TIterator2 last2, TPredicate predicate) + { + while ((first1 != last1) && (first2 != last2)) + { + if (!predicate(*first1++ , *first2++)) + { + return false; + } + } + + return (first1 == last1) && (first2 == last2); + } +#endif //ETL_USING_STL && !(ETL_CPP20_NOT_SUPPORTED && defined(ETL_FORCE_CONSTEXPR_ALGORITHMS)) + //*************************************************************************** // lexicographical_compare template diff --git a/include/etl/memory.h b/include/etl/memory.h index bfcdc70c..e1c4fdeb 100644 --- a/include/etl/memory.h +++ b/include/etl/memory.h @@ -938,6 +938,48 @@ namespace etl } #endif +#if ETL_NOT_USING_STL || ETL_CPP20_NOT_SUPPORTED +#if ETL_CPP11_SUPPORTED + //***************************************************************************** + /// Constructs an item at address p with value constructed from 'args'. + /// https://en.cppreference.com/w/cpp/memory/construct_at + ///\ingroup memory + //***************************************************************************** + template + ETL_CONSTEXPR T* construct_at(T* p, TArgs&&... args) + { + return ::new (const_cast(static_cast(p))) T(etl::forward(args)...); + } +#else + //***************************************************************************** + /// Constructs an item at address p. + /// https://en.cppreference.com/w/cpp/memory/construct_at + ///\ingroup memory + //***************************************************************************** + template + ETL_CONSTEXPR T* construct_at(T* p) + { + return ::new (const_cast(static_cast(p))) T(); + } + //***************************************************************************** + /// Constructs an item at address p with value 'arg'. + /// https://en.cppreference.com/w/cpp/memory/construct_at + ///\ingroup memory + //***************************************************************************** + template + ETL_CONSTEXPR T* construct_at(T* p, const TArg& arg) + { + return ::new (const_cast(static_cast(p))) T(arg); + } +#endif +#else + template + ETL_CONSTEXPR20 T* construct_at(T* p, TArgs&&... args) + { + return std::construct_at(o, etl::forward(args)...); + } +#endif + #if ETL_NOT_USING_STL || ETL_CPP17_NOT_SUPPORTED //***************************************************************************** /// Destroys an item at address p. diff --git a/include/etl/platform.h b/include/etl/platform.h index 030b8dc0..26ce60f1 100644 --- a/include/etl/platform.h +++ b/include/etl/platform.h @@ -229,14 +229,6 @@ SOFTWARE. #define ETL_NO_UNIQUE_ADDRESS #endif -#if !defined(ETL_USING_INITIALIZER_LIST) - #if ETL_CPP11_SUPPORTED && ETL_USING_STL && ETL_NOT_USING_STLPORT - #define ETL_USING_INITIALIZER_LIST 1 - #else - #define ETL_USING_INITIALIZER_LIST 0 - #endif -#endif - //************************************* // Determine if the ETL can use std::array #if !defined(ETL_HAS_STD_ARRAY) @@ -265,6 +257,20 @@ SOFTWARE. #endif #endif +//************************************* +// Check for availability of certain builtins +#if !defined(ETL_USING_INITIALIZER_LIST) + #if ETL_CPP11_SUPPORTED && ETL_USING_STL && ETL_NOT_USING_STLPORT + #define ETL_USING_INITIALIZER_LIST 1 + #else + #define ETL_USING_INITIALIZER_LIST 0 + #endif +#endif + +//************************************* +// Check for availability of certain builtins +#include "profiles/determine_builtin_support.h" + //************************************* // Sort out namespaces for STL/No STL options. #include "private/choose_namespace.h" diff --git a/include/etl/profiles/determine_builtin_support.h b/include/etl/profiles/determine_builtin_support.h index f04ad28b..cda30b0a 100644 --- a/include/etl/profiles/determine_builtin_support.h +++ b/include/etl/profiles/determine_builtin_support.h @@ -36,6 +36,10 @@ SOFTWARE. #define ETL_USE_BUILTIN_MEMCMP 1 #endif + #if !defined(ETL_USE_BUILTIN_MEMCPY) + #define ETL_USE_BUILTIN_MEMCPY 1 + #endif + #if !defined(ETL_USE_BUILTIN_MEMMOVE) #define ETL_USE_BUILTIN_MEMMOVE 1 #endif @@ -72,6 +76,10 @@ SOFTWARE. #define ETL_USE_BUILTIN_MEMCMP __has_builtin(__builtin_memcmp) #endif +#if !defined(ETL_USE_BUILTIN_MEMCPY) + #define ETL_USE_BUILTIN_MEMCPY __has_builtin(__builtin_memcpy) +#endif + #if !defined(ETL_USE_BUILTIN_MEMMOVE) #define ETL_USE_BUILTIN_MEMMOVE __has_builtin(__builtin_memmove) #endif @@ -104,6 +112,10 @@ SOFTWARE. #define ETL_USE_BUILTIN_MEMCMP 0 #endif + #if !defined(ETL_USE_BUILTIN_MEMCPY) + #define ETL_USE_BUILTIN_MEMCPY 0 + #endif + #if !defined(ETL_USE_BUILTIN_MEMMOVE) #define ETL_USE_BUILTIN_MEMMOVE 0 #endif diff --git a/test/etl_profile.h b/test/etl_profile.h index 230a65db..238e5ba6 100644 --- a/test/etl_profile.h +++ b/test/etl_profile.h @@ -137,7 +137,7 @@ SOFTWARE. #define ETL_TARGET_OS_GENERIC #endif -#if ETL_CPP20_NOT_SUPPORTED || !defined(ETL_NO_STL) +#if !((ETL_CPP20_SUPPORTED && ETL_USING_STL) || defined(__BYTE_ORDER__)) #define ETL_ENDIAN_NATIVE 0 #endif diff --git a/test/test_memory.cpp b/test/test_memory.cpp index 2c0a52bf..e6fdbfd4 100644 --- a/test/test_memory.cpp +++ b/test/test_memory.cpp @@ -227,6 +227,32 @@ namespace CHECK_EQUAL(0U, count); } + //************************************************************************* + TEST(test_construct_destroy_trivial) + { + char n[sizeof(trivial_t)]; + trivial_t* pn = reinterpret_cast(n); + + // Non count. + std::fill(std::begin(n), std::end(n), 0xFFU); + etl::construct_at(pn); + CHECK_EQUAL(0UL, *pn); + etl::destroy_at(pn); + CHECK_EQUAL(0UL, *pn); + + std::fill(std::begin(n), std::end(n), 0xFFU); + etl::construct_at(pn); + CHECK_EQUAL(0x00000000UL, *pn); + etl::destroy_at(pn); + CHECK_EQUAL(0x00000000UL, *pn); + + std::fill(std::begin(n), std::end(n), 0xFFU); + etl::construct_at(pn, test_item_trivial); + CHECK_EQUAL(test_item_trivial, *pn); + etl::destroy_at(pn); + CHECK_EQUAL(test_item_trivial, *pn); + } + //************************************************************************* TEST(test_uninitialized_fill_n_trivial) { diff --git a/test/test_string_view.cpp b/test/test_string_view.cpp index 5b925d8c..60d865b4 100644 --- a/test/test_string_view.cpp +++ b/test/test_string_view.cpp @@ -57,31 +57,17 @@ namespace char ctext[] = { 'H', 'e', 'l', 'l', 'o', ' ', 'W', 'o', 'r', 'l', 'd', '\0' }; char* pctext = ctext; - constexpr etl::string_view string_view_assign() - { - etl::string_view a; - - const char* text = "Hello"; - a = etl::string_view(text, text + 5); - - if (a.ends_with("o")) - { - return a; - } - else - { - return etl::string_view("World"); - } - } - SUITE(test_string_view) { //************************************************************************* TEST(test_constexpr) { -#if ETL_USE_BUILTIN_MEMMOVE - constexpr etl::string_view b(string_view_assign()); -#endif + constexpr const char* text = "Hello"; + + constexpr etl::string_view view1(text); + constexpr etl::string_view view2(text, 5U); + constexpr etl::string_view view3(text, text + 5U); + constexpr etl::string_view view4(view3); } //************************************************************************* diff --git a/test/vs2019/etl.vcxproj b/test/vs2019/etl.vcxproj index 2bc2f90c..5cebdba2 100644 --- a/test/vs2019/etl.vcxproj +++ b/test/vs2019/etl.vcxproj @@ -2085,6 +2085,7 @@ + @@ -9572,4 +9573,4 @@ - + \ No newline at end of file diff --git a/test/vs2019/etl.vcxproj.filters b/test/vs2019/etl.vcxproj.filters index 33fbf35c..71af5294 100644 --- a/test/vs2019/etl.vcxproj.filters +++ b/test/vs2019/etl.vcxproj.filters @@ -1248,6 +1248,9 @@ Tests\Test Support + + ETL\Profiles + @@ -2789,9 +2792,6 @@ Tests\Algorithms - - Tests\Algorithms - Tests\Algorithms @@ -3176,6 +3176,9 @@ Tests + + Tests\Memory & Iterators +