diff --git a/include/etl/algorithm.h b/include/etl/algorithm.h index 7773ac28..4d6ac1c4 100644 --- a/include/etl/algorithm.h +++ b/include/etl/algorithm.h @@ -1727,6 +1727,90 @@ namespace etl return etl::is_sorted_until(begin, end, compare) == end; } + //*************************************************************************** + /// is_unique_sorted_until + ///\ingroup algorithm + //*************************************************************************** + template + ETL_NODISCARD + ETL_CONSTEXPR14 + TIterator is_unique_sorted_until(TIterator begin, + TIterator end, + TCompare compare) + { + if (begin != end) + { + TIterator next = begin; + + while (++next != end) + { + if (!compare(*begin, *next)) + { + return next; + } + + ++begin; + } + } + + return end; + } + + //*************************************************************************** + /// is_unique_sorted_until + ///\ingroup algorithm + //*************************************************************************** + template + ETL_NODISCARD + ETL_CONSTEXPR14 + TIterator is_unique_sorted_until(TIterator begin, + TIterator end) + { + if (begin != end) + { + TIterator next = begin; + + while (++next != end) + { + if (!(*begin < *next)) + { + return next; + } + + ++begin; + } + } + + return end; + } + + //*************************************************************************** + /// is_unique_sorted + ///\ingroup algorithm + //*************************************************************************** + template + ETL_NODISCARD + ETL_CONSTEXPR14 + bool is_unique_sorted(TIterator begin, + TIterator end) + { + return etl::is_unique_sorted_until(begin, end) == end; + } + + //*************************************************************************** + /// is_unique_sorted + ///\ingroup algorithm + //*************************************************************************** + template + ETL_NODISCARD + ETL_CONSTEXPR14 + bool is_unique_sorted(TIterator begin, + TIterator end, + TCompare compare) + { + return etl::is_unique_sorted_until(begin, end, compare) == end; + } + //*************************************************************************** /// find_if_not ///\ingroup algorithm diff --git a/include/etl/const_map.h b/include/etl/const_map.h new file mode 100644 index 00000000..f8db3bc7 --- /dev/null +++ b/include/etl/const_map.h @@ -0,0 +1,434 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 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. +******************************************************************************/ + +#ifndef ETL_CONST_MAP_INCLUDED +#define ETL_CONST_MAP_INCLUDED + +#include "platform.h" +#include "algorithm.h" +#include "type_traits.h" +#include "functional.h" +#include "initializer_list.h" +#include "nth_type.h" + +//#include "private/minmax_push.h" +#include "private/comparator_is_transparent.h" + +///\defgroup const_map const_map +///\ingroup containers + +namespace etl +{ + template > + class const_map + { + public: + + using key_type = TKey; + using value_type = ETL_OR_STD::pair; + using mapped_type = TMapped ; + using key_compare_type = TKeyCompare; + using reference = const value_type&; + using const_reference = const value_type&; + using rvalue_reference = value_type&&; + using pointer = const value_type*; + using const_pointer = const value_type*; + using iterator = const value_type*; + using const_iterator = const value_type*; + using size_type = size_t; + + /// Defines the parameter types + using const_key_reference = const key_type&; + using rvalue_key_reference = key_type&&; + using const_mapped_reference = const mapped_type&; + + private: + + //********************************************************************* + /// How to compare elements and keys. + //********************************************************************* + class Compare + { + public: + + // Compare two value types. + ETL_CONSTEXPR14 bool operator ()(const value_type& element1, const value_type& element2) const ETL_NOEXCEPT + { + return key_compare(element1.first, element2.first); + } + + ETL_CONSTEXPR14 bool operator ()(const value_type& element, const_key_reference key) const ETL_NOEXCEPT + { + return key_compare(element.first, key); + } + + template ::value, int> = 0> + ETL_CONSTEXPR14 bool operator ()(const value_type& element, const K& key) const ETL_NOEXCEPT + { + return key_compare(element.first, key); + } + + ETL_CONSTEXPR14 bool operator ()(const_key_reference key, const value_type& element) const ETL_NOEXCEPT + { + return key_compare(key, element.first); + } + + template ::value, int> = 0> + ETL_CONSTEXPR14 bool operator ()(const K& key, const value_type& element) const ETL_NOEXCEPT + { + return key_compare(element.first, key); + } + + key_compare_type key_compare; + }; + + public: + + //************************************************************************* + ///\brief Construct a const_map from a variadic list of elements. + /// Static asserts if the element type is not constructible. + /// Static asserts if the elements are not of type value_type. + /// Static asserts if the number of elements is greater than the capacity of the const_map. + //************************************************************************* + template + ETL_CONSTEXPR14 explicit const_map(TElements&&... elements) ETL_NOEXCEPT + : element_list{etl::forward(elements)...} + , element_list_end{element_list + sizeof...(elements)} + { + static_assert((etl::is_default_constructible::value), "value_type must be default constructible"); + static_assert((etl::are_all_same...>::value), "All elements must be value_type"); + static_assert(sizeof...(elements) <= Size, "Number of elements exceeds capacity"); + } + + //************************************************************************* + /// Check that the elements are valid for a map. + /// The elements must be sorted and contain no duplicates. + /// \return true if the elements are valid for the map. + //************************************************************************* + ETL_CONSTEXPR14 bool is_valid() const ETL_NOEXCEPT + { + return etl::is_unique_sorted(begin(), end(), compare); + } + + //************************************************************************* + ///\brief Returns a const_iterator to the beginning of the map. + //************************************************************************* + ETL_CONSTEXPR14 const_iterator begin() const ETL_NOEXCEPT + { + return element_list; + } + + //************************************************************************* + ///\brief Returns a const_iterator to the beginning of the map. + //************************************************************************* + ETL_CONSTEXPR14 const_iterator cbegin() const ETL_NOEXCEPT + { + return element_list; + } + + //************************************************************************* + ///\brief Returns a const_iterator to the end of the map. + //************************************************************************* + ETL_CONSTEXPR14 const_iterator end() const ETL_NOEXCEPT + { + return element_list_end; + } + + //************************************************************************* + ///\brief Returns a const_iterator to the end of the map. + //************************************************************************* + ETL_CONSTEXPR14 const_iterator cend() const ETL_NOEXCEPT + { + return element_list_end; + } + + //************************************************************************* + ///\brief Returns a const_pointer to the beginning of the map. + //************************************************************************* + ETL_CONSTEXPR14 const_pointer data() const ETL_NOEXCEPT + { + return element_list; + } + + //************************************************************************* + ///\brief Index operator. + ///\return A const_mapped_reference to the mapped value at the index. + /// Undefined behaviour if the key is not in the map. + //************************************************************************* + ETL_CONSTEXPR14 const_mapped_reference operator[](const_key_reference key) const ETL_NOEXCEPT + { + const_iterator itr = find(key); + + return itr->second; + } + + //************************************************************************* + ///\brief Key index operator. + /// Enabled for transparent comparators. + ///\return A const_mapped_reference to the mapped value at the key index. + /// Undefined behaviour if the key is not in the map. + //************************************************************************* + template ::value, int> = 0> + ETL_CONSTEXPR14 const_mapped_reference operator[](const K& key) const ETL_NOEXCEPT + { + const_iterator itr = find(key); + + return itr->second; + } + + //************************************************************************* + ///\brief Gets the mapped value at the key index. + ///\return A const_mapped_reference to the mapped value at the index. + /// Undefined behaviour if the key is not in the map. + //************************************************************************* + ETL_CONSTEXPR14 const_mapped_reference at(const_key_reference key) const ETL_NOEXCEPT + { + const_iterator itr = find(key); + + return itr->second; + } + + //************************************************************************* + template ::value, int> = 0> + ETL_CONSTEXPR14 const_mapped_reference at(const K& key) const ETL_NOEXCEPT + { + const_iterator itr = find(key); + + return itr->second; + } + + //************************************************************************* + ETL_CONSTEXPR14 const_iterator find(const_key_reference key) const ETL_NOEXCEPT + { + iterator itr = lower_bound(key); + + if (itr != end()) + { + if (keys_are_equal(itr->first, key)) + { + return itr; + } + else + { + return end(); + } + } + + return end(); + + } + + //************************************************************************* + template ::value, int> = 0> + ETL_CONSTEXPR14 const_iterator find(const K& key) const ETL_NOEXCEPT + { + iterator itr = lower_bound(key); + + if (itr != end()) + { + if (keys_are_equal(itr->first, key)) + { + return itr; + } + else + { + return end(); + } + } + + return end(); + } + + //************************************************************************* + ETL_CONSTEXPR14 bool contains(const_key_reference key) const ETL_NOEXCEPT + { + return find(key) != end(); + } + + //************************************************************************* + template ::value, int> = 0> + ETL_CONSTEXPR14 bool contains(const K& key) const ETL_NOEXCEPT + { + return find(key) != end(); + } + + //************************************************************************* + ETL_CONSTEXPR14 size_type count(const_key_reference key) const ETL_NOEXCEPT + { + return contains(key) ? 1 : 0; + } + + //************************************************************************* + template ::value, int> = 0> + ETL_CONSTEXPR14 size_type count(const K& key) const ETL_NOEXCEPT + { + return contains(key) ? 1 : 0; + } + + //************************************************************************* + ETL_CONSTEXPR14 ETL_OR_STD::pair equal_range(const_key_reference key) const ETL_NOEXCEPT + { + return etl::equal_range(begin(), end(), key, compare); + } + + //************************************************************************* + template ::value, int> = 0> + ETL_CONSTEXPR14 ETL_OR_STD::pair equal_range(const K& key) const ETL_NOEXCEPT + { + return etl::equal_range(begin(), end(), key, compare); + } + + //************************************************************************* + ETL_CONSTEXPR14 const_iterator lower_bound(const_key_reference key) const ETL_NOEXCEPT + { + const_iterator itr = etl::lower_bound(begin(), end(), key, compare); + + if ((itr != end()) && keys_are_equal(key, itr->first)) + { + return itr; + } + else + { + return end(); + } + } + + //************************************************************************* + template ::value, int> = 0> + ETL_CONSTEXPR14 const_iterator lower_bound(const K& key) const ETL_NOEXCEPT + { + const_iterator itr = etl::lower_bound(begin(), end(), key, compare); + + if ((itr != end()) && keys_are_equal(key, itr->first)) + { + return itr; + } + else + { + return end(); + } + } + + //************************************************************************* + ETL_CONSTEXPR14 const_iterator upper_bound(const_key_reference key) const ETL_NOEXCEPT + { + const_iterator itr = etl::upper_bound(begin(), end(), key, compare); + + if ((itr != end()) && keys_are_equal(key, itr->first)) + { + return itr; + } + else + { + return end(); + } + } + + //************************************************************************* + template ::value, int> = 0> + ETL_CONSTEXPR14 const_iterator upper_bound(const K& key) const ETL_NOEXCEPT + { + const_iterator itr = etl::upper_bound(begin(), end(), key, compare); + + if ((itr != end()) && keys_are_equal(key, itr->first)) + { + return itr; + } + else + { + return end(); + } + } + + //************************************************************************* + ETL_CONSTEXPR14 size_type empty() const ETL_NOEXCEPT + { + return size() == 0U; + } + + //************************************************************************* + ETL_CONSTEXPR14 size_type full() const ETL_NOEXCEPT + { + return size() == Size; + } + + //************************************************************************* + ETL_CONSTEXPR14 size_type size() const ETL_NOEXCEPT + { + return size_type(element_list_end - element_list); + } + + //************************************************************************* + ETL_CONSTEXPR14 size_type max_size() const ETL_NOEXCEPT + { + return Size; + } + + //************************************************************************* + ETL_CONSTEXPR14 size_type capacity() const ETL_NOEXCEPT + { + return Size; + } + + private: + + //********************************************************************* + /// Check to see if the keys are equal. + //********************************************************************* + bool keys_are_equal(const_key_reference key1, const_key_reference key2) const + { + return !key_compare_type()(key1, key2) && !key_compare_type()(key2, key1); + } + + //********************************************************************* + template ::value, int> = 0> + bool keys_are_equal(const K1& key1, const K2& key2) const + { + return !key_compare_type()(key1, key2) && !key_compare_type()(key2, key1); + } + + Compare compare; + + value_type element_list[Size]; + value_type* element_list_end; + }; + + //************************************************************************* + /// Template deduction guides. + //************************************************************************* +#if ETL_USING_CPP17 + template + const_map(TPairs...) -> const_map::first_type, + typename etl::nth_type_t<0, TPairs...>::second_type, + sizeof...(TPairs)>; +#endif +} + +#endif diff --git a/test/test_algorithm.cpp b/test/test_algorithm.cpp index 2d362dd9..eb8f7e3b 100644 --- a/test/test_algorithm.cpp +++ b/test/test_algorithm.cpp @@ -334,6 +334,62 @@ namespace CHECK(!is_sorted); } + //************************************************************************* + TEST(is_unique_sorted_until) + { + int sorted_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + int not_sorted_data[] = { 1, 2, 3, 4, 6, 5, 7, 8, 9, 10 }; + int not_unique_data[] = { 1, 2, 3, 4, 4, 5, 6, 8, 9, 10 }; + + int* p_sorted = etl::is_unique_sorted_until(std::begin(sorted_data), std::end(sorted_data)); + int* p_not_sorted = etl::is_unique_sorted_until(std::begin(not_sorted_data), std::end(not_sorted_data)); + int* p_not_unique = etl::is_unique_sorted_until(std::begin(not_unique_data), std::end(not_unique_data)); + + CHECK_EQUAL(10, std::distance(sorted_data, p_sorted)); + CHECK_EQUAL(5, std::distance(not_sorted_data, p_not_sorted)); + CHECK_EQUAL(4, std::distance(not_unique_data, p_not_unique)); + } + + //************************************************************************* + TEST(is_unique_sorted_until_compare) + { + int sorted_data[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; + int not_sorted_data[] = { 10, 9, 8, 7, 5, 6, 4, 3, 2, 1 }; + int not_unique_data[] = { 10, 9, 8, 6, 5, 4, 4, 3, 2, 1 }; + + int* p_sorted = etl::is_unique_sorted_until(std::begin(sorted_data), std::end(sorted_data), std::greater()); + int* p_not_sorted = etl::is_unique_sorted_until(std::begin(not_sorted_data), std::end(not_sorted_data), std::greater()); + int* p_not_unique = etl::is_unique_sorted_until(std::begin(not_unique_data), std::end(not_unique_data), std::greater()); + + CHECK_EQUAL(10, std::distance(sorted_data, p_sorted)); + CHECK_EQUAL(5, std::distance(not_sorted_data, p_not_sorted)); + CHECK_EQUAL(6, std::distance(not_unique_data, p_not_unique)); + } + + //************************************************************************* + TEST(is_unique_sorted) + { + int sorted_data[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; + int not_sorted_data[] = { 1, 2, 3, 4, 6, 5, 7, 8, 9, 10 }; + int not_unique_data[] = { 1, 2, 3, 4, 4, 5, 6, 8, 9, 10 }; + + CHECK_TRUE((etl::is_unique_sorted(std::begin(sorted_data), std::end(sorted_data)))); + CHECK_FALSE((etl::is_unique_sorted(std::begin(not_sorted_data), std::end(not_sorted_data)))); + CHECK_FALSE((etl::is_unique_sorted(std::begin(not_unique_data), std::end(not_unique_data)))); + } + + //************************************************************************* + TEST(is_unique_sorted_compare) + { + int sorted_data[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }; + int not_sorted_data[] = { 10, 9, 8, 7, 5, 6, 4, 3, 2, 1 }; + int not_unique_data[] = { 10, 9, 8, 6, 5, 4, 4, 3, 2, 1 }; + + CHECK_TRUE((etl::is_unique_sorted(std::begin(sorted_data), std::end(sorted_data), std::greater()))); + CHECK_FALSE((etl::is_unique_sorted(std::begin(not_sorted_data), std::end(not_sorted_data), std::greater()))); + CHECK_FALSE((etl::is_unique_sorted(std::begin(not_unique_data), std::end(not_unique_data), std::greater()))); + } + //************************************************************************* TEST(copy_pod_pointer) { diff --git a/test/test_const_map.cpp b/test/test_const_map.cpp new file mode 100644 index 00000000..609f8588 --- /dev/null +++ b/test/test_const_map.cpp @@ -0,0 +1,799 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove, rlindeman + +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 +#include +#include +#include +#include +#include +#include + +#include "etl/const_map.h" +#include "etl/map.h" +#include "etl/string.h" + +#include "data.h" + +namespace +{ + static const size_t Max_Size = 10UL; + + //************************************************************************* + // The key type + //************************************************************************* + struct Key + { + // Default constructor + constexpr Key() + : k(0) + { + } + + // Construct from char key + constexpr explicit Key(char k_) + : k(k_) + { + } + + char k; + }; + + // Less-than operator for Key < Key + constexpr bool operator <(const Key& lhs, const Key& rhs) ETL_NOEXCEPT + { + return (lhs.k < rhs.k); + } + + // Less-than operator for Key < char + constexpr bool operator <(const Key& lhs, char rhs) ETL_NOEXCEPT + { + return (lhs.k < rhs); + } + + // Less-than operator for char < Key + constexpr bool operator <(char lhs, const Key& rhs) ETL_NOEXCEPT + { + return (lhs < rhs.k); + } + + // Greater-than operator for Key > char + constexpr bool operator >(const Key& lhs, const Key& rhs) ETL_NOEXCEPT + { + return (lhs.k > rhs.k); + } + + // Greater-than operator for char > Key + constexpr bool operator ==(const Key& lhs, const Key& rhs) ETL_NOEXCEPT + { + return (lhs.k == rhs.k); + } + + //#define TEST_GREATER_THAN + #ifdef TEST_GREATER_THAN + using Data = etl::const_map>; + using DataTransparentComparator = etl::const_map>; + #else + using Data = etl::const_map>; + using DataTransparentComparator = etl::const_map>; + #endif + + using value_type = Data::value_type; + + using Data_iterator = Data::iterator; + using Data_const_iterator = Data::const_iterator; + + SUITE(test_const_map) + { + //************************************************************************* +#include "etl/private/diagnostic_null_dereference_push.h" + template + bool Check_Equal(T1 begin1, T1 end1, T2 begin2) + { + while (begin1 != end1) + { + if ((begin1->first != begin2->first) || (begin1->second != begin2->second)) + { + return false; + } + + ++begin1; + ++begin2; + } + + return true; + } +#include "etl/private/diagnostic_pop.h" + + //************************************************************************* + TEST(test_default_constructor) + { + static constexpr Data data; + + static constexpr bool is_valid = data.is_valid(); + static constexpr size_t size = data.size(); + static constexpr bool empty = data.empty(); + static constexpr bool full = data.full(); + static constexpr size_t capacity = data.capacity(); + static constexpr size_t max_size = data.max_size(); + static constexpr Data::const_iterator begin = data.begin(); + static constexpr Data::const_iterator end = data.end(); + + CHECK_TRUE(is_valid); + CHECK_TRUE(size == 0UL); + CHECK_TRUE(empty); + CHECK_FALSE(full); + CHECK_TRUE(capacity == Max_Size); + CHECK_TRUE(max_size == Max_Size); + CHECK_TRUE(begin == end); + } + + //************************************************************************* + TEST(test_constructor_min_size) + { + static constexpr Data data{ value_type{Key('A'), 0 } }; + + static constexpr bool is_valid = data.is_valid(); + static constexpr size_t size = data.size(); + static constexpr bool empty = data.empty(); + static constexpr bool full = data.full(); + static constexpr size_t capacity = data.capacity(); + static constexpr size_t max_size = data.max_size(); + static constexpr Data::const_iterator begin = data.begin(); + static constexpr Data::const_iterator end = data.end(); + + CHECK_TRUE(is_valid); + CHECK_TRUE(size == 1U); + CHECK_FALSE(empty); + CHECK_FALSE(full); + CHECK_TRUE(capacity == Max_Size); + CHECK_TRUE(max_size == Max_Size); + CHECK_FALSE(begin == end); + } + + //************************************************************************* + TEST(test_constructor_max_size) + { +#ifdef TEST_GREATER_THAN + static constexpr Data data{ value_type{Key('J'), 9 }, value_type{Key('I'), 8 }, value_type{Key('H'), 7 }, value_type{Key('G'), 6 }, value_type{Key('F'), 5 }, + value_type{Key('E'), 4 }, value_type{Key('D'), 3 }, value_type{Key('C'), 2 }, value_type{Key('B'), 1 }, value_type{Key('A'), 0 } }; +#else + static constexpr Data data{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('C'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; +#endif + + CHECK_TRUE(data.is_valid()); + CHECK_TRUE(data.size() == Max_Size); + CHECK_FALSE(data.empty()); + CHECK_TRUE(data.full()); + CHECK_TRUE(data.capacity() == Max_Size); + CHECK_TRUE(data.max_size() == Max_Size); + CHECK_FALSE(data.begin() == data.end()); + } + + ////************************************************************************* + // Enable to check static_assert "Number of elements exceeds capacity" + ////************************************************************************* + //TEST(test_constructor_excess_size) + //{ + // static constexpr Data data{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('C'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + // value_type{Key('F'), 5 }, value_type{'G'), 6 }, value_type{'H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 }, + // value_type{Key('K'), 10 } }; + //} + +#if ETL_USING_CPP17 + //************************************************************************* + TEST(test_cpp17_deduced_constructor) + { +#ifdef TEST_GREATER_THAN + static constexpr Data data{ value_type{Key('J'), 9 }, value_type{Key('I'), 8 }, value_type{Key('H'), 7 }, value_type{Key('G'), 6 }, value_type{Key('F'), 5 }, + value_type{Key('E'), 4 }, value_type{Key('D'), 3 }, value_type{Key('C'), 2 }, value_type{Key('B'), 1 }, value_type{Key('A'), 0 } }; +#else + static constexpr Data data{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('C'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; +#endif + +#ifdef TEST_GREATER_THAN + etl::const_map check{ value_type{Key('J'), 9 }, value_type{Key('I'), 8 }, value_type{Key('H'), 7 }, value_type{Key('G'), 6 }, value_type{Key('F'), 5 }, + value_type{Key('E'), 4 }, value_type{Key('D'), 3 }, value_type{Key('C'), 2 }, value_type{Key('B'), 1 }, value_type{Key('A'), 0 } }; +#else + etl::const_map check{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('C'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; +#endif + CHECK_TRUE(data.is_valid()); + CHECK_TRUE(data.size() == Max_Size); + CHECK_FALSE(data.empty()); + CHECK_TRUE(data.full()); + CHECK_TRUE(data.capacity() == Max_Size); + CHECK_TRUE(data.max_size() == Max_Size); + CHECK_FALSE(data.begin() == data.end()); + } +#endif + + //************************************************************************* + TEST(test_begin) + { +#ifdef TEST_GREATER_THAN + static constexpr Data data{ value_type{Key('J'), 9 }, value_type{Key('I'), 8 }, value_type{Key('H'), 7 }, value_type{Key('G'), 6 }, value_type{Key('F'), 5 }, + value_type{Key('E'), 4 }, value_type{Key('D'), 3 }, value_type{Key('C'), 2 }, value_type{Key('B'), 1 }, value_type{Key('A'), 0 } }; +#else + static constexpr Data data{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('C'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; +#endif + + CHECK_TRUE(data.is_valid()); + auto value = *data.begin(); + +#ifdef TEST_GREATER_THAN + CHECK_TRUE((value_type{ Key('J'), 9 }) == value); +#else + CHECK_TRUE((value_type{ Key('A'), 0 }) == value); +#endif + } + + //************************************************************************* + TEST(test_end) + { +#ifdef TEST_GREATER_THAN + static constexpr Data data{ value_type{Key('J'), 9 }, value_type{Key('I'), 8 }, value_type{Key('H'), 7 }, value_type{Key('G'), 6 }, value_type{Key('F'), 5 }, + value_type{Key('E'), 4 }, value_type{Key('D'), 3 }, value_type{Key('C'), 2 }, value_type{Key('B'), 1 }, value_type{Key('A'), 0 } }; +#else + static constexpr Data data{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('C'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; +#endif + + CHECK_TRUE(data.is_valid()); + CHECK_TRUE(data.end() == (data.begin() + data.size())); + } + + //************************************************************************* + TEST(test_index) + { +#ifdef TEST_GREATER_THAN + static constexpr Data data{ value_type{Key('J'), 9 }, value_type{Key('I'), 8 }, value_type{Key('H'), 7 }, value_type{Key('G'), 6 }, value_type{Key('F'), 5 }, + value_type{Key('E'), 4 }, value_type{Key('D'), 3 }, value_type{Key('C'), 2 }, value_type{Key('B'), 1 }, value_type{Key('A'), 0 } }; +#else + static constexpr Data data{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('C'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; +#endif + + CHECK_TRUE(data.is_valid()); + CHECK(data[Key('A')] == 0); + CHECK(data[Key('B')] == 1); + CHECK(data[Key('C')] == 2); + CHECK(data[Key('D')] == 3); + CHECK(data[Key('E')] == 4); + CHECK(data[Key('F')] == 5); + CHECK(data[Key('G')] == 6); + CHECK(data[Key('H')] == 7); + CHECK(data[Key('I')] == 8); + CHECK(data[Key('J')] == 9); + } + + //************************************************************************* + TEST(test_index__using_transparent_comparator) + { +#ifdef TEST_GREATER_THAN + static constexpr DataTransparentComparator data{ value_type{Key('J'), 9 }, value_type{Key('I'), 8 }, value_type{Key('H'), 7 }, value_type{Key('G'), 6 }, value_type{Key('F'), 5 }, + value_type{Key('E'), 4 }, value_type{Key('D'), 3 }, value_type{Key('C'), 2 }, value_type{Key('B'), 1 }, value_type{Key('A'), 0 } }; +#else + static constexpr DataTransparentComparator data{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('C'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; +#endif + + CHECK_TRUE(data.is_valid()); + CHECK(data['A'] == 0); + CHECK(data['B'] == 1); + CHECK(data['C'] == 2); + CHECK(data['D'] == 3); + CHECK(data['E'] == 4); + CHECK(data['F'] == 5); + CHECK(data['G'] == 6); + CHECK(data['H'] == 7); + CHECK(data['I'] == 8); + CHECK(data['J'] == 9); + } + + //************************************************************************* + TEST(test_at) + { +#ifdef TEST_GREATER_THAN + static constexpr Data data{ value_type{Key('J'), 9 }, value_type{Key('I'), 8 }, value_type{Key('H'), 7 }, value_type{Key('G'), 6 }, value_type{Key('F'), 5 }, + value_type{Key('E'), 4 }, value_type{Key('D'), 3 }, value_type{Key('C'), 2 }, value_type{Key('B'), 1 }, value_type{Key('A'), 0 } }; +#else + static constexpr Data data{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('C'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; +#endif + + CHECK_TRUE(data.is_valid()); + CHECK(data.at(Key('A')) == 0); + CHECK(data.at(Key('B')) == 1); + CHECK(data.at(Key('C')) == 2); + CHECK(data.at(Key('D')) == 3); + CHECK(data.at(Key('E')) == 4); + CHECK(data.at(Key('F')) == 5); + CHECK(data.at(Key('G')) == 6); + CHECK(data.at(Key('H')) == 7); + CHECK(data.at(Key('I')) == 8); + CHECK(data.at(Key('J')) == 9); + } + + //************************************************************************* + TEST(test_at_using_transparent_comparator) + { + #ifdef TEST_GREATER_THAN + static constexpr DataTransparentComparator data{ value_type{Key('J'), 9 }, value_type{Key('I'), 8 }, value_type{Key('H'), 7 }, value_type{Key('G'), 6 }, value_type{Key('F'), 5 }, + value_type{Key('E'), 4 }, value_type{Key('D'), 3 }, value_type{Key('C'), 2 }, value_type{Key('B'), 1 }, value_type{Key('A'), 0 } }; + #else + static constexpr DataTransparentComparator data{ value_type{Key('A'), 0 }, value_type{Key('B'), 1 }, value_type{Key('C'), 2 }, value_type{Key('D'), 3 }, value_type{Key('E'), 4 }, + value_type{Key('F'), 5 }, value_type{Key('G'), 6 }, value_type{Key('H'), 7 }, value_type{Key('I'), 8 }, value_type{Key('J'), 9 } }; + #endif + + CHECK_TRUE(data.is_valid()); + CHECK(data.at('A') == 0); + CHECK(data.at('B') == 1); + CHECK(data.at('C') == 2); + CHECK(data.at('D') == 3); + CHECK(data.at('E') == 4); + CHECK(data.at('F') == 5); + CHECK(data.at('G') == 6); + CHECK(data.at('H') == 7); + CHECK(data.at('I') == 8); + CHECK(data.at('J') == 9); + } + +// //************************************************************************* +// TEST(test_equal_range) +// { +// Compare_Data compare_data(random_data.begin(), random_data.end()); +// Data data(random_data.begin(), random_data.end()); +// +// ETL_OR_STD::pair data_result = data.equal_range('2'); +// Data::iterator data_lb = data.lower_bound('2'); +// ETL_OR_STD::pair compare_result = compare_data.equal_range('2'); +// Compare_Data::iterator compare_data_lb = compare_data.lower_bound('2'); +// +// // Check that both return the same return results +// CHECK(data_lb->first == compare_data_lb->first); +// CHECK(data_lb->second == compare_data_lb->second); +// CHECK(data_result.first->first == compare_result.first->first); +// CHECK(data_result.first->second == compare_result.first->second); +// CHECK(data_result.second->first == compare_result.second->first); +// CHECK(data_result.second->second == compare_result.second->second); +// +// bool isEqual = Check_Equal(data.begin(), data.end(), compare_data.begin()); +// +// CHECK(isEqual); +// } + +// //************************************************************************* +// TEST(test_equal_range_using_transparent_comparator) +// { +// using CMap = std::map>; +// using EMap = etl::map>; +// +// CMap compare_data(random_data.begin(), random_data.end()); +// EMap data(random_data.begin(), random_data.end()); +// +// ETL_OR_STD::pair data_result = data.equal_range(Key('2')); +// EMap::iterator data_lb = data.lower_bound('2'); +// ETL_OR_STD::pair compare_result = compare_data.equal_range('2'); +// CMap::iterator compare_data_lb = compare_data.lower_bound('2'); +// +// // Check that both return the same return results +// CHECK(data_lb->first == compare_data_lb->first); +// CHECK(data_lb->second == compare_data_lb->second); +// CHECK(data_result.first->first == compare_result.first->first); +// CHECK(data_result.first->second == compare_result.first->second); +// CHECK(data_result.second->first == compare_result.second->first); +// CHECK(data_result.second->second == compare_result.second->second); +// +// bool isEqual = Check_Equal(data.begin(), data.end(), compare_data.begin()); +// +// CHECK(isEqual); +// } + +// //************************************************************************* +// TEST(test_count) +// { +// const Data data(initial_data.begin(), initial_data.end()); +// +// CHECK(data.count('3') == 1UL); +// +// CHECK(data.count(Key('A') == 0UL); +// } + +// //************************************************************************* +// TEST(test_count_using_transparent_comparator) +// { +// using EMap = etl::map>; +// +// const EMap data(initial_data.begin(), initial_data.end()); +// +// CHECK(data.count(Key('3')) == 1UL); +// +// CHECK(data.count(Key(Key('A')) == 0UL); +// } + +// //************************************************************************* +// TEST(test_iterator) +// { +// Compare_Data compare_data(initial_data.begin(), initial_data.end()); +// +// Data data(compare_data.begin(), compare_data.end()); +// +// bool isEqual = Check_Equal(data.begin(), +// data.end(), +// compare_data.begin()); +// +// CHECK(isEqual); +// } + +// //************************************************************************* +// TEST(test_const_iterator) +// { +// Compare_Data compare_data(initial_data.begin(), initial_data.end()); +// +// Data data(compare_data.begin(), compare_data.end()); +// +// bool isEqual = Check_Equal(data.cbegin(), +// data.cend(), +// compare_data.cbegin()); +// +// CHECK(isEqual); +// } + +// //************************************************************************* +// TEST(test_find) +// { +// Data data(initial_data.begin(), initial_data.end()); +// +// Data::iterator it = data.find('3'); +// CHECK(3 == it->second); +// +// it = data.find(Key('A'); +// CHECK(data.end() == it); +// +// it = data.find('!'); +// CHECK(data.end() == it); +// } + +// //************************************************************************* +// TEST(test_find_using_transparent_comparator) +// { +// using EMap = etl::map>; +// +// EMap data(initial_data.begin(), initial_data.end()); +// +// EMap::iterator it = data.find(Key('3')); +// CHECK(3 == it->second); +// +// it = data.find(Key(Key('A')); +// CHECK(data.end() == it); +// +// it = data.find(Key('!')); +// CHECK(data.end() == it); +// } + +// //************************************************************************* +// TEST(test_equal) +// { +// const Data initial1(initial_data.begin(), initial_data.end()); +// const Data initial2(initial_data.begin(), initial_data.end()); +// +// CHECK(initial1 == initial2); +// +// const Data different(different_data.begin(), different_data.end()); +// +// CHECK(!(initial1 == different)); +// } + +// //************************************************************************* +// TEST(test_not_equal) +// { +// const Data initial1(initial_data.begin(), initial_data.end()); +// const Data initial2(initial_data.begin(), initial_data.end()); +// +// CHECK(!(initial1 != initial2)); +// +// const Data different(different_data.begin(), different_data.end()); +// +// CHECK(initial1 != different); +// } + +// //************************************************************************* +// TEST(test_lower_bound) +// { +// Compare_Data compare_data(initial_data.begin(), initial_data.end()); +// Data data(initial_data.begin(), initial_data.end()); +// +// Compare_Data::iterator i_compare = compare_data.lower_bound('8'); +// Data::iterator i_data = data.lower_bound('8'); +// CHECK(i_compare->second == i_data->second); +// +//#ifdef TEST_GREATER_THAN +// i_compare = compare_data.lower_bound('.'); +// CHECK(compare_data.end() == i_compare); +// +// i_data = data.lower_bound('.'); +// CHECK(data.end() == i_data); +// +// i_compare = compare_data.lower_bound(Key('A'); +// i_data = data.lower_bound(Key('A'); +// CHECK(i_compare->second == i_data->second); +//#else +// i_compare = compare_data.lower_bound('.'); +// i_data = data.lower_bound('.'); +// CHECK(i_compare->second == i_data->second); +// +// i_compare = compare_data.lower_bound(Key('A'); +// CHECK(compare_data.end() == i_compare); +// +// i_data = data.lower_bound(Key('A'); +// CHECK(data.end() == i_data); +//#endif +// } + +// //************************************************************************* +// TEST(test_lower_bound_using_transparent_comparator) +// { +// using CMap = std::map>; +// using EMap = etl::map>; +// +// CMap compare_data(initial_data.begin(), initial_data.end()); +// EMap data(initial_data.begin(), initial_data.end()); +// +// CMap::iterator i_compare = compare_data.lower_bound('8'); +// EMap::iterator i_data = data.lower_bound(Key('8')); +// CHECK(i_compare->second == i_data->second); +// +// i_compare = compare_data.lower_bound('.'); +// i_data = data.lower_bound(Key('.')); +// CHECK(i_compare->second == i_data->second); +// +// i_compare = compare_data.lower_bound(Key('A'); +// CHECK(compare_data.end() == i_compare); +// +// i_data = data.lower_bound(Key(Key('A')); +// CHECK(data.end() == i_data); +// } + +// //************************************************************************* +// TEST(test_upper_bound) +// { +// Compare_Data compare_data(initial_data.begin(), initial_data.end()); +// Data data(initial_data.begin(), initial_data.end()); +// +// Compare_Data::iterator i_compare = compare_data.upper_bound('2'); +// Data::iterator i_data = data.upper_bound('2'); +// CHECK(i_compare->second == i_data->second); +// +//#ifdef TEST_GREATER_THAN +// i_compare = compare_data.upper_bound('.'); +// CHECK(compare_data.end() == i_compare); +// +// i_data = data.upper_bound('.'); +// CHECK(data.end() == i_data); +// +// i_compare = compare_data.upper_bound(Key('A'); +// i_data = data.upper_bound(Key('A'); +// CHECK(i_compare->second == i_data->second); +//#else +// i_compare = compare_data.upper_bound('.'); +// i_data = data.upper_bound('.'); +// CHECK(i_compare->second == i_data->second); +// +// i_compare = compare_data.upper_bound(Key('A'); +// CHECK(compare_data.end() == i_compare); +// +// i_data = data.upper_bound(Key('A'); +// CHECK(data.end() == i_data); +//#endif +// } + +// //************************************************************************* +// TEST(test_upper_bound_using_transparent_comparator) +// { +// using CMap = std::map>; +// using EMap = etl::map>; +// +// CMap compare_data(initial_data.begin(), initial_data.end()); +// EMap data(initial_data.begin(), initial_data.end()); +// +// CMap::iterator i_compare = compare_data.upper_bound('2'); +// EMap::iterator i_data = data.upper_bound(Key('2')); +// CHECK(i_compare->second == i_data->second); +// +// i_compare = compare_data.upper_bound('.'); +// i_data = data.upper_bound(Key('.')); +// CHECK(i_compare->second == i_data->second); +// +// i_compare = compare_data.upper_bound(Key('A'); +// CHECK(compare_data.end() == i_compare); +// +// i_data = data.upper_bound(Key(Key('A')); +// CHECK(data.end() == i_data); +// } + +// //************************************************************************* +// TEST(test_key_compare) +// { +// const Data data(initial_data.begin(), initial_data.end()); +// +// Data::key_compare compare = data.key_comp(); +// +// Data::key_type a(Key('A'); +// Data::key_type b(Key('B'); +// +//#ifdef TEST_GREATER_THAN +// CHECK(!compare(a, b)); +// CHECK(compare(b, a)); +//#else +// CHECK(compare(a, b)); +// CHECK(!compare(b, a)); +//#endif +// } + +// //************************************************************************* +// TEST(test_key_compare_using_transparent_comparator) +// { +// using EMap = etl::map>; +// const EMap data(initial_data.begin(), initial_data.end()); +// +// EMap::key_compare compare = data.key_comp(); +// +// char a(Key('A'); +// Key b(Key('B'); +// +// CHECK(compare(a, b)); +// CHECK(!compare(b, a)); +// } + +// //************************************************************************* +// TEST(test_value_compare) +// { +// const Data data(initial_data.begin(), initial_data.end()); +// +// Data::value_compare compare = data.value_comp(); +// +// Data::value_type a(char(Key('A'), 0); +// Data::value_type b(char(Key('B'), 1); +// +//#ifdef TEST_GREATER_THAN +// CHECK(!compare(a, b)); +// CHECK(compare(b, a)); +//#else +// CHECK(compare(a, b)); +// CHECK(!compare(b, a)); +//#endif +// } + +// //************************************************************************* +// TEST(test_compare_lower_upper_bound) +// { +// Data data(initial_data_even.begin(), initial_data_even.end()); +// Compare_Data compare(initial_data_even.begin(), initial_data_even.end()); +// +// std::vector > tab(test_data.begin(), test_data.end()); +// +// //make sure both data and compare contain same elements +// std::vector > data_elements(data.begin(), data.end()); +// std::vector > compare_data_elements(compare.begin(), compare.end()); +// +// CHECK(data_elements == compare_data_elements); +// CHECK(data_elements.size() == Max_Size); +// +// for(std::vector >::iterator it = tab.begin() ; it != tab.end() ; ++it) +// { +// char i = it->first; +// +// //lower_bound +// CHECK((compare.lower_bound(i) == compare.end()) == (data.lower_bound(i) == data.end())); +// //if both end, or none +// if((compare.lower_bound(i) == compare.end()) == (data.lower_bound(i) == data.end())) +// { +// //if both are not end +// if(compare.lower_bound(i) != compare.end()) +// { +// CHECK((*compare.lower_bound(i)) == (*data.lower_bound(i))); +// } +// +// ETL_OR_STD::pair stlret = compare.equal_range(i); +// ETL_OR_STD::pair etlret = data.equal_range(i); +// +// CHECK((stlret.first == compare.end()) == (etlret.first == data.end())); +// if((stlret.first != compare.end()) && (etlret.first != data.end())) +// { +// CHECK((*stlret.first) == (*etlret.first)); +// } +// CHECK((stlret.second == compare.end()) == (etlret.second == data.end())); +// if((stlret.second != compare.end()) && (etlret.second != data.end())) +// { +// CHECK((*stlret.second) == (*etlret.second)); +// } +// } +// +// //upper_bound +// CHECK((compare.upper_bound(i) == compare.end()) == (data.upper_bound(i) == data.end())); +// //if both end, or none +// if((compare.upper_bound(i) == compare.end()) == (data.upper_bound(i) == data.end())) +// { +// //if both are not end +// if(compare.upper_bound(i) != compare.end()) +// { +// CHECK((*compare.upper_bound(i)) == (*data.upper_bound(i))); +// } +// } +// } +// } + +// //************************************************************************* +//#if ETL_USING_CPP17 && ETL_HAS_INITIALIZER_LIST && !defined(ETL_TEMPLATE_DEDUCTION_GUIDE_TESTS_DISABLED) +// TEST(test_map_template_deduction) +// { +// using Pair = std::pair, int>; +// +// etl::map data { Pair{'0', 0}, Pair{'1', 1}, Pair{'2', 2}, Pair{'3', 3}, Pair{'4', 4}, Pair{'5', 5} }; +// +// auto v = *data.begin(); +// using Type = decltype(v); +// CHECK((std::is_same_v)); +// +// CHECK_EQUAL(0, data.at('0')); +// CHECK_EQUAL(1, data.at('1')); +// CHECK_EQUAL(2, data.at('2')); +// CHECK_EQUAL(3, data.at('3')); +// CHECK_EQUAL(4, data.at('4')); +// CHECK_EQUAL(5, data.at('5')); +// } +//#endif + +// //************************************************************************* +// TEST(test_contains) +// { +// Data data(initial_data.begin(), initial_data.end()); +// +// CHECK(data.contains(char('1'))); +// CHECK(!data.contains(char('99'))); +// } + +// //************************************************************************* +// TEST(test_contains_with_transparent_comparator) +// { +// etl::map> data(initial_data.begin(), initial_data.end()); +// +// CHECK(data.contains(char('1'))); +// CHECK(data.contains(Key('1'))); +// +// CHECK(!data.contains(char('99'))); +// CHECK(!data.contains(Key('99'))); +// } + }; +}