From 53af6f7dafb1c20feab4d78b0dbcaebf98313443 Mon Sep 17 00:00:00 2001 From: Austin Morton Date: Tue, 9 Jan 2018 12:58:10 -0500 Subject: [PATCH 01/50] replace usages of _DEBUG with ETL_DEBUG fixes some -Wundef errors when _DEBUG was not defined --- src/flat_map.h | 4 ++-- src/forward_list.h | 2 +- src/intrusive_forward_list.h | 4 ++-- src/intrusive_list.h | 4 ++-- src/list.h | 4 ++-- src/reference_flat_map.h | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/flat_map.h b/src/flat_map.h index 1a5b09c0..26132748 100644 --- a/src/flat_map.h +++ b/src/flat_map.h @@ -263,8 +263,8 @@ namespace etl //********************************************************************* /// Assigns values to the flat_map. - /// If ETL_THROW_EXCEPTIONS & _DEBUG are defined, emits flat_map_full if the flat_map does not have enough free space. - /// If ETL_THROW_EXCEPTIONS & _DEBUG are defined, emits flat_map_iterator if the iterators are reversed. + /// If ETL_THROW_EXCEPTIONS & ETL_DEBUG are defined, emits flat_map_full if the flat_map does not have enough free space. + /// If ETL_THROW_EXCEPTIONS & ETL_DEBUG are defined, emits flat_map_iterator if the iterators are reversed. ///\param first The iterator to the first element. ///\param last The iterator to the last element + 1. //********************************************************************* diff --git a/src/forward_list.h b/src/forward_list.h index 116846a2..921b40b3 100644 --- a/src/forward_list.h +++ b/src/forward_list.h @@ -568,7 +568,7 @@ namespace etl //************************************************************************* /// Assigns a range of values to the forward_list. /// If asserts or exceptions are enabled throws etl::forward_list_full if the forward_list does not have enough free space. - /// If ETL_THROW_EXCEPTIONS & _DEBUG are defined throws forward_list_iterator if the iterators are reversed. + /// If ETL_THROW_EXCEPTIONS & ETL_DEBUG are defined throws forward_list_iterator if the iterators are reversed. //************************************************************************* template void assign(TIterator first, TIterator last) diff --git a/src/intrusive_forward_list.h b/src/intrusive_forward_list.h index 578fdfac..c2d91d2b 100644 --- a/src/intrusive_forward_list.h +++ b/src/intrusive_forward_list.h @@ -147,7 +147,7 @@ namespace etl //************************************************************************* /// Assigns a range of values to the intrusive_forward_list. - /// If ETL_THROW_EXCEPTIONS & _DEBUG are defined throws forward_list_iterator if the iterators are reversed. + /// If ETL_THROW_EXCEPTIONS & ETL_DEBUG are defined throws forward_list_iterator if the iterators are reversed. //************************************************************************* template void assign(TIterator first, TIterator last) @@ -971,7 +971,7 @@ namespace etl { if (!other.empty()) { -#if _DEBUG +#if defined(ETL_DEBUG) ETL_ASSERT(etl::is_sorted(other.begin(), other.end(), compare), ETL_ERROR(intrusive_forward_list_unsorted)); ETL_ASSERT(etl::is_sorted(begin(), end(), compare), ETL_ERROR(intrusive_forward_list_unsorted)); #endif diff --git a/src/intrusive_list.h b/src/intrusive_list.h index f1da84e8..a3d3be91 100644 --- a/src/intrusive_list.h +++ b/src/intrusive_list.h @@ -126,7 +126,7 @@ namespace etl //************************************************************************* /// Assigns a range of values to the intrusive_list. - /// If ETL_THROW_EXCEPTIONS & _DEBUG are defined emits a + /// If ETL_THROW_EXCEPTIONS & ETL_DEBUG are defined emits a /// intrusive_list_iterator_exception if the iterators are reversed. //************************************************************************* template @@ -1020,7 +1020,7 @@ namespace etl { if (!other.empty()) { -#if _DEBUG +#if defined(ETL_DEBUG) ETL_ASSERT(etl::is_sorted(other.begin(), other.end(), compare), ETL_ERROR(intrusive_list_unsorted)); ETL_ASSERT(etl::is_sorted(begin(), end(), compare), ETL_ERROR(intrusive_list_unsorted)); #endif diff --git a/src/list.h b/src/list.h index b4c83130..4ba169a2 100644 --- a/src/list.h +++ b/src/list.h @@ -706,7 +706,7 @@ namespace etl //************************************************************************* /// Assigns a range of values to the list. /// If asserts or exceptions are enabled throws etl::list_full if the list does not have enough free space. - /// If ETL_THROW_EXCEPTIONS & _DEBUG are defined throws list_iterator if the iterators are reversed. + /// If ETL_THROW_EXCEPTIONS & ETL_DEBUG are defined throws list_iterator if the iterators are reversed. //************************************************************************* template void assign(TIterator first, TIterator last) @@ -1250,7 +1250,7 @@ namespace etl { if (!other.empty()) { -#if _DEBUG +#if defined(ETL_DEBUG) ETL_ASSERT(etl::is_sorted(other.begin(), other.end(), compare), ETL_ERROR(list_unsorted)); ETL_ASSERT(etl::is_sorted(begin(), end(), compare), ETL_ERROR(list_unsorted)); #endif diff --git a/src/reference_flat_map.h b/src/reference_flat_map.h index fd98fc3e..eda76782 100644 --- a/src/reference_flat_map.h +++ b/src/reference_flat_map.h @@ -514,8 +514,8 @@ namespace etl //********************************************************************* /// Assigns values to the reference_flat_map. - /// If ETL_THROW_EXCEPTIONS & _DEBUG are defined, emits flat_map_full if the reference_flat_map does not have enough free space. - /// If ETL_THROW_EXCEPTIONS & _DEBUG are defined, emits flat_map_iterator if the iterators are reversed. + /// If ETL_THROW_EXCEPTIONS & ETL_DEBUG are defined, emits flat_map_full if the reference_flat_map does not have enough free space. + /// If ETL_THROW_EXCEPTIONS & ETL_DEBUG are defined, emits flat_map_iterator if the iterators are reversed. ///\param first The iterator to the first element. ///\param last The iterator to the last element + 1. //********************************************************************* From bb294e80fe2a772a28a3b3515eb290f7863b4134 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 21 Jan 2018 18:42:03 +0000 Subject: [PATCH 02/50] Array wrapper and unit tests --- src/array_wrapper.h | 420 ++++++++++++++++++++++++ src/container.h | 2 + src/platform.h | 6 + test/test_array_wrapper.cpp | 564 ++++++++++++++++++++++++++++++++ test/vs2017/etl.vcxproj | 2 + test/vs2017/etl.vcxproj.filters | 6 + 6 files changed, 1000 insertions(+) create mode 100644 src/array_wrapper.h create mode 100644 test/test_array_wrapper.cpp diff --git a/src/array_wrapper.h b/src/array_wrapper.h new file mode 100644 index 00000000..9ada074e --- /dev/null +++ b/src/array_wrapper.h @@ -0,0 +1,420 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2017 jwellbelove + +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_ARRAY_WRAPPER__ +#define __ETL_ARRAY_WRAPPER__ + +#include "platform.h" +#include "iterator.h" +#include "error_handler.h" +#include "exception.h" +#include "hash.h" +#include "container.h" +#include "parameter_type.h" + +#include + +///\defgroup array array +/// A wrapper for arrays +///\ingroup containers + +#undef ETL_FILE +#define ETL_FILE "42" + +namespace etl +{ + //*************************************************************************** + /// The base class for array_wrapper exceptions. + //*************************************************************************** + class array_wrapper_exception : public exception + { + public: + + array_wrapper_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + : exception(reason_, file_name_, line_number_) + { + } + }; + + //*************************************************************************** + ///\ingroup stack + /// The exception thrown when the index is out of bounds. + //*************************************************************************** + class array_wrapper_bounds : public array_wrapper_exception + { + public: + + array_wrapper_bounds(string_type file_name_, numeric_type line_number_) + : array_wrapper_exception(ETL_ERROR_TEXT("array_wrapper:bounds", ETL_FILE"A"), file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// Array wrapper. + //*************************************************************************** + template + class array_wrapper + { + public: + + typedef T value_type; + typedef std::size_t size_type; + typedef T& reference; + typedef const T& const_reference; + typedef T* pointer; + typedef const T* const_pointer; + typedef T* iterator; + typedef const T* const_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + typedef typename etl::parameter_type::type parameter_t; + + // Indexes for positions in the array. + enum + { + SIZE = SIZE_, + MAX_SIZE = SIZE_, + FRONT = 0, + BACK = SIZE - 1, + BEGIN = 0, + END = SIZE, + RBEGIN = SIZE - 1, + REND = -1 + }; + + //************************************************************************* + /// Returns a reference to the first element. + //************************************************************************* + ETL_CONSTEXPR reference front() + { + return *&ARRAY_[FRONT]; + } + + //************************************************************************* + /// Returns a const reference to the first element. + //************************************************************************* + ETL_CONSTEXPR const_reference front() const + { + return *&ARRAY_[FRONT]; + } + + //************************************************************************* + /// Returns a reference to the last element. + //************************************************************************* + ETL_CONSTEXPR reference back() + { + return *&ARRAY_[BACK]; + } + + //************************************************************************* + /// Returns a const reference to the last element. + //************************************************************************* + ETL_CONSTEXPR const_reference back() const + { + return *&ARRAY_[BACK]; + } + + //************************************************************************* + /// Returns a pointer to the first element of the internal storage. + //************************************************************************* + ETL_CONSTEXPR pointer data() + { + return &ARRAY_[BEGIN]; + } + + //************************************************************************* + /// Returns a const pointer to the first element of the internal storage. + //************************************************************************* + ETL_CONSTEXPR const_pointer data() const + { + return &ARRAY_[BEGIN]; + } + + //************************************************************************* + /// Returns an iterator to the beginning of the array. + //************************************************************************* + ETL_CONSTEXPR iterator begin() + { + return &ARRAY_[BEGIN]; + } + + //************************************************************************* + /// Returns a const iterator to the beginning of the array. + //************************************************************************* + ETL_CONSTEXPR const_iterator begin() const + { + return &ARRAY_[BEGIN]; + } + + //************************************************************************* + /// Returns a const iterator to the beginning of the array. + //************************************************************************* + ETL_CONSTEXPR const_iterator cbegin() const + { + return &ARRAY_[BEGIN]; + } + + //************************************************************************* + /// Returns an iterator to the end of the array. + //************************************************************************* + ETL_CONSTEXPR iterator end() + { + return &ARRAY_[END]; + } + + //************************************************************************* + /// Returns a const iterator to the end of the array. + //************************************************************************* + ETL_CONSTEXPR const_iterator end() const + { + return &ARRAY_[END]; + } + + //************************************************************************* + // Returns a const iterator to the end of the array. + //************************************************************************* + ETL_CONSTEXPR const_iterator cend() const + { + return &ARRAY_[END]; + } + + //************************************************************************* + // Returns an reverse iterator to the reverse beginning of the array. + //************************************************************************* + ETL_CONSTEXPR reverse_iterator rbegin() + { + return reverse_iterator(&ARRAY_[END]); + } + + //************************************************************************* + /// Returns a const reverse iterator to the reverse beginning of the array. + //************************************************************************* + ETL_CONSTEXPR const_reverse_iterator rbegin() const + { + return const_reverse_iterator(&ARRAY_[END]); + } + + //************************************************************************* + /// Returns a const reverse iterator to the reverse beginning of the array. + //************************************************************************* + ETL_CONSTEXPR const_reverse_iterator crbegin() const + { + return const_reverse_iterator(&ARRAY_[END]); + } + + //************************************************************************* + /// Returns a reverse iterator to the end of the array. + //************************************************************************* + ETL_CONSTEXPR reverse_iterator rend() + { + return reverse_iterator(&ARRAY_[BEGIN]); + } + + //************************************************************************* + /// Returns a const reverse iterator to the end of the array. + //************************************************************************* + ETL_CONSTEXPR const_reverse_iterator rend() const + { + return const_reverse_iterator(&ARRAY_[BEGIN]); + } + + //************************************************************************* + /// Returns a const reverse iterator to the end of the array. + //************************************************************************* + ETL_CONSTEXPR const_reverse_iterator crend() const + { + return const_reverse_iterator(&ARRAY_[BEGIN]); + } + + //************************************************************************* + /// Returns the size of the array. + //************************************************************************* + ETL_CONSTEXPR size_t size() const + { + return SIZE; + } + + //************************************************************************* + /// Returns the maximum possible size of the array. + //************************************************************************* + ETL_CONSTEXPR size_t max_size() const + { + return MAX_SIZE; + } + + //************************************************************************* + /// Returns a reference to the indexed value. + //************************************************************************* + ETL_CONSTEXPR reference operator[](size_t i) + { + return ARRAY_[i]; + } + + //************************************************************************* + /// Returns a const reference to the indexed value. + //************************************************************************* + ETL_CONSTEXPR const_reference operator[](size_t i) const + { + return ARRAY_[i]; + } + + //************************************************************************* + /// Returns a reference to the indexed value. + //************************************************************************* + ETL_CONSTEXPR reference at(size_t i) + { + ETL_ASSERT(i < SIZE, ETL_ERROR(etl::array_wrapper_bounds)); + return ARRAY_[i]; + } + + //************************************************************************* + /// Returns a const reference to the indexed value. + //************************************************************************* + ETL_CONSTEXPR const_reference at(size_t i) const + { + ETL_ASSERT(i < SIZE, ETL_ERROR(etl::array_wrapper_bounds)); + return ARRAY_[i]; + } + + //************************************************************************* + /// Fills the array. + //************************************************************************* + void fill(parameter_t value) + { + std::fill(begin(), end(), value); + } + + //************************************************************************* + /// Swaps the contents of arrays. + //************************************************************************* + template + void swap(etl::array_wrapper& other) + { + for (size_t i = 0; i < SIZE; ++i) + { + std::swap(ARRAY_[i], other.begin()[i]); + } + } + }; + + //************************************************************************* + /// Equality for array wrappers. + //************************************************************************* + template + bool operator == (const etl::array_wrapper& lhs, + const etl::array_wrapper& rhs) + { + return (SIZEL == SIZER) && std::equal(lhs.begin(), lhs.end(), rhs.begin()); + } + + //************************************************************************* + /// Inequality for array wrapper. + //************************************************************************* + template + bool operator != (const etl::array_wrapper& lhs, + const etl::array_wrapper& rhs) + { + return !(lhs == rhs); + } + + //************************************************************************* + /// Less-than for array wrapper. + //************************************************************************* + template + bool operator < (const etl::array_wrapper& lhs, + const etl::array_wrapper& rhs) + { + return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); + } + + //************************************************************************* + /// Greater-than for array wrapper. + //************************************************************************* + template + bool operator > (const etl::array_wrapper& lhs, + const etl::array_wrapper& rhs) + { + return rhs < lhs; + } + + //************************************************************************* + /// Less-than-equal for array wrapper. + //************************************************************************* + template + bool operator <= (const etl::array_wrapper& lhs, + const etl::array_wrapper& rhs) + { + return !(lhs > rhs); + } + + //************************************************************************* + /// Greater-than-equal for array wrapper. + //************************************************************************* + template + bool operator >= (const etl::array_wrapper& lhs, + const etl::array_wrapper& rhs) + { + return !(lhs < rhs); + } + + //************************************************************************* + /// Hash function. + //************************************************************************* +#if ETL_8BIT_SUPPORT + template + struct hash > + { + size_t operator()(const etl::array_wrapper& aw) const + { + return etl::__private_hash__::generic_hash(reinterpret_cast(&aw[0]), + reinterpret_cast(&aw[aw.size()])); + } + }; +#endif +} + +//************************************************************************* +/// Swap. +//************************************************************************* +template +void swap(etl::array_wrapper& lhs, + etl::array_wrapper& rhs) +{ + lhs.swap(rhs); +} + +#define ETL_ARRAY_WRAPPER(arraytype, arrayobject) etl::array_wrapper + +#undef ETL_FILE + +#endif + diff --git a/src/container.h b/src/container.h index 961ed90f..93b2936a 100644 --- a/src/container.h +++ b/src/container.h @@ -295,5 +295,7 @@ namespace etl char(&array_size(T(&array)[ARRAY_SIZE]))[ARRAY_SIZE]; } +#define ETL_ARRAY_SIZE(a) sizeof(etl::array_size(a)) + #endif diff --git a/src/platform.h b/src/platform.h index cfe38897..9c1487fa 100644 --- a/src/platform.h +++ b/src/platform.h @@ -40,4 +40,10 @@ SOFTWARE. #include "etl_profile.h" +#if ETL_CPP11_SUPPORTED + #define ETL_CONSTEXPR constexpr +#else + #define ETL_CONSTEXPR +#endif + #endif diff --git a/test/test_array_wrapper.cpp b/test/test_array_wrapper.cpp new file mode 100644 index 00000000..8d798b67 --- /dev/null +++ b/test/test_array_wrapper.cpp @@ -0,0 +1,564 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2017 jwellbelove + +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 "UnitTest++.h" + +#include "array_wrapper.h" + +namespace +{ + int data5[] = { 0, 1, 2, 3, 4 }; + int data5b[] = { 100, 100, 100, 100, 100 }; + int data5c[] = { 0, 1, 2, 3, 4 }; + int data5d[] = { 100, 100, 100, 100, 100 }; + extern const int data5same[] = { 0, 1, 2, 3, 4 }; + extern const int data5greater[] = { 0, 1, 5, 3, 4 }; + extern const int data5smaller[] = { 0, 1, 1, 3, 4 }; + extern const int data4[] = { 0, 1, 2, 3 }; + extern const int data6[] = { 0, 1, 2, 3, 4, 5 }; + extern const int cdata5[] = { 5, 6, 7, 8, 9 }; + + typedef ETL_ARRAY_WRAPPER(int, data5) Data5; + typedef ETL_ARRAY_WRAPPER(int, data5b) Data5b; + typedef ETL_ARRAY_WRAPPER(int, data5c) Data5c; + typedef ETL_ARRAY_WRAPPER(int, data5d) Data5d; + typedef ETL_ARRAY_WRAPPER(const int, data5same) Data5Same; + typedef ETL_ARRAY_WRAPPER(const int, data5greater) Data5Greater; + typedef ETL_ARRAY_WRAPPER(const int, data5smaller) Data5Smaller; + typedef ETL_ARRAY_WRAPPER(const int, cdata5) CData5; + typedef ETL_ARRAY_WRAPPER(const int, data4) Data4; + typedef ETL_ARRAY_WRAPPER(const int, data6) Data6; + + int temp; + + void Save(int i) + { + temp = i; + } + + void Restore(int& i) + { + i = temp; + } + + SUITE(test_array_wrapper) + { + //************************************************************************* + TEST(test_constructor) + { + Data5 aw5; + CHECK_ARRAY_EQUAL(data5, aw5.data(), aw5.size()); + + const Data5 caw5a; + CHECK_ARRAY_EQUAL(data5, caw5a.data(), caw5a.size()); + + CData5 caw5b; + CHECK_ARRAY_EQUAL(cdata5, caw5b.data(), caw5b.size()); + } + + //************************************************************************* + TEST(test_indexes) + { + CHECK_EQUAL(5, Data5::SIZE); + CHECK_EQUAL(Data5::SIZE, Data5::MAX_SIZE); + CHECK_EQUAL(0, Data5::FRONT); + CHECK_EQUAL(Data5::SIZE - 1, Data5::BACK); + CHECK_EQUAL(0, Data5::BEGIN); + CHECK_EQUAL(Data5::SIZE, Data5::END); + CHECK_EQUAL(Data5::SIZE - 1, Data5::RBEGIN); + CHECK_EQUAL(Data5::BEGIN - 1, Data5::REND); + } + + //************************************************************************* + TEST(test_at) + { + Data5 aw5; + + CHECK_EQUAL(data5[2], aw5.at(2)); + + Save(data5[2]); + aw5.at(2) = 100; + CHECK_EQUAL(100, data5[2]); + CHECK_EQUAL(100, aw5.at(2)); + Restore(data5[2]); + + CHECK_THROW(aw5.at(aw5.size()), etl::array_wrapper_bounds); + } + + //************************************************************************* + TEST(test_at_const) + { + const Data5 caw5a; // array_wrapper is const. + CData5 caw5b; // array wrapped by array_wrapper is const. + + CHECK_EQUAL(data5[2], caw5a.at(2)); + CHECK_EQUAL(cdata5[2], caw5b.at(2)); + + CHECK_THROW(caw5a.at(caw5a.size()), etl::array_wrapper_bounds); + + // These lines should fail to compile. + // caw5a.at(2) = 100; + // caw5b.at(100) = 100; + } + + //************************************************************************* + TEST(test_index_operator) + { + Data5 aw5; + + CHECK_EQUAL(data5[2], aw5[2]); + + Save(data5[2]); + aw5[2] = 100; + CHECK_EQUAL(100, data5[2]); + CHECK_EQUAL(100, aw5[2]); + Restore(data5[2]); + } + + //************************************************************************* + TEST(test_index_operator_const) + { + const Data5 caw5a; // array_wrapper is const. + CData5 caw5b; // array wrapped by array_wrapper is const. + + CHECK_EQUAL(data5[2], caw5a[2]); + CHECK_EQUAL(cdata5[2], caw5b[2]); + + // These lines should fail to compile. + // caw5a[2] = 100; + // caw5b[100] = 100; + } + + //************************************************************************* + TEST(test_front) + { + Data5 aw5; + CHECK_EQUAL(data5[Data5::FRONT], aw5.front()); + } + + //************************************************************************* + TEST(test_front_const) + { + const Data5 caw5; + CHECK_EQUAL(data5[Data5::FRONT], caw5.front()); + + CData5 caw5b; + CHECK_EQUAL(cdata5[Data5::FRONT], caw5b.front()); + } + + //************************************************************************* + TEST(test_back) + { + Data5 aw5; + CHECK_EQUAL(data5[Data5::BACK], aw5.back()); + } + + //************************************************************************* + TEST(test_back_const) + { + const Data5 caw5a; + CHECK_EQUAL(data5[Data5::BACK], caw5a.back()); + + CData5 caw5b; + CHECK_EQUAL(cdata5[CData5::BACK], caw5b.back()); + } + + //************************************************************************* + TEST(test_data) + { + Data5 aw5; + CHECK_EQUAL(data5, aw5.data()); + } + + //************************************************************************* + TEST(test_data_const) + { + const Data5 caw5a; + CHECK_EQUAL(data5, caw5a.data()); + + CData5 caw5b; + CHECK_EQUAL(cdata5, caw5b.data()); + } + + //************************************************************************* + TEST(test_begin) + { + Data5 aw5; + + CHECK_EQUAL(0, Data5::BEGIN); + CHECK_EQUAL(data5, aw5.begin()); + } + + //************************************************************************* + TEST(test_begin_const) + { + const Data5 caw5a; + CHECK_EQUAL(data5, caw5a.begin()); + CHECK_EQUAL(data5, caw5a.cbegin()); + + CData5 caw5b; + CHECK_EQUAL(cdata5, caw5b.begin()); + CHECK_EQUAL(cdata5, caw5b.cbegin()); + } + + //************************************************************************* + TEST(test_end) + { + Data5 aw5; + CHECK_EQUAL(&data5[Data5::END], aw5.end()); + } + + //************************************************************************* + TEST(test_end_const) + { + const Data5 caw5a; + CHECK_EQUAL(&data5[Data5::END], caw5a.end()); + CHECK_EQUAL(&data5[Data5::END], caw5a.cend()); + + CData5 caw5b; + CHECK_EQUAL(&cdata5[CData5::END], caw5b.end()); + CHECK_EQUAL(&cdata5[CData5::END], caw5b.cend()); + } + + //************************************************************************* + TEST(test_rbegin) + { + Data5 aw5; + CHECK_EQUAL(&data5[Data5::RBEGIN], &*aw5.rbegin()); + } + + //************************************************************************* + TEST(test_rend) + { + Data5 aw5; + CHECK_EQUAL(&data5[Data5::REND], &*aw5.rend()); + } + + //************************************************************************* + TEST(test_crbegin) + { + Data5 aw5; + CHECK_EQUAL(&data5[Data5::RBEGIN], &*aw5.crbegin()); + } + + //************************************************************************* + TEST(test_crend) + { + const Data5 caw5a; + CHECK_EQUAL(&data5[Data5::REND], &*caw5a.rend()); + CHECK_EQUAL(&data5[Data5::REND], &*caw5a.crend()); + + CData5 caw5b; + CHECK_EQUAL(&cdata5[CData5::REND], &*caw5b.rend()); + CHECK_EQUAL(&cdata5[CData5::REND], &*caw5b.crend()); + } + + //************************************************************************* + TEST(test_iterator) + { + Data5 aw5; + Data5::iterator itr = aw5.begin(); + int* p = data5; + + while (p != &data5[Data5::END]) + { + CHECK_EQUAL(*p, *itr); + ++p; + ++itr; + } + + Save(data5[2]); + itr = aw5.begin() + 2; + *itr = 100; + CHECK_EQUAL(100, data5[2]); + Restore(data5[2]); + } + + //************************************************************************* + TEST(test_const_iterator) + { + const Data5 caw5a; + Data5::const_iterator itr = caw5a.begin(); + int* p = data5; + + while (p != &data5[Data5::END]) + { + CHECK_EQUAL(*p, *itr); + ++p; + ++itr; + } + + // These lines should fail to compile. + // *itr = 100; + } + + //************************************************************************* + TEST(test_reverse_iterator) + { + Data5 aw5; + Data5::reverse_iterator itr = aw5.rbegin(); + int* p = &data5[Data5::RBEGIN]; + + while (p != &data5[Data5::REND]) + { + CHECK_EQUAL(*p, *itr); + --p; + ++itr; + } + + Save(data5[2]); + itr = aw5.rbegin() + 2; + *itr = 100; + CHECK_EQUAL(100, data5[2]); + Restore(data5[2]); + } + + //************************************************************************* + TEST(test_const_reverse_iterator) + { + Data5 aw5; + Data5::const_reverse_iterator itr = aw5.crbegin(); + int* p = &data5[Data5::RBEGIN]; + + while (p != &data5[Data5::REND]) + { + CHECK_EQUAL(*p, *itr); + --p; + ++itr; + } + } + + //************************************************************************* + TEST(test_size) + { + Data5 aw5; + CHECK_EQUAL(5, aw5.SIZE); + CHECK_EQUAL(5, aw5.size()); + + const Data5 caw5a; + CHECK_EQUAL(5, caw5a.SIZE); + CHECK_EQUAL(5, caw5a.size()); + + CData5 caw5b; + CHECK_EQUAL(5, caw5b.SIZE); + CHECK_EQUAL(5, caw5b.size()); + } + + //************************************************************************* + TEST(test_max_size) + { + Data5 aw5; + CHECK_EQUAL(5, aw5.MAX_SIZE); + CHECK_EQUAL(5, aw5.max_size()); + + const Data5 caw5a; + CHECK_EQUAL(5, caw5a.MAX_SIZE); + CHECK_EQUAL(5, caw5a.max_size()); + + CData5 caw5b; + CHECK_EQUAL(5, caw5b.MAX_SIZE); + CHECK_EQUAL(5, caw5b.max_size()); + } + + //************************************************************************* + TEST(test_fill) + { + Data5 aw5; + Data5Same aw5same; + + aw5.fill(100); + CHECK_ARRAY_EQUAL(data5b, aw5.data(), Data5::SIZE); + + std::copy(aw5same.begin(), aw5same.end(), aw5.begin()); + } + + //************************************************************************* + TEST(test_swap) + { + Data5 aw5; + Data5b aw5b; + Data5c aw5c; + Data5d aw5d; + + swap(aw5, aw5b); + + CHECK_ARRAY_EQUAL(aw5d.begin(), aw5.begin(), aw5.size()); + CHECK_ARRAY_EQUAL(aw5c.begin(), aw5b.begin(), aw5b.size()); + + // Put them back. + swap(aw5, aw5b); + } + + //************************************************************************* + TEST(test_equal) + { + Data5 aw5; + Data5Same aw5same; + Data5Greater aw5greater; + Data5Smaller aw5smaller; + Data4 aw4; + Data6 aw6; + + CHECK(aw5 == aw5same); + CHECK(!(aw5 == aw5greater)); + CHECK(!(aw5 == aw5smaller)); + CHECK(!(aw5 == aw4)); + CHECK(!(aw5 == aw6)); + } + + //************************************************************************* + TEST(test_not_equal) + { + Data5 aw5; + Data5Same aw5same; + Data5Greater aw5greater; + Data5Smaller aw5smaller; + Data4 aw4; + Data6 aw6; + + CHECK(!(aw5 != aw5same)); + CHECK(aw5 != aw5greater); + CHECK(aw5 != aw5smaller); + CHECK(aw5 != aw4); + CHECK(aw5 != aw6); + } + + //************************************************************************* + TEST(test_less_than) + { + Data5 aw5; + Data5Same aw5same; + Data5Greater aw5greater; + Data5Smaller aw5smaller; + Data4 aw4; + Data6 aw6; + + CHECK(!(aw5 < aw5same)); + CHECK(!(aw5same < aw5)); + + CHECK(aw5 < aw5greater); + CHECK(!(aw5greater < aw5)); + + CHECK(!(aw5 < aw5smaller)); + CHECK(aw5smaller < aw5); + + CHECK(!(aw5 < aw4)); + CHECK(aw4 < aw5); + + CHECK(aw5 < aw6); + CHECK(!(aw6 < aw5)); + } + + //************************************************************************* + TEST(test_less_than_equal) + { + Data5 aw5; + Data5Same aw5same; + Data5Greater aw5greater; + Data5Smaller aw5smaller; + Data4 aw4; + Data6 aw6; + + CHECK(aw5 <= aw5same); + CHECK(aw5same <= aw5); + + CHECK(aw5 <= aw5greater); + CHECK(!(aw5greater <= aw5)); + + CHECK(!(aw5 <= aw5smaller)); + CHECK(aw5smaller <= aw5); + + CHECK(!(aw5 <= aw4)); + CHECK(aw4 <= aw5); + + CHECK(aw5 <= aw6); + CHECK(!(aw6 <= aw5)); + } + + //************************************************************************* + TEST(test_greater_than) + { + Data5 aw5; + Data5Same aw5same; + Data5Greater aw5greater; + Data5Smaller aw5smaller; + Data4 aw4; + Data6 aw6; + + CHECK(!(aw5 > aw5same)); + CHECK(!(aw5same > aw5)); + + CHECK(!(aw5 > aw5greater)); + CHECK(aw5greater > aw5); + + CHECK(aw5 > aw5smaller); + CHECK(!(aw5smaller > aw5)); + + CHECK(aw5 > aw4); + CHECK(!(aw4 > aw5)); + + CHECK(!(aw5 > aw6)); + CHECK(aw6 > aw5); + } + + //************************************************************************* + TEST(test_greater_than_equal) + { + Data5 aw5; + Data5Same aw5same; + Data5Greater aw5greater; + Data5Smaller aw5smaller; + Data4 aw4; + Data6 aw6; + + CHECK(aw5 >= aw5same); + CHECK(aw5same >= aw5); + + CHECK(!(aw5 >= aw5greater)); + CHECK(aw5greater >= aw5); + + CHECK(aw5 >= aw5smaller); + CHECK(!(aw5smaller >= aw5)); + + CHECK(aw5 >= aw4); + CHECK(!(aw4 >= aw5)); + + CHECK(!(aw5 >= aw6)); + CHECK(aw6 >= aw5); + } + + //************************************************************************* + TEST(test_hash) + { + Data5 aw5; + size_t hash = etl::hash()(aw5); + size_t compare_hash = etl::fnv_1a_32(reinterpret_cast(&data5[0]), reinterpret_cast(&data5[5])); + CHECK_EQUAL(compare_hash, hash); + } + }; +} diff --git a/test/vs2017/etl.vcxproj b/test/vs2017/etl.vcxproj index cef80540..d8de307b 100644 --- a/test/vs2017/etl.vcxproj +++ b/test/vs2017/etl.vcxproj @@ -133,6 +133,7 @@ + @@ -342,6 +343,7 @@ false + diff --git a/test/vs2017/etl.vcxproj.filters b/test/vs2017/etl.vcxproj.filters index 4ddc59f6..baca3942 100644 --- a/test/vs2017/etl.vcxproj.filters +++ b/test/vs2017/etl.vcxproj.filters @@ -567,6 +567,9 @@ ETL\Containers + + ETL\Containers + @@ -947,6 +950,9 @@ Source Files + + Source Files + From 1b61672eb36d85e60bc08e6f70f7a8287bd4af63 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 21 Jan 2018 20:38:37 +0000 Subject: [PATCH 03/50] Array wrapper and unit tests --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 2fd7a984..1189cdbe 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=10.9.1 +version=10.10.0 author= John Wellbelove maintainer=John Wellbelove sentence=A C++ template library tailored for embedded systems. From 4cb02cb6df2e87a7b7eff68aa048eedd77a4fb95 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 22 Jan 2018 09:07:25 +0000 Subject: [PATCH 04/50] Added shift version of XOR checksum XOR: sum = sum ^ value XOR-shift sum = etl::rotate_left(sum) ^ value --- src/checksum.h | 53 +++++++++++ test/test_xor_shift_checksum.cpp | 149 +++++++++++++++++++++++++++++++ test/vs2017/etl.vcxproj | 1 + test/vs2017/etl.vcxproj.filters | 3 + 4 files changed, 206 insertions(+) create mode 100644 test/test_xor_shift_checksum.cpp diff --git a/src/checksum.h b/src/checksum.h index d981400a..e6484583 100644 --- a/src/checksum.h +++ b/src/checksum.h @@ -110,6 +110,30 @@ namespace etl } }; + //*************************************************************************** + /// XOR-shift checksum policy. + //*************************************************************************** + template + struct checksum_policy_xor_shift + { + typedef T value_type; + + inline T initial() const + { + return 0; + } + + inline T add(T sum, uint8_t value) const + { + return etl::rotate_left(sum) ^ value; + } + + inline T final(T sum) const + { + return sum; + } + }; + //************************************************************************* /// Standard Checksum. //************************************************************************* @@ -196,6 +220,35 @@ namespace etl this->add(begin, end); } }; + + //************************************************************************* + /// XOR-shift Checksum. + //************************************************************************* + template + class xor_shift_checksum : public etl::frame_check_sequence > + { + public: + + //************************************************************************* + /// Default constructor. + //************************************************************************* + xor_shift_checksum() + { + this->reset(); + } + + //************************************************************************* + /// Constructor from range. + /// \param begin Start of the range. + /// \param end End of the range. + //************************************************************************* + template + xor_shift_checksum(TIterator begin, const TIterator end) + { + this->reset(); + this->add(begin, end); + } + }; } #endif diff --git a/test/test_xor_shift_checksum.cpp b/test/test_xor_shift_checksum.cpp new file mode 100644 index 00000000..2132569f --- /dev/null +++ b/test/test_xor_shift_checksum.cpp @@ -0,0 +1,149 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +http://www.etlcpp.com + +Copyright(c) 2017 jwellbelove + +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 "UnitTest++.h" + +#include +#include +#include +#include + +#include "checksum.h" + +namespace +{ + template + TSum reference_checksum(TIterator begin, TIterator end) + { + typedef typename std::iterator_traits::value_type value_type; + TSum checksum = 0; + + while (begin != end) + { + value_type value = *begin++; + checksum = etl::rotate_left(checksum) ^ value; + } + + return checksum; + } + + SUITE(test_checksum) + { + //************************************************************************* + TEST(test_checksum_constructor) + { + std::string data("123456789"); + + uint8_t sum = etl::xor_shift_checksum(data.begin(), data.end()); + uint8_t compare = reference_checksum(data.begin(), data.end()); + + CHECK_EQUAL(int(compare), int(sum)); + } + + //************************************************************************* + TEST(test_checksum_add_values8_add) + { + std::string data("123456789"); + + etl::xor_shift_checksum checksum_calculator; + + for (size_t i = 0; i < data.size(); ++i) + { + checksum_calculator.add(data[i]); + } + + uint8_t sum = checksum_calculator; + uint8_t compare = reference_checksum(data.begin(), data.end()); + + CHECK_EQUAL(int(compare), int(sum)); + } + + //************************************************************************* + TEST(test_checksum_add_values8_operator_plus_equals) + { + std::string data("123456789"); + + etl::xor_shift_checksum checksum_calculator; + + for (size_t i = 0; i < data.size(); ++i) + { + checksum_calculator.add(data[i]); + } + + uint8_t sum = checksum_calculator; + uint8_t compare = reference_checksum(data.begin(), data.end()); + + CHECK_EQUAL(int(compare), int(sum)); + } + + //************************************************************************* + TEST(test_checksum_add_range) + { + std::string data("123456789"); + + etl::xor_shift_checksum checksum_calculator; + + checksum_calculator.add(data.begin(), data.end()); + + uint8_t sum = checksum_calculator.value(); + uint8_t compare = reference_checksum(data.begin(), data.end()); + + CHECK_EQUAL(int(compare), int(sum)); + } + + //************************************************************************* + TEST(test_checksum_add_range_sum32) + { + std::string data("1"); + + etl::xor_shift_checksum checksum_calculator; + + checksum_calculator.add(data.begin(), data.end()); + + uint32_t sum = checksum_calculator.value(); + uint32_t compare = reference_checksum(data.begin(), data.end()); + + CHECK_EQUAL(compare, sum); + } + + //************************************************************************* + TEST(test_checksum_add_range_endian) + { + std::vector data1 = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }; + std::vector data2 = { 0x04030201, 0x08070605 }; + std::vector data3 = { 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 }; + + uint64_t hash1 = etl::xor_shift_checksum(data1.begin(), data1.end()); + uint64_t hash2 = etl::xor_shift_checksum((uint8_t*)&data2[0], (uint8_t*)&data2[0] + (data2.size() * sizeof(uint32_t))); + uint64_t hash3 = etl::xor_shift_checksum(data3.rbegin(), data3.rend()); + CHECK_EQUAL(hash1, hash2); + CHECK_EQUAL(hash1, hash3); + } + }; +} + diff --git a/test/vs2017/etl.vcxproj b/test/vs2017/etl.vcxproj index d8de307b..a1168d71 100644 --- a/test/vs2017/etl.vcxproj +++ b/test/vs2017/etl.vcxproj @@ -467,6 +467,7 @@ + diff --git a/test/vs2017/etl.vcxproj.filters b/test/vs2017/etl.vcxproj.filters index baca3942..660b08d3 100644 --- a/test/vs2017/etl.vcxproj.filters +++ b/test/vs2017/etl.vcxproj.filters @@ -953,6 +953,9 @@ Source Files + + Source Files + From 48df943aa07c096387d16dce66473066d859df56 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 23 Jan 2018 08:20:46 +0000 Subject: [PATCH 05/50] Renamed xor_shift to xor_rotate --- src/checksum.h | 10 +++++----- ...ecksum.cpp => test_xor_rotate_checksum.cpp} | 18 +++++++++--------- test/vs2017/etl.vcxproj | 2 +- test/vs2017/etl.vcxproj.filters | 2 +- 4 files changed, 16 insertions(+), 16 deletions(-) rename test/{test_xor_shift_checksum.cpp => test_xor_rotate_checksum.cpp} (86%) diff --git a/src/checksum.h b/src/checksum.h index e6484583..9a2a6069 100644 --- a/src/checksum.h +++ b/src/checksum.h @@ -111,10 +111,10 @@ namespace etl }; //*************************************************************************** - /// XOR-shift checksum policy. + /// XOR-rotate checksum policy. //*************************************************************************** template - struct checksum_policy_xor_shift + struct checksum_policy_xor_rotate { typedef T value_type; @@ -225,14 +225,14 @@ namespace etl /// XOR-shift Checksum. //************************************************************************* template - class xor_shift_checksum : public etl::frame_check_sequence > + class xor_rotate_checksum : public etl::frame_check_sequence > { public: //************************************************************************* /// Default constructor. //************************************************************************* - xor_shift_checksum() + xor_rotate_checksum() { this->reset(); } @@ -243,7 +243,7 @@ namespace etl /// \param end End of the range. //************************************************************************* template - xor_shift_checksum(TIterator begin, const TIterator end) + xor_rotate_checksum(TIterator begin, const TIterator end) { this->reset(); this->add(begin, end); diff --git a/test/test_xor_shift_checksum.cpp b/test/test_xor_rotate_checksum.cpp similarity index 86% rename from test/test_xor_shift_checksum.cpp rename to test/test_xor_rotate_checksum.cpp index 2132569f..43f50436 100644 --- a/test/test_xor_shift_checksum.cpp +++ b/test/test_xor_rotate_checksum.cpp @@ -3,7 +3,7 @@ The MIT License(MIT) Embedded Template Library. https://github.com/ETLCPP/etl -http://www.etlcpp.com +https://www.etlcpp.com Copyright(c) 2017 jwellbelove @@ -59,7 +59,7 @@ namespace { std::string data("123456789"); - uint8_t sum = etl::xor_shift_checksum(data.begin(), data.end()); + uint8_t sum = etl::xor_rotate_checksum(data.begin(), data.end()); uint8_t compare = reference_checksum(data.begin(), data.end()); CHECK_EQUAL(int(compare), int(sum)); @@ -70,7 +70,7 @@ namespace { std::string data("123456789"); - etl::xor_shift_checksum checksum_calculator; + etl::xor_rotate_checksum checksum_calculator; for (size_t i = 0; i < data.size(); ++i) { @@ -88,7 +88,7 @@ namespace { std::string data("123456789"); - etl::xor_shift_checksum checksum_calculator; + etl::xor_rotate_checksum checksum_calculator; for (size_t i = 0; i < data.size(); ++i) { @@ -106,7 +106,7 @@ namespace { std::string data("123456789"); - etl::xor_shift_checksum checksum_calculator; + etl::xor_rotate_checksum checksum_calculator; checksum_calculator.add(data.begin(), data.end()); @@ -121,7 +121,7 @@ namespace { std::string data("1"); - etl::xor_shift_checksum checksum_calculator; + etl::xor_rotate_checksum checksum_calculator; checksum_calculator.add(data.begin(), data.end()); @@ -138,9 +138,9 @@ namespace std::vector data2 = { 0x04030201, 0x08070605 }; std::vector data3 = { 0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01 }; - uint64_t hash1 = etl::xor_shift_checksum(data1.begin(), data1.end()); - uint64_t hash2 = etl::xor_shift_checksum((uint8_t*)&data2[0], (uint8_t*)&data2[0] + (data2.size() * sizeof(uint32_t))); - uint64_t hash3 = etl::xor_shift_checksum(data3.rbegin(), data3.rend()); + uint64_t hash1 = etl::xor_rotate_checksum(data1.begin(), data1.end()); + uint64_t hash2 = etl::xor_rotate_checksum((uint8_t*)&data2[0], (uint8_t*)&data2[0] + (data2.size() * sizeof(uint32_t))); + uint64_t hash3 = etl::xor_rotate_checksum(data3.rbegin(), data3.rend()); CHECK_EQUAL(hash1, hash2); CHECK_EQUAL(hash1, hash3); } diff --git a/test/vs2017/etl.vcxproj b/test/vs2017/etl.vcxproj index a1168d71..fca63a9b 100644 --- a/test/vs2017/etl.vcxproj +++ b/test/vs2017/etl.vcxproj @@ -467,7 +467,7 @@ - + diff --git a/test/vs2017/etl.vcxproj.filters b/test/vs2017/etl.vcxproj.filters index 660b08d3..dea71e14 100644 --- a/test/vs2017/etl.vcxproj.filters +++ b/test/vs2017/etl.vcxproj.filters @@ -953,7 +953,7 @@ Source Files - + Source Files From c58a6d3c42b1ba0cfa9abfb9f5d67e07de9dc891 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 23 Jan 2018 09:21:34 +0000 Subject: [PATCH 06/50] Added ETL_CONSTEXPR prefix to all functions --- src/container.h | 58 ++++++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 27 deletions(-) diff --git a/src/container.h b/src/container.h index 93b2936a..9ce23b60 100644 --- a/src/container.h +++ b/src/container.h @@ -46,7 +46,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - typename TContainer::iterator begin(TContainer& container) + ETL_CONSTEXPR typename TContainer::iterator begin(TContainer& container) { return container.begin(); } @@ -56,7 +56,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - typename TContainer::const_iterator begin(const TContainer& container) + ETL_CONSTEXPR typename TContainer::const_iterator begin(const TContainer& container) { return container.begin(); } @@ -66,7 +66,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - typename TContainer::const_iterator cbegin(const TContainer& container) + ETL_CONSTEXPR typename TContainer::const_iterator cbegin(const TContainer& container) { return container.cbegin(); } @@ -76,7 +76,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - typename TContainer::reverse_iterator rbegin(const TContainer& container) + ETL_CONSTEXPR typename TContainer::reverse_iterator rbegin(const TContainer& container) { return container.rbegin(); } @@ -86,7 +86,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - typename TContainer::reverse_iterator crbegin(const TContainer& container) + ETL_CONSTEXPR typename TContainer::reverse_iterator crbegin(const TContainer& container) { return container.crbegin(); } @@ -96,7 +96,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - typename TContainer::iterator end(TContainer& container) + ETL_CONSTEXPR typename TContainer::iterator end(TContainer& container) { return container.end(); } @@ -106,7 +106,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - typename TContainer::const_iterator end(const TContainer& container) + ETL_CONSTEXPR typename TContainer::const_iterator end(const TContainer& container) { return container.end(); } @@ -116,7 +116,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - typename TContainer::const_iterator cend(const TContainer& container) + ETL_CONSTEXPR typename TContainer::const_iterator cend(const TContainer& container) { return container.cend(); } @@ -126,7 +126,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - typename TContainer::const_iterator rend(const TContainer& container) + ETL_CONSTEXPR typename TContainer::const_iterator rend(const TContainer& container) { return container.rend(); } @@ -136,7 +136,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - typename TContainer::reverse_iterator crend(const TContainer& container) + ETL_CONSTEXPR typename TContainer::reverse_iterator crend(const TContainer& container) { return container.crend(); } @@ -146,7 +146,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - TValue* begin(TValue(&data)[ARRAY_SIZE]) + ETL_CONSTEXPR TValue* begin(TValue(&data)[ARRAY_SIZE]) { return &data[0]; } @@ -156,7 +156,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - const TValue* begin(const TValue(&data)[ARRAY_SIZE]) + ETL_CONSTEXPR const TValue* begin(const TValue(&data)[ARRAY_SIZE]) { return &data[0]; } @@ -166,7 +166,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - const TValue* cbegin(const TValue(&data)[ARRAY_SIZE]) + ETL_CONSTEXPR const TValue* cbegin(const TValue(&data)[ARRAY_SIZE]) { return &data[0]; } @@ -176,7 +176,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - std::reverse_iterator rbegin(const TValue(&data)[ARRAY_SIZE]) + ETL_CONSTEXPR std::reverse_iterator rbegin(const TValue(&data)[ARRAY_SIZE]) { return std::reverse_iterator(&data[ARRAY_SIZE]); } @@ -186,7 +186,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - std::reverse_iterator crbegin(const TValue(&data)[ARRAY_SIZE]) + ETL_CONSTEXPR std::reverse_iterator crbegin(const TValue(&data)[ARRAY_SIZE]) { return std::reverse_iterator(&data[ARRAY_SIZE]); } @@ -196,7 +196,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - TValue* end(TValue(&data)[ARRAY_SIZE]) + ETL_CONSTEXPR TValue* end(TValue(&data)[ARRAY_SIZE]) { return &data[ARRAY_SIZE]; } @@ -206,7 +206,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - const TValue* end(const TValue(&data)[ARRAY_SIZE]) + ETL_CONSTEXPR const TValue* end(const TValue(&data)[ARRAY_SIZE]) { return &data[ARRAY_SIZE]; } @@ -216,7 +216,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - const TValue* cend(const TValue(&data)[ARRAY_SIZE]) + ETL_CONSTEXPR const TValue* cend(const TValue(&data)[ARRAY_SIZE]) { return &data[ARRAY_SIZE]; } @@ -226,7 +226,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - std::reverse_iterator rend(const TValue(&data)[ARRAY_SIZE]) + ETL_CONSTEXPR std::reverse_iterator rend(const TValue(&data)[ARRAY_SIZE]) { return std::reverse_iterator(&data[0]); } @@ -236,7 +236,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - std::reverse_iterator crend(const TValue(&data)[ARRAY_SIZE]) + ETL_CONSTEXPR std::reverse_iterator crend(const TValue(&data)[ARRAY_SIZE]) { return std::reverse_iterator(&data[0]); } @@ -246,7 +246,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - TIterator next(TIterator iterator, ptrdiff_t n = 1) + ETL_CONSTEXPR TIterator next(TIterator iterator, ptrdiff_t n = 1) { std::advance(iterator, n); return iterator; @@ -257,7 +257,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - TIterator prev(TIterator iterator, ptrdiff_t n = 1) + ETL_CONSTEXPR TIterator prev(TIterator iterator, ptrdiff_t n = 1) { std::advance(iterator, -n); return iterator; @@ -269,23 +269,23 @@ namespace etl ///\ingroup container ///************************************************************************** template - typename TContainer::size_type size(const TContainer& container) + ETL_CONSTEXPR typename TContainer::size_type size(const TContainer& container) { return container.size(); } ///************************************************************************** - /// Get the size of an array in elements at run time. + /// Get the size of an array in elements at run time, or compile time if C++11 or above. ///\ingroup container ///************************************************************************** template - size_t size(TValue(&)[ARRAY_SIZE]) + ETL_CONSTEXPR size_t size(TValue(&)[ARRAY_SIZE]) { return ARRAY_SIZE; } ///************************************************************************** - /// Get the size of an array in elements at compile time. + /// Get the size of an array in elements at compile time for C++03 ///\code /// sizeof(array_size(array)) ///\endcode @@ -295,7 +295,11 @@ namespace etl char(&array_size(T(&array)[ARRAY_SIZE]))[ARRAY_SIZE]; } -#define ETL_ARRAY_SIZE(a) sizeof(etl::array_size(a)) +#if ETL_CPP11_SUPPORTED + #define ETL_ARRAY_SIZE(a) (etl::size(a)) +#else + #define ETL_ARRAY_SIZE(a) sizeof(etl::array_size(a)) +#endif #endif From 7fc874617daa39ca26936b8e5bec9e2d01f705e0 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 23 Jan 2018 09:23:36 +0000 Subject: [PATCH 07/50] Updated --- library.properties | 2 +- src/basic_string.h | 9 ++++----- src/forward_list.h | 2 +- support/Release notes.txt | 8 ++++++++ test/test_vector.cpp | 1 + 5 files changed, 15 insertions(+), 7 deletions(-) diff --git a/library.properties b/library.properties index 1189cdbe..67d5914d 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=10.10.0 +version=10.11.0 author= John Wellbelove maintainer=John Wellbelove sentence=A C++ template library tailored for embedded systems. diff --git a/src/basic_string.h b/src/basic_string.h index b27b46f4..4fde9ebd 100644 --- a/src/basic_string.h +++ b/src/basic_string.h @@ -639,11 +639,10 @@ namespace etl //************************************************************************* void pop_back() { -#if defined(ETL_CHECK_PUSH_POP) - ETL_ASSERT(!empty(), ETL_ERROR(string_empty)); -#endif - - p_buffer[--current_size] = 0; + if (current_size != 0) + { + p_buffer[--current_size] = 0; + } } //********************************************************************* diff --git a/src/forward_list.h b/src/forward_list.h index 921b40b3..2ac02e55 100644 --- a/src/forward_list.h +++ b/src/forward_list.h @@ -585,7 +585,7 @@ namespace etl // Add all of the elements. while (first != last) { - ETL_ASSERT(!full(), ETL_ERROR(forward_list_iterator)); + ETL_ASSERT(!full(), ETL_ERROR(forward_list_full)); data_node_t& data_node = allocate_data_node(*first++); join(p_last_node, &data_node); diff --git a/support/Release notes.txt b/support/Release notes.txt index cc551b9a..54c6643e 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,4 +1,12 @@ +=============================================================================== +Added ETL_CONSTEXPR macro and applied to various functions. +Allows C++11 and above compilers to set functions as constexpr. +=============================================================================== +10.10.0 +Added array_wrapper + +=============================================================================== 10.9.0 Array view diff --git a/test/test_vector.cpp b/test/test_vector.cpp index 11c1f954..23770eac 100644 --- a/test/test_vector.cpp +++ b/test/test_vector.cpp @@ -80,6 +80,7 @@ namespace CHECK(data.empty()); CHECK_EQUAL(data.capacity(), SIZE); CHECK_EQUAL(data.max_size(), SIZE); + CHECK(data.begin() == data.end()); } //************************************************************************* From 71b865ae6bd6c04e9137603abb818a2b1fd6339c Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 23 Jan 2018 12:15:12 +0000 Subject: [PATCH 08/50] GCC compatibility changes --- library.properties | 2 +- src/array_wrapper.h | 27 ++++++++++++++------------- src/container.h | 14 +++++++------- src/platform.h | 1 + src/profiles/gcc_generic.h | 9 +++++++-- src/profiles/gcc_linux_x86.h | 9 +++++++-- src/profiles/gcc_windows_x86.h | 9 +++++++-- support/Release notes.txt | 4 ++++ test/test_array_wrapper.cpp | 26 +++++++++++++------------- 9 files changed, 61 insertions(+), 40 deletions(-) diff --git a/library.properties b/library.properties index 67d5914d..feff42fd 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=10.11.0 +version=10.11.1 author= John Wellbelove maintainer=John Wellbelove sentence=A C++ template library tailored for embedded systems. diff --git a/src/array_wrapper.h b/src/array_wrapper.h index 9ada074e..ba839c38 100644 --- a/src/array_wrapper.h +++ b/src/array_wrapper.h @@ -114,7 +114,7 @@ namespace etl //************************************************************************* /// Returns a reference to the first element. //************************************************************************* - ETL_CONSTEXPR reference front() + reference front() { return *&ARRAY_[FRONT]; } @@ -130,7 +130,7 @@ namespace etl //************************************************************************* /// Returns a reference to the last element. //************************************************************************* - ETL_CONSTEXPR reference back() + reference back() { return *&ARRAY_[BACK]; } @@ -146,7 +146,7 @@ namespace etl //************************************************************************* /// Returns a pointer to the first element of the internal storage. //************************************************************************* - ETL_CONSTEXPR pointer data() + pointer data() { return &ARRAY_[BEGIN]; } @@ -162,7 +162,7 @@ namespace etl //************************************************************************* /// Returns an iterator to the beginning of the array. //************************************************************************* - ETL_CONSTEXPR iterator begin() + iterator begin() { return &ARRAY_[BEGIN]; } @@ -186,7 +186,7 @@ namespace etl //************************************************************************* /// Returns an iterator to the end of the array. //************************************************************************* - ETL_CONSTEXPR iterator end() + iterator end() { return &ARRAY_[END]; } @@ -210,7 +210,7 @@ namespace etl //************************************************************************* // Returns an reverse iterator to the reverse beginning of the array. //************************************************************************* - ETL_CONSTEXPR reverse_iterator rbegin() + reverse_iterator rbegin() { return reverse_iterator(&ARRAY_[END]); } @@ -234,7 +234,7 @@ namespace etl //************************************************************************* /// Returns a reverse iterator to the end of the array. //************************************************************************* - ETL_CONSTEXPR reverse_iterator rend() + reverse_iterator rend() { return reverse_iterator(&ARRAY_[BEGIN]); } @@ -274,7 +274,7 @@ namespace etl //************************************************************************* /// Returns a reference to the indexed value. //************************************************************************* - ETL_CONSTEXPR reference operator[](size_t i) + reference operator[](size_t i) { return ARRAY_[i]; } @@ -290,7 +290,7 @@ namespace etl //************************************************************************* /// Returns a reference to the indexed value. //************************************************************************* - ETL_CONSTEXPR reference at(size_t i) + reference at(size_t i) { ETL_ASSERT(i < SIZE, ETL_ERROR(etl::array_wrapper_bounds)); return ARRAY_[i]; @@ -299,7 +299,7 @@ namespace etl //************************************************************************* /// Returns a const reference to the indexed value. //************************************************************************* - ETL_CONSTEXPR const_reference at(size_t i) const + const_reference at(size_t i) const { ETL_ASSERT(i < SIZE, ETL_ERROR(etl::array_wrapper_bounds)); return ARRAY_[i]; @@ -316,8 +316,9 @@ namespace etl //************************************************************************* /// Swaps the contents of arrays. //************************************************************************* - template - void swap(etl::array_wrapper& other) + template + typename etl::enable_if::value, void>::type + swap(etl::array_wrapper& other) { for (size_t i = 0; i < SIZE; ++i) { @@ -345,7 +346,7 @@ namespace etl { return !(lhs == rhs); } - + //************************************************************************* /// Less-than for array wrapper. //************************************************************************* diff --git a/src/container.h b/src/container.h index 9ce23b60..5e622566 100644 --- a/src/container.h +++ b/src/container.h @@ -240,13 +240,13 @@ namespace etl { return std::reverse_iterator(&data[0]); } - + //***************************************************************************** /// Get the next iterator. ///\ingroup container //***************************************************************************** template - ETL_CONSTEXPR TIterator next(TIterator iterator, ptrdiff_t n = 1) + TIterator next(TIterator iterator, ptrdiff_t n = 1) { std::advance(iterator, n); return iterator; @@ -257,7 +257,7 @@ namespace etl ///\ingroup container //***************************************************************************** template - ETL_CONSTEXPR TIterator prev(TIterator iterator, ptrdiff_t n = 1) + TIterator prev(TIterator iterator, ptrdiff_t n = 1) { std::advance(iterator, -n); return iterator; @@ -295,11 +295,11 @@ namespace etl char(&array_size(T(&array)[ARRAY_SIZE]))[ARRAY_SIZE]; } -#if ETL_CPP11_SUPPORTED - #define ETL_ARRAY_SIZE(a) (etl::size(a)) -#else +//#if ETL_CPP11_SUPPORTED +// #define ETL_ARRAY_SIZE(a) (etl::size(a)) +//#else #define ETL_ARRAY_SIZE(a) sizeof(etl::array_size(a)) -#endif +//#endif #endif diff --git a/src/platform.h b/src/platform.h index 9c1487fa..e50d4f19 100644 --- a/src/platform.h +++ b/src/platform.h @@ -40,6 +40,7 @@ SOFTWARE. #include "etl_profile.h" + #if ETL_CPP11_SUPPORTED #define ETL_CONSTEXPR constexpr #else diff --git a/src/profiles/gcc_generic.h b/src/profiles/gcc_generic.h index c19609e6..52b05ebf 100644 --- a/src/profiles/gcc_generic.h +++ b/src/profiles/gcc_generic.h @@ -40,8 +40,13 @@ SOFTWARE. #define ETL_TARGET_DEVICE_GENERIC #define ETL_TARGET_OS_NONE #define ETL_COMPILER_GCC -#define ETL_CPP11_SUPPORTED (__cplusplus >= 201103L) -#define ETL_CPP14_SUPPORTED (__cplusplus >= 201402L) +#ifdef __cplusplus + #define ETL_CPP11_SUPPORTED (__cplusplus >= 201103L) + #define ETL_CPP14_SUPPORTED (__cplusplus >= 201402L) +#else + #define ETL_CPP11_SUPPORTED 0 + #define ETL_CPP14_SUPPORTED 0 +#endif #define ETL_NO_NULLPTR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_NO_LARGE_CHAR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED ETL_CPP14_SUPPORTED diff --git a/src/profiles/gcc_linux_x86.h b/src/profiles/gcc_linux_x86.h index fd8af659..3a8ac812 100644 --- a/src/profiles/gcc_linux_x86.h +++ b/src/profiles/gcc_linux_x86.h @@ -40,8 +40,13 @@ SOFTWARE. #define ETL_TARGET_DEVICE_X86 #define ETL_TARGET_OS_LINUX #define ETL_COMPILER_GCC -#define ETL_CPP11_SUPPORTED (__cplusplus >= 201103L) -#define ETL_CPP14_SUPPORTED (__cplusplus >= 201402L) +#ifdef __cplusplus + #define ETL_CPP11_SUPPORTED (__cplusplus >= 201103L) + #define ETL_CPP14_SUPPORTED (__cplusplus >= 201402L) +#else + #define ETL_CPP11_SUPPORTED 0 + #define ETL_CPP14_SUPPORTED 0 +#endif #define ETL_NO_NULLPTR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_NO_LARGE_CHAR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED ETL_CPP14_SUPPORTED diff --git a/src/profiles/gcc_windows_x86.h b/src/profiles/gcc_windows_x86.h index d60fd198..a234552d 100644 --- a/src/profiles/gcc_windows_x86.h +++ b/src/profiles/gcc_windows_x86.h @@ -40,8 +40,13 @@ SOFTWARE. #define ETL_TARGET_DEVICE_X86 #define ETL_TARGET_OS_WINDOWS #define ETL_COMPILER_GCC -#define ETL_CPP11_SUPPORTED (__cplusplus >= 201103L) -#define ETL_CPP14_SUPPORTED (__cplusplus >= 201402L) +#ifdef __cplusplus + #define ETL_CPP11_SUPPORTED (__cplusplus >= 201103L) + #define ETL_CPP14_SUPPORTED (__cplusplus >= 201402L) +#else + #define ETL_CPP11_SUPPORTED 0 + #define ETL_CPP14_SUPPORTED 0 +#endif #define ETL_NO_NULLPTR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_NO_LARGE_CHAR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED ETL_CPP14_SUPPORTED diff --git a/support/Release notes.txt b/support/Release notes.txt index 54c6643e..8f8941bf 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,4 +1,8 @@ =============================================================================== +10.11.1 +GCC compatibility changes. +=============================================================================== +10.11.0 Added ETL_CONSTEXPR macro and applied to various functions. Allows C++11 and above compilers to set functions as constexpr. diff --git a/test/test_array_wrapper.cpp b/test/test_array_wrapper.cpp index 8d798b67..b4eafaaf 100644 --- a/test/test_array_wrapper.cpp +++ b/test/test_array_wrapper.cpp @@ -84,7 +84,7 @@ namespace //************************************************************************* TEST(test_indexes) { - CHECK_EQUAL(5, Data5::SIZE); + CHECK_EQUAL(5 , Data5::SIZE); CHECK_EQUAL(Data5::SIZE, Data5::MAX_SIZE); CHECK_EQUAL(0, Data5::FRONT); CHECK_EQUAL(Data5::SIZE - 1, Data5::BACK); @@ -357,32 +357,32 @@ namespace TEST(test_size) { Data5 aw5; - CHECK_EQUAL(5, aw5.SIZE); - CHECK_EQUAL(5, aw5.size()); + CHECK_EQUAL(5 , aw5.SIZE); + CHECK_EQUAL(5U, aw5.size()); const Data5 caw5a; - CHECK_EQUAL(5, caw5a.SIZE); - CHECK_EQUAL(5, caw5a.size()); + CHECK_EQUAL(5 , caw5a.SIZE); + CHECK_EQUAL(5U, caw5a.size()); CData5 caw5b; - CHECK_EQUAL(5, caw5b.SIZE); - CHECK_EQUAL(5, caw5b.size()); + CHECK_EQUAL(5 , caw5b.SIZE); + CHECK_EQUAL(5U, caw5b.size()); } //************************************************************************* TEST(test_max_size) { Data5 aw5; - CHECK_EQUAL(5, aw5.MAX_SIZE); - CHECK_EQUAL(5, aw5.max_size()); + CHECK_EQUAL(5 , aw5.MAX_SIZE); + CHECK_EQUAL(5U, aw5.max_size()); const Data5 caw5a; - CHECK_EQUAL(5, caw5a.MAX_SIZE); - CHECK_EQUAL(5, caw5a.max_size()); + CHECK_EQUAL(5 , caw5a.MAX_SIZE); + CHECK_EQUAL(5U, caw5a.max_size()); CData5 caw5b; - CHECK_EQUAL(5, caw5b.MAX_SIZE); - CHECK_EQUAL(5, caw5b.max_size()); + CHECK_EQUAL(5 , caw5b.MAX_SIZE); + CHECK_EQUAL(5U, caw5b.max_size()); } //************************************************************************* From 3385d2cf04fb2ae7b37e9bb36a1d86f1fa56e85f Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 23 Jan 2018 13:14:08 +0000 Subject: [PATCH 09/50] GCC compatibility changes --- library.properties | 2 +- src/platform.h | 8 +++++++- support/Release notes.txt | 3 +++ test/ecl_user.h | 14 ++++++-------- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/library.properties b/library.properties index feff42fd..bea30a02 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=10.11.1 +version=10.11.2 author= John Wellbelove maintainer=John Wellbelove sentence=A C++ template library tailored for embedded systems. diff --git a/src/platform.h b/src/platform.h index e50d4f19..8dd01fc9 100644 --- a/src/platform.h +++ b/src/platform.h @@ -38,8 +38,14 @@ SOFTWARE. #define ETL_DEBUG #endif -#include "etl_profile.h" +#undef ETL_CPP11_SUPPORTED +#undef ETL_CPP14_SUPPORTED +#undef ETL_NO_NULLPTR_SUPPORT +#undef ETL_NO_LARGE_CHAR_SUPPORT +#undef ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED +#undef ETL_ATOMIC_SUPPORTED +#include "etl_profile.h" #if ETL_CPP11_SUPPORTED #define ETL_CONSTEXPR constexpr diff --git a/support/Release notes.txt b/support/Release notes.txt index 8f8941bf..9613e04c 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,4 +1,7 @@ =============================================================================== +10.11.2 +GCC compatibility changes. +=============================================================================== 10.11.1 GCC compatibility changes. =============================================================================== diff --git a/test/ecl_user.h b/test/ecl_user.h index 637089e4..26eb1ab4 100644 --- a/test/ecl_user.h +++ b/test/ecl_user.h @@ -29,22 +29,20 @@ SOFTWARE. #ifndef __ECL_USER__ #define __ECL_USER__ -#include "platform.h" - #include -#if defined(ETL_COMPILER_GCC) - #define ECL_TIMER_TIMER_SEMAPHORE uint32_t - #define ECL_TIMER_DISABLE_PROCESSING(x) __sync_fetch_and_add(&x, 1) - #define ECL_TIMER_ENABLE_PROCESSING(x) __sync_fetch_and_sub(&x, 1) - #define ECL_TIMER_PROCESSING_ENABLED(x) (__sync_fetch_and_add(&x, 0) == 0) -#else +#if defined(_MSC_VER) #include #define ECL_TIMER_TIMER_SEMAPHORE uint32_t #define ECL_TIMER_DISABLE_PROCESSING(x) InterlockedIncrement((volatile long*)&x) #define ECL_TIMER_ENABLE_PROCESSING(x) InterlockedDecrement((volatile long*)&x) #define ECL_TIMER_PROCESSING_ENABLED(x) (InterlockedAdd((volatile long*)&x, 0) == 0) +#else + #define ECL_TIMER_TIMER_SEMAPHORE uint32_t + #define ECL_TIMER_DISABLE_PROCESSING(x) __sync_fetch_and_add(&x, 1) + #define ECL_TIMER_ENABLE_PROCESSING(x) __sync_fetch_and_sub(&x, 1) + #define ECL_TIMER_PROCESSING_ENABLED(x) (__sync_fetch_and_add(&x, 0) == 0) #endif #endif From cb03b5f177ce81034cccc3f4029155ce1ced7f1c Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 25 Jan 2018 10:45:28 +0000 Subject: [PATCH 10/50] Code::Blocks project update --- src/fsm.h | 82 ++-- test/codeblocks/ETL.cbp | 3 + test/codeblocks/ETL.layout | 937 +++++++++++++++++++------------------ 3 files changed, 515 insertions(+), 507 deletions(-) diff --git a/src/fsm.h b/src/fsm.h index 665f7666..8a9a9a7f 100644 --- a/src/fsm.h +++ b/src/fsm.h @@ -288,7 +288,7 @@ namespace etl /// Does this FSM accept the message id? /// Yes, it accepts everything! //******************************************* - bool accepts(etl::message_id_t id) const + bool accepts(etl::message_id_t) const { return true; } @@ -346,10 +346,10 @@ namespace etl //*************************************************************************** // The definition for all 16 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -407,10 +407,10 @@ namespace etl //*************************************************************************** // Specialisation for 15 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -467,10 +467,10 @@ namespace etl //*************************************************************************** // Specialisation for 14 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -526,10 +526,10 @@ namespace etl //*************************************************************************** // Specialisation for 13 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -584,9 +584,9 @@ namespace etl //*************************************************************************** // Specialisation for 12 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -640,9 +640,9 @@ namespace etl //*************************************************************************** // Specialisation for 11 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -695,9 +695,9 @@ namespace etl //*************************************************************************** // Specialisation for 10 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -749,9 +749,9 @@ namespace etl //*************************************************************************** // Specialisation for 9 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -802,8 +802,8 @@ namespace etl //*************************************************************************** // Specialisation for 8 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -853,8 +853,8 @@ namespace etl //*************************************************************************** // Specialisation for 7 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -903,8 +903,8 @@ namespace etl //*************************************************************************** // Specialisation for 6 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -952,8 +952,8 @@ namespace etl //*************************************************************************** // Specialisation for 5 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -1000,7 +1000,7 @@ namespace etl //*************************************************************************** // Specialisation for 4 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -1046,7 +1046,7 @@ namespace etl //*************************************************************************** // Specialisation for 3 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -1091,7 +1091,7 @@ namespace etl //*************************************************************************** // Specialisation for 2 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -1135,7 +1135,7 @@ namespace etl //*************************************************************************** // Specialisation for 1 message type. //*************************************************************************** - template class fsm_state : public ifsm_state { diff --git a/test/codeblocks/ETL.cbp b/test/codeblocks/ETL.cbp index 4d976d13..39a2bd7f 100644 --- a/test/codeblocks/ETL.cbp +++ b/test/codeblocks/ETL.cbp @@ -60,6 +60,7 @@ + @@ -290,6 +291,7 @@ + @@ -379,6 +381,7 @@ + diff --git a/test/codeblocks/ETL.layout b/test/codeblocks/ETL.layout index 3bd0bf67..a0ca37fb 100644 --- a/test/codeblocks/ETL.layout +++ b/test/codeblocks/ETL.layout @@ -2,459 +2,19 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -462,6 +22,321 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -472,24 +347,84 @@ - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -497,34 +432,49 @@ - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + @@ -532,14 +482,69 @@ - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From bf06775b5102a9623606d8cfbcb0b2852aa81721 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 27 Jan 2018 15:40:03 +0000 Subject: [PATCH 11/50] Added fast clear for types that are trivially destructible. (Integral and pointer types only for C++03) --- src/deque.h | 12 +++++-- src/flat_map.h | 19 ++++++++++- src/flat_multimap.h | 19 ++++++++++- src/flat_multiset.h | 23 +++++++++++-- src/flat_set.h | 26 ++++++++++++--- src/forward_list.h | 61 ++++++++++++++++++++++------------- src/list.h | 20 ++++++++---- src/queue.h | 28 +++++++++++++--- src/reference_flat_map.h | 2 +- src/reference_flat_multimap.h | 2 +- src/reference_flat_multiset.h | 2 +- src/reference_flat_set.h | 2 +- src/stack.h | 24 ++++++++++++-- test/test_deque.cpp | 21 ++++++++++++ test/test_flat_map.cpp | 32 ++++++++++++++++++ test/test_flat_multimap.cpp | 33 +++++++++++++++++++ test/test_flat_multiset.cpp | 34 +++++++++++++++++-- test/test_flat_set.cpp | 29 +++++++++++++++++ test/test_forward_list.cpp | 24 +++++++++++++- test/test_list.cpp | 25 +++++++++++++- test/test_queue.cpp | 45 ++++++++++++++++++++++++++ test/test_stack.cpp | 45 ++++++++++++++++++++++++++ test/vs2017/etl.vcxproj | 3 +- 23 files changed, 473 insertions(+), 58 deletions(-) diff --git a/src/deque.h b/src/deque.h index 533795df..6171131c 100644 --- a/src/deque.h +++ b/src/deque.h @@ -1797,9 +1797,17 @@ namespace etl //********************************************************************* void initialise() { - while (current_size > 0) + if ETL_IF_CONSTEXPR(etl::is_trivially_destructible::value) { - destroy_element_back(); + current_size = 0; + construct_count.clear(); + } + else + { + while (current_size > 0) + { + destroy_element_back(); + } } _begin = iterator(0, *this, p_buffer); diff --git a/src/flat_map.h b/src/flat_map.h index 26132748..6ca6f8ed 100644 --- a/src/flat_map.h +++ b/src/flat_map.h @@ -398,7 +398,24 @@ namespace etl //************************************************************************* void clear() { - erase(begin(), end()); + if ETL_IF_CONSTEXPR(etl::is_trivially_destructible::value) + { + storage.release_all(); + } + else + { + iterator itr = begin(); + + while (itr != end()) + { + itr->~value_type(); + storage.release(etl::addressof(*itr)); + ++itr; + } + } + + construct_count.clear(); + refmap_t::clear(); } //********************************************************************* diff --git a/src/flat_multimap.h b/src/flat_multimap.h index e6315c13..41246cb2 100644 --- a/src/flat_multimap.h +++ b/src/flat_multimap.h @@ -349,7 +349,24 @@ namespace etl //************************************************************************* void clear() { - erase(begin(), end()); + if ETL_IF_CONSTEXPR(etl::is_trivially_destructible::value) + { + storage.release_all(); + } + else + { + iterator itr = begin(); + + while (itr != end()) + { + itr->~value_type(); + storage.release(etl::addressof(*itr)); + ++itr; + } + } + + construct_count.clear(); + refmap_t::clear(); } //********************************************************************* diff --git a/src/flat_multiset.h b/src/flat_multiset.h index 10dbc9c9..ff88bb21 100644 --- a/src/flat_multiset.h +++ b/src/flat_multiset.h @@ -294,7 +294,7 @@ namespace etl //********************************************************************* void erase(iterator i_element) { - i_element->~value_type(); + etl::destroy_at(etl::addressof(*i_element)); storage.release(etl::addressof(*i_element)); refset_t::erase(i_element); --construct_count; @@ -313,7 +313,7 @@ namespace etl while (itr != last) { - itr->~value_type(); + etl::destroy_at(etl::addressof(*itr)); storage.release(etl::addressof(*itr)); ++itr; --construct_count; @@ -327,7 +327,24 @@ namespace etl //************************************************************************* void clear() { - erase(begin(), end()); + if ETL_IF_CONSTEXPR(etl::is_trivially_destructible::value) + { + storage.release_all(); + } + else + { + iterator itr = begin(); + + while (itr != end()) + { + etl::destroy_at(etl::addressof(*itr)); + storage.release(etl::addressof(*itr)); + ++itr; + } + } + + construct_count.clear(); + refset_t::clear(); } //********************************************************************* diff --git a/src/flat_set.h b/src/flat_set.h index abaf5c07..dec75bc1 100644 --- a/src/flat_set.h +++ b/src/flat_set.h @@ -284,7 +284,7 @@ namespace etl } else { - i_element->~value_type(); + etl::destroy_at(etl::addressof(*i_element)); storage.release(etl::addressof(*i_element)); refset_t::erase(i_element); --construct_count; @@ -298,7 +298,7 @@ namespace etl //********************************************************************* void erase(iterator i_element) { - i_element->~value_type(); + etl::destroy_at(etl::addressof(*i_element)); storage.release(etl::addressof(*i_element)); refset_t::erase(i_element); --construct_count; @@ -317,7 +317,7 @@ namespace etl while (itr != last) { - itr->~value_type(); + etl::destroy_at(etl::addressof(*itr)); storage.release(etl::addressof(*itr)); ++itr; --construct_count; @@ -331,7 +331,25 @@ namespace etl //************************************************************************* void clear() { - erase(begin(), end()); + if ETL_IF_CONSTEXPR(etl::is_trivially_destructible::value) + { + storage.release_all(); + } + else + { + iterator itr = begin(); + + while (itr != end()) + { + etl::destroy_at(etl::addressof(*itr)); + storage.release(etl::addressof(*itr)); + ++itr; + --construct_count; + } + } + + construct_count.clear(); + refset_t::clear(); } //********************************************************************* diff --git a/src/forward_list.h b/src/forward_list.h index 2ac02e55..4be5bca8 100644 --- a/src/forward_list.h +++ b/src/forward_list.h @@ -728,26 +728,33 @@ namespace etl iterator i_node = begin(); iterator i_last_node; - // Find where we're currently at. - while ((i < n) && (i_node != end())) + if (empty()) { - ++i; - i_last_node = i_node; - ++i_node; + assign(n, value); } - - if (i_node != end()) + else { - // Reduce. - erase_after(i_last_node, end()); - } - else if (i_node == end()) - { - // Increase. - while (i < n) + // Find where we're currently at. + while ((i < n) && (i_node != end())) { - i_last_node = insert_after(i_last_node, value); ++i; + i_last_node = i_node; + ++i_node; + } + + if (i_node != end()) + { + // Reduce. + erase_after(i_last_node, end()); + } + else if (i_node == end()) + { + // Increase. + while (i < n) + { + i_last_node = insert_after(i_last_node, value); + ++i; + } } } } @@ -1226,15 +1233,23 @@ namespace etl { if (!empty()) { - node_t* p_first = start_node.next; - node_t* p_next; - - // Erase the ones in between. - while (p_first != nullptr) + if ETL_IF_CONSTEXPR(etl::is_trivially_destructible::value) { - p_next = p_first->next; // Remember the next node. - destroy_data_node(static_cast(*p_first)); // Destroy the pool object. - p_first = p_next; // Move to the next node. + p_node_pool->release_all(); + construct_count.clear(); + } + else + { + node_t* p_first = start_node.next; + node_t* p_next; + + // Erase the ones in between. + while (p_first != nullptr) + { + p_next = p_first->next; // Remember the next node. + destroy_data_node(static_cast(*p_first)); // Destroy the pool object. + p_first = p_next; // Move to the next node. + } } } diff --git a/src/list.h b/src/list.h index 4ba169a2..97c08724 100644 --- a/src/list.h +++ b/src/list.h @@ -1442,13 +1442,21 @@ namespace etl { if (!empty()) { - node_t* p_first = terminal_node.next; - node_t* p_last = &terminal_node; - - while (p_first != p_last) + if ETL_IF_CONSTEXPR(etl::is_trivially_destructible::value) { - destroy_data_node(static_cast(*p_first)); // Destroy the current node. - p_first = p_first->next; // Move to the next node. + p_node_pool->release_all(); + construct_count.clear(); + } + else + { + node_t* p_first = terminal_node.next; + node_t* p_last = &terminal_node; + + while (p_first != p_last) + { + destroy_data_node(static_cast(*p_first)); // Destroy the current node. + p_first = p_first->next; // Move to the next node. + } } } diff --git a/src/queue.h b/src/queue.h index 75fc8ceb..16c3de56 100644 --- a/src/queue.h +++ b/src/queue.h @@ -191,6 +191,17 @@ namespace etl --construct_count; } + //************************************************************************* + /// Clears the indexes. + //************************************************************************* + void index_clear() + { + in = 0; + out = 0; + current_size = 0; + construct_count.clear(); + } + size_type in; ///< Where to input new data. size_type out; ///< Where to get the oldest data. size_type current_size; ///< The number of items in the queue. @@ -362,14 +373,21 @@ namespace etl //************************************************************************* void clear() { - while (current_size > 0) + if ETL_IF_CONSTEXPR(etl::is_trivially_destructible::value) { - p_buffer[out].~T(); - base_t::del_out(); + base_t::index_clear(); } + else + { + while (current_size > 0) + { + p_buffer[out].~T(); + base_t::del_out(); + } - in = 0; - out = 0; + in = 0; + out = 0; + } } //************************************************************************* diff --git a/src/reference_flat_map.h b/src/reference_flat_map.h index eda76782..bfd66da4 100644 --- a/src/reference_flat_map.h +++ b/src/reference_flat_map.h @@ -622,7 +622,7 @@ namespace etl //************************************************************************* void clear() { - erase(begin(), end()); + lookup.clear(); } //********************************************************************* diff --git a/src/reference_flat_multimap.h b/src/reference_flat_multimap.h index 5af87cc1..6076596d 100644 --- a/src/reference_flat_multimap.h +++ b/src/reference_flat_multimap.h @@ -542,7 +542,7 @@ namespace etl //************************************************************************* void clear() { - erase(begin(), end()); + lookup.clear(); } //********************************************************************* diff --git a/src/reference_flat_multiset.h b/src/reference_flat_multiset.h index 25e88d58..d0a2cd53 100644 --- a/src/reference_flat_multiset.h +++ b/src/reference_flat_multiset.h @@ -554,7 +554,7 @@ namespace etl //************************************************************************* void clear() { - erase(begin(), end()); + lookup.clear(); } //********************************************************************* diff --git a/src/reference_flat_set.h b/src/reference_flat_set.h index 361f6036..ef9f6089 100644 --- a/src/reference_flat_set.h +++ b/src/reference_flat_set.h @@ -534,7 +534,7 @@ namespace etl //************************************************************************* void clear() { - erase(begin(), end()); + lookup.clear(); } //********************************************************************* diff --git a/src/stack.h b/src/stack.h index 96bf282f..5c2b0056 100644 --- a/src/stack.h +++ b/src/stack.h @@ -44,6 +44,7 @@ SOFTWARE. #include "debug_count.h" #include "type_traits.h" #include "parameter_type.h" +#include "type_traits.h" #define ETL_FILE "15" @@ -183,6 +184,16 @@ namespace etl --construct_count; } + //************************************************************************* + /// Clears all of the indexes. + //************************************************************************* + void index_clear() + { + top_index = 0; + current_size = 0; + construct_count.clear(); + } + size_type top_index; ///< The index of the top of the stack. size_type current_size; ///< The number of items in the stack. const size_type CAPACITY; ///< The maximum number of items in the stack. @@ -333,10 +344,17 @@ namespace etl //************************************************************************* void clear() { - while (current_size > 0) + if ETL_IF_CONSTEXPR(etl::is_trivially_destructible::value) { - p_buffer[top_index].~T(); - base_t::del_out(); + base_t::index_clear(); + } + else + { + while (current_size > 0) + { + p_buffer[top_index].~T(); + base_t::del_out(); + } } } diff --git a/test/test_deque.cpp b/test/test_deque.cpp index 7a0719d9..503e561d 100644 --- a/test/test_deque.cpp +++ b/test/test_deque.cpp @@ -608,6 +608,27 @@ namespace data.resize(SIZE); data.clear(); CHECK(data.empty()); + + // Do it again to check that clear() didn't screw up the internals. + data.resize(SIZE); + CHECK_EQUAL(SIZE, data.size()); + data.clear(); + CHECK(data.empty()); + } + + //************************************************************************* + TEST(test_clear_pod) + { + DataInt data; + + data.resize(SIZE); + data.clear(); + CHECK(data.empty()); + + // Do it again to check that clear() didn't screw up the internals. + data.resize(SIZE); + data.clear(); + CHECK(data.empty()); } //************************************************************************* diff --git a/test/test_flat_map.cpp b/test/test_flat_map.cpp index dd3768a4..149b2406 100644 --- a/test/test_flat_map.cpp +++ b/test/test_flat_map.cpp @@ -52,11 +52,15 @@ namespace typedef std::pair ElementDC; typedef std::pair ElementNDC; + typedef std::pair ElementInt; + typedef etl::flat_map DataDC; typedef etl::flat_map DataNDC; typedef etl::iflat_map IDataDC; typedef etl::iflat_map IDataNDC; + typedef etl::flat_map DataInt; + typedef std::map Compare_DataDC; typedef std::map Compare_DataNDC; @@ -159,6 +163,8 @@ namespace std::vector excess_data; std::vector different_data; + std::vector int_data; + //************************************************************************* template bool Check_Equal(T1 begin1, T1 end1, T2 begin2) @@ -207,10 +213,17 @@ namespace ElementDC(5, M5), ElementDC(6, M6), ElementDC(7, M7), ElementDC(8, M8), ElementDC(9, M9) }; + ElementInt n5[] = + { + ElementInt(0, 0), ElementInt(1, 1), ElementInt(2, 2), ElementInt(3, 3), ElementInt(4, 4), + ElementInt(5, 5), ElementInt(6, 6), ElementInt(7, 7), ElementInt(8, 8), ElementInt(9, 9) + }; + initial_data.assign(std::begin(n), std::end(n)); excess_data.assign(std::begin(n2), std::end(n2)); different_data.assign(std::begin(n3), std::end(n3)); initial_data_dc.assign(std::begin(n4), std::end(n4)); + int_data.assign(std::begin(n5), std::end(n5)); } }; @@ -655,7 +668,26 @@ namespace DataNDC data(compare_data.begin(), compare_data.end()); data.clear(); + CHECK_EQUAL(data.size(), size_t(0)); + // Do it again to check that clear() didn't screw up the internals. + data.assign(compare_data.begin(), compare_data.end()); + CHECK_EQUAL(data.size(), compare_data.size()); + data.clear(); + CHECK_EQUAL(data.size(), size_t(0)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_clear_pod) + { + DataInt data(int_data.begin(), int_data.end()); + data.clear(); + CHECK_EQUAL(data.size(), size_t(0)); + + // Do it again to check that clear() didn't screw up the internals. + data.assign(int_data.begin(), int_data.end()); + CHECK_EQUAL(data.size(), int_data.size()); + data.clear(); CHECK_EQUAL(data.size(), size_t(0)); } diff --git a/test/test_flat_multimap.cpp b/test/test_flat_multimap.cpp index 0765984b..0e573278 100644 --- a/test/test_flat_multimap.cpp +++ b/test/test_flat_multimap.cpp @@ -50,11 +50,15 @@ namespace typedef std::pair ElementDC; typedef std::pair ElementNDC; + typedef std::pair ElementInt; + typedef etl::flat_multimap DataDC; typedef etl::flat_multimap DataNDC; typedef etl::iflat_multimap IDataDC; typedef etl::iflat_multimap IDataNDC; + typedef etl::flat_multimap DataInt; + typedef std::multimap Compare_DataDC; typedef std::multimap Compare_DataNDC; @@ -84,6 +88,8 @@ namespace std::vector different_data; std::vector multi_data; + std::vector int_data; + //************************************************************************* template bool Check_Equal(T1 begin1, T1 end1, T2 begin2) @@ -166,10 +172,17 @@ namespace ElementNDC(4, N5), ElementNDC(4, N6), ElementNDC(5, N7), ElementNDC(4, N8), ElementNDC(0, N9) }; + ElementInt n5[] = + { + ElementInt(0, 0), ElementInt(1, 1), ElementInt(2, 2), ElementInt(3, 3), ElementInt(4, 4), + ElementInt(5, 5), ElementInt(6, 6), ElementInt(7, 7), ElementInt(8, 8), ElementInt(9, 9) + }; + initial_data.assign(std::begin(n), std::end(n)); excess_data.assign(std::begin(n2), std::end(n2)); different_data.assign(std::begin(n3), std::end(n3)); multi_data.assign(std::begin(n4), std::end(n4)); + int_data.assign(std::begin(n5), std::end(n5)); } }; @@ -485,7 +498,27 @@ namespace DataNDC data(compare_data.begin(), compare_data.end()); data.clear(); + CHECK_EQUAL(data.size(), size_t(0)); + + // Do it again to check that clear() didn't screw up the internals. + data.assign(compare_data.begin(), compare_data.end()); + CHECK_EQUAL(data.size(), compare_data.size()); + data.clear(); + CHECK_EQUAL(data.size(), size_t(0)); + } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_clear_pod) + { + DataInt data(int_data.begin(), int_data.end()); + + data.clear(); + CHECK_EQUAL(data.size(), size_t(0)); + + // Do it again to check that clear() didn't screw up the internals. + data.assign(int_data.begin(), int_data.end()); + CHECK_EQUAL(data.size(), int_data.size()); + data.clear(); CHECK_EQUAL(data.size(), size_t(0)); } diff --git a/test/test_flat_multiset.cpp b/test/test_flat_multiset.cpp index d787c274..882774d8 100644 --- a/test/test_flat_multiset.cpp +++ b/test/test_flat_multiset.cpp @@ -51,6 +51,8 @@ namespace typedef etl::flat_multiset DataNDC; typedef etl::iflat_multiset IDataNDC; + typedef etl::flat_multiset DataInt; + typedef std::multiset Compare_DataDC; typedef std::multiset Compare_DataNDC; @@ -101,6 +103,8 @@ namespace std::vector different_data; std::vector multi_data; + std::vector int_data; + //************************************************************************* struct SetupFixture { @@ -126,10 +130,16 @@ namespace N0, N0, N1, N2, N3, N1, N3, N3, N4, N2 }; + int n5[] = + { + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 + }; + initial_data.assign(std::begin(n), std::end(n)); excess_data.assign(std::begin(n2), std::end(n2)); different_data.assign(std::begin(n3), std::end(n3)); multi_data.assign(std::begin(n4), std::end(n4)); + int_data.assign(std::begin(n5), std::end(n5)); } }; @@ -432,8 +442,8 @@ namespace data.erase(i_data, i_data_end); bool isEqual = std::equal(data.begin(), - data.end(), - compare_data.begin()); + data.end(), + compare_data.begin()); CHECK(isEqual); } @@ -445,7 +455,27 @@ namespace DataNDC data(compare_data.begin(), compare_data.end()); data.clear(); + CHECK_EQUAL(data.size(), size_t(0)); + // Do it again to check that clear() didn't screw up the internals. + data.assign(compare_data.begin(), compare_data.end()); + CHECK_EQUAL(data.size(), compare_data.size()); + data.clear(); + CHECK_EQUAL(data.size(), size_t(0)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_clear_pod) + { + DataInt data(int_data.begin(), int_data.end()); + + data.clear(); + CHECK_EQUAL(data.size(), size_t(0)); + + // Do it again to check that clear() didn't screw up the internals. + data.assign(int_data.begin(), int_data.end()); + CHECK_EQUAL(data.size(), int_data.size()); + data.clear(); CHECK_EQUAL(data.size(), size_t(0)); } diff --git a/test/test_flat_set.cpp b/test/test_flat_set.cpp index 8b841a56..35def29d 100644 --- a/test/test_flat_set.cpp +++ b/test/test_flat_set.cpp @@ -51,6 +51,8 @@ namespace typedef etl::flat_set DataNDC; typedef etl::iflat_set IDataNDC; + typedef etl::flat_set DataInt; + typedef std::set Compare_DataDC; typedef std::set Compare_DataNDC; @@ -99,6 +101,8 @@ namespace std::vector initial_data; std::vector excess_data; std::vector different_data; + + std::vector int_data; //************************************************************************* struct SetupFixture @@ -120,9 +124,15 @@ namespace N10, N11, N12, N13, N14, N15, N16, N17, N18, N19 }; + int n4[] = + { + 10, 11, 12, 13, 14, 15, 16, 17, 18, 19 + }; + initial_data.assign(std::begin(n), std::end(n)); excess_data.assign(std::begin(n2), std::end(n2)); different_data.assign(std::begin(n3), std::end(n3)); + int_data.assign(std::begin(n4), std::end(n4)); } }; @@ -434,7 +444,26 @@ namespace DataNDC data(compare_data.begin(), compare_data.end()); data.clear(); + CHECK_EQUAL(data.size(), size_t(0)); + // Do it again to check that clear() didn't screw up the internals. + data.assign(compare_data.begin(), compare_data.end()); + CHECK_EQUAL(data.size(), compare_data.size()); + data.clear(); + CHECK_EQUAL(data.size(), size_t(0)); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_clear_pod) + { + DataInt data(int_data.begin(), int_data.end()); + data.clear(); + CHECK_EQUAL(data.size(), size_t(0)); + + // Do it again to check that clear() didn't screw up the internals. + data.assign(int_data.begin(), int_data.end()); + CHECK_EQUAL(data.size(), int_data.size()); + data.clear(); CHECK_EQUAL(data.size(), size_t(0)); } diff --git a/test/test_forward_list.cpp b/test/test_forward_list.cpp index 37063637..11ca2e11 100644 --- a/test/test_forward_list.cpp +++ b/test/test_forward_list.cpp @@ -53,6 +53,8 @@ namespace typedef etl::forward_list DataNDC; typedef etl::iforward_list IDataNDC; + typedef etl::forward_list DataInt; + typedef std::forward_list CompareDataDC; typedef std::forward_list CompareDataNDC; typedef std::vector InitialDataNDC; @@ -249,8 +251,28 @@ namespace { DataNDC data(sorted_data.begin(), sorted_data.end()); data.clear(); - CHECK(data.empty()); + + // Do it again to check that clear() didn't screw up the internals. + data.assign(sorted_data.begin(), sorted_data.end()); + CHECK_EQUAL(SIZE, data.size()); + data.clear(); + CHECK_EQUAL(size_t(0), data.size()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_clear_pod) + { + DataInt data(SIZE, 1); + + data.clear(); + CHECK(data.empty()); + + // Do it again to check that clear() didn't screw up the internals. + data.resize(SIZE); + CHECK_EQUAL(SIZE, data.size()); + data.clear(); + CHECK_EQUAL(size_t(0), data.size()); } //************************************************************************* diff --git a/test/test_list.cpp b/test/test_list.cpp index 1bb66cd3..cef78918 100644 --- a/test/test_list.cpp +++ b/test/test_list.cpp @@ -52,6 +52,8 @@ namespace typedef etl::list DataNDC2; typedef etl::ilist IDataNDC; + typedef etl::list DataInt; + typedef std::list CompareData; typedef std::vector InitialData; @@ -272,9 +274,30 @@ namespace TEST_FIXTURE(SetupFixture, test_clear) { DataNDC data(sorted_data.begin(), sorted_data.end()); - data.clear(); + data.clear(); CHECK_EQUAL(0U, data.size()); + + // Do it again to check that clear() didn't screw up the internals. + data.assign(sorted_data.begin(), sorted_data.end()); + CHECK_EQUAL(SIZE, data.size()); + data.clear(); + CHECK_EQUAL(size_t(0), data.size()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_clear_pod) + { + DataInt data(SIZE, 1); + + data.clear(); + CHECK(data.empty()); + + // Do it again to check that clear() didn't screw up the internals. + data.resize(SIZE); + CHECK_EQUAL(SIZE, data.size()); + data.clear(); + CHECK_EQUAL(size_t(0), data.size()); } //************************************************************************* diff --git a/test/test_queue.cpp b/test/test_queue.cpp index 16cdbced..d6c3bc00 100644 --- a/test/test_queue.cpp +++ b/test/test_queue.cpp @@ -53,6 +53,26 @@ namespace return (lhs.c == rhs.c) && (lhs.i == rhs.i) && (lhs.d == rhs.d); } + struct ItemNTD + { + ItemNTD() + { + p = new char; + } + + ItemNTD(const ItemNTD&) + : p(new char) + { + } + + ~ItemNTD() + { + delete p; + } + + char* p; + }; + SUITE(test_queue) { //************************************************************************* @@ -98,6 +118,31 @@ namespace queue.push(2); queue.clear(); CHECK_EQUAL(0U, queue.size()); + + // Do it again to check that clear() didn't screw up the internals. + queue.push(1); + queue.push(2); + CHECK_EQUAL(2U, queue.size()); + queue.clear(); + CHECK_EQUAL(0U, queue.size()); + } + + //************************************************************************* + TEST(test_clear_non_pod) + { + etl::queue queue; + + queue.push(ItemNTD()); + queue.push(ItemNTD()); + queue.clear(); + CHECK_EQUAL(0U, queue.size()); + + // Do it again to check that clear() didn't screw up the internals. + queue.push(ItemNTD()); + queue.push(ItemNTD()); + CHECK_EQUAL(2U, queue.size()); + queue.clear(); + CHECK_EQUAL(0U, queue.size()); } //************************************************************************* diff --git a/test/test_stack.cpp b/test/test_stack.cpp index 49a5da9c..4810c410 100644 --- a/test/test_stack.cpp +++ b/test/test_stack.cpp @@ -55,6 +55,26 @@ namespace return (lhs.c == rhs.c) && (lhs.i == rhs.i) && (lhs.d == rhs.d); } + struct ItemNTD + { + ItemNTD() + { + p = new char; + } + + ItemNTD(const ItemNTD&) + : p(new char) + { + } + + ~ItemNTD() + { + delete p; + } + + char* p; + }; + SUITE(test_stack) { typedef TestDataDC ItemDC; @@ -138,6 +158,31 @@ namespace stack.push(2); stack.clear(); CHECK_EQUAL(0U, stack.size()); + + // Do it again to check that clear() didn't screw up the internals. + stack.push(1); + stack.push(2); + CHECK_EQUAL(2U, stack.size()); + stack.clear(); + CHECK_EQUAL(0U, stack.size()); + } + + //************************************************************************* + TEST(test_clear_non_pod) + { + etl::stack stack; + + stack.push(ItemNTD()); + stack.push(ItemNTD()); + stack.clear(); + CHECK_EQUAL(0U, stack.size()); + + // Do it again to check that clear() didn't screw up the internals. + stack.push(ItemNTD()); + stack.push(ItemNTD()); + CHECK_EQUAL(2U, stack.size()); + stack.clear(); + CHECK_EQUAL(0U, stack.size()); } //************************************************************************* diff --git a/test/vs2017/etl.vcxproj b/test/vs2017/etl.vcxproj index fca63a9b..49eab9a4 100644 --- a/test/vs2017/etl.vcxproj +++ b/test/vs2017/etl.vcxproj @@ -78,8 +78,7 @@ false - - + stdcpp14 Console From d4fdf9d657111eeeeebac0517363d0acd5f8c5bc Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 27 Jan 2018 15:40:52 +0000 Subject: [PATCH 12/50] Added C++17 macros. The library doesn't currently support C++17. --- src/platform.h | 14 +++++++++++++- src/profiles/arduino_arm.h | 1 + src/profiles/armv5.h | 1 + src/profiles/armv6.h | 1 + src/profiles/cpp03.h | 1 + src/profiles/cpp11.h | 1 + src/profiles/cpp14.h | 1 + src/profiles/gcc_generic.h | 2 ++ src/profiles/gcc_linux_x86.h | 2 ++ src/profiles/gcc_windows_x86.h | 2 ++ src/profiles/msvc_x86.h | 1 + src/profiles/ticc.h | 1 + 12 files changed, 27 insertions(+), 1 deletion(-) diff --git a/src/platform.h b/src/platform.h index 8dd01fc9..f1a4c4de 100644 --- a/src/platform.h +++ b/src/platform.h @@ -35,11 +35,12 @@ SOFTWARE. #define ETL_8BIT_SUPPORT (CHAR_BIT == 8) #if defined(_DEBUG) || defined(DEBUG) - #define ETL_DEBUG +#define ETL_DEBUG #endif #undef ETL_CPP11_SUPPORTED #undef ETL_CPP14_SUPPORTED +#undef ETL_CPP17_SUPPORTED #undef ETL_NO_NULLPTR_SUPPORT #undef ETL_NO_LARGE_CHAR_SUPPORT #undef ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED @@ -47,10 +48,21 @@ SOFTWARE. #include "etl_profile.h" +#if defined(ETL_COMPILER_MICROSOFT) + // Disable warning of deprecated std::iterator. + #pragma warning(disable : 4996) +#endif + #if ETL_CPP11_SUPPORTED #define ETL_CONSTEXPR constexpr #else #define ETL_CONSTEXPR #endif +#if ETL_CPP17_SUPPORTED + #define ETL_IF_CONSTEXPR constexpr +#else + #define ETL_IF_CONSTEXPR +#endif + #endif diff --git a/src/profiles/arduino_arm.h b/src/profiles/arduino_arm.h index 8de9d110..2ffe5977 100644 --- a/src/profiles/arduino_arm.h +++ b/src/profiles/arduino_arm.h @@ -42,6 +42,7 @@ SOFTWARE. #define ETL_COMPILER_GCC #define ETL_CPP11_SUPPORTED 0 #define ETL_CPP14_SUPPORTED 0 +#define ETL_CPP17_SUPPORTED 0 #define ETL_NO_NULLPTR_SUPPORT 1 #define ETL_NO_LARGE_CHAR_SUPPORT 1 #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 0 diff --git a/src/profiles/armv5.h b/src/profiles/armv5.h index 51e173fe..5d108fb6 100644 --- a/src/profiles/armv5.h +++ b/src/profiles/armv5.h @@ -42,6 +42,7 @@ SOFTWARE. #define ETL_COMPILER_ARM #define ETL_CPP11_SUPPORTED 0 #define ETL_CPP14_SUPPORTED 0 +#define ETL_CPP17_SUPPORTED 0 #define ETL_NO_NULLPTR_SUPPORT 1 #define ETL_NO_LARGE_CHAR_SUPPORT 1 #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 0 diff --git a/src/profiles/armv6.h b/src/profiles/armv6.h index cdd73213..08b99db2 100644 --- a/src/profiles/armv6.h +++ b/src/profiles/armv6.h @@ -42,6 +42,7 @@ SOFTWARE. #define ETL_COMPILER_LLVM #define ETL_CPP11_SUPPORTED 1 #define ETL_CPP14_SUPPORTED 0 +#define ETL_CPP17_SUPPORTED 0 #define ETL_NO_NULLPTR_SUPPORT 0 #define ETL_NO_LARGE_CHAR_SUPPORT 0 #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 1 diff --git a/src/profiles/cpp03.h b/src/profiles/cpp03.h index 760f7984..4b50addb 100644 --- a/src/profiles/cpp03.h +++ b/src/profiles/cpp03.h @@ -42,6 +42,7 @@ SOFTWARE. #define ETL_COMPILER_GENERIC #define ETL_CPP11_SUPPORTED 0 #define ETL_CPP14_SUPPORTED 0 +#define ETL_CPP17_SUPPORTED 0 #define ETL_NO_NULLPTR_SUPPORT 1 #define ETL_NO_LARGE_CHAR_SUPPORT 1 #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 0 diff --git a/src/profiles/cpp11.h b/src/profiles/cpp11.h index 072b2da7..6af61ee5 100644 --- a/src/profiles/cpp11.h +++ b/src/profiles/cpp11.h @@ -42,6 +42,7 @@ SOFTWARE. #define ETL_COMPILER_GENERIC #define ETL_CPP11_SUPPORTED 1 #define ETL_CPP14_SUPPORTED 0 +#define ETL_CPP17_SUPPORTED 0 #define ETL_NO_NULLPTR_SUPPORT 0 #define ETL_NO_LARGE_CHAR_SUPPORT 0 #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 1 diff --git a/src/profiles/cpp14.h b/src/profiles/cpp14.h index 0062770d..4a26d7cb 100644 --- a/src/profiles/cpp14.h +++ b/src/profiles/cpp14.h @@ -42,6 +42,7 @@ SOFTWARE. #define ETL_COMPILER_GENERIC #define ETL_CPP11_SUPPORTED 1 #define ETL_CPP14_SUPPORTED 1 +#define ETL_CPP17_SUPPORTED 0 #define ETL_NO_NULLPTR_SUPPORT 0 #define ETL_NO_LARGE_CHAR_SUPPORT 0 #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 1 diff --git a/src/profiles/gcc_generic.h b/src/profiles/gcc_generic.h index 52b05ebf..3e4c4d0a 100644 --- a/src/profiles/gcc_generic.h +++ b/src/profiles/gcc_generic.h @@ -43,9 +43,11 @@ SOFTWARE. #ifdef __cplusplus #define ETL_CPP11_SUPPORTED (__cplusplus >= 201103L) #define ETL_CPP14_SUPPORTED (__cplusplus >= 201402L) + #define ETL_CPP17_SUPPORTED 0 #else #define ETL_CPP11_SUPPORTED 0 #define ETL_CPP14_SUPPORTED 0 + #define ETL_CPP17_SUPPORTED 0 #endif #define ETL_NO_NULLPTR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_NO_LARGE_CHAR_SUPPORT !ETL_CPP11_SUPPORTED diff --git a/src/profiles/gcc_linux_x86.h b/src/profiles/gcc_linux_x86.h index 3a8ac812..8280d59d 100644 --- a/src/profiles/gcc_linux_x86.h +++ b/src/profiles/gcc_linux_x86.h @@ -43,9 +43,11 @@ SOFTWARE. #ifdef __cplusplus #define ETL_CPP11_SUPPORTED (__cplusplus >= 201103L) #define ETL_CPP14_SUPPORTED (__cplusplus >= 201402L) + #define ETL_CPP17_SUPPORTED 0 #else #define ETL_CPP11_SUPPORTED 0 #define ETL_CPP14_SUPPORTED 0 + #define ETL_CPP17_SUPPORTED 0 #endif #define ETL_NO_NULLPTR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_NO_LARGE_CHAR_SUPPORT !ETL_CPP11_SUPPORTED diff --git a/src/profiles/gcc_windows_x86.h b/src/profiles/gcc_windows_x86.h index a234552d..610cc60f 100644 --- a/src/profiles/gcc_windows_x86.h +++ b/src/profiles/gcc_windows_x86.h @@ -43,9 +43,11 @@ SOFTWARE. #ifdef __cplusplus #define ETL_CPP11_SUPPORTED (__cplusplus >= 201103L) #define ETL_CPP14_SUPPORTED (__cplusplus >= 201402L) + #define ETL_CPP17_SUPPORTED 0 #else #define ETL_CPP11_SUPPORTED 0 #define ETL_CPP14_SUPPORTED 0 + #define ETL_CPP17_SUPPORTED 0 #endif #define ETL_NO_NULLPTR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_NO_LARGE_CHAR_SUPPORT !ETL_CPP11_SUPPORTED diff --git a/src/profiles/msvc_x86.h b/src/profiles/msvc_x86.h index 462f3a4c..5382b62d 100644 --- a/src/profiles/msvc_x86.h +++ b/src/profiles/msvc_x86.h @@ -42,6 +42,7 @@ SOFTWARE. #define ETL_COMPILER_MICROSOFT #define ETL_CPP11_SUPPORTED (_MSC_VER >= 1600) #define ETL_CPP14_SUPPORTED (_MSC_VER >= 1900) +#define ETL_CPP17_SUPPORTED 0 #define ETL_NO_NULLPTR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_NO_LARGE_CHAR_SUPPORT !ETL_CPP11_SUPPORTED #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED ETL_CPP14_SUPPORTED diff --git a/src/profiles/ticc.h b/src/profiles/ticc.h index d695546a..b1478c64 100644 --- a/src/profiles/ticc.h +++ b/src/profiles/ticc.h @@ -42,6 +42,7 @@ SOFTWARE. #define ETL_COMPILER_TI #define ETL_CPP11_SUPPORTED 0 #define ETL_CPP14_SUPPORTED 0 +#define ETL_CPP17_SUPPORTED 0 #define ETL_NO_NULLPTR_SUPPORT 1 #define ETL_NO_LARGE_CHAR_SUPPORT 1 #define ETL_CPP11_TYPE_TRAITS_IS_TRIVIAL_SUPPORTED 0 From 231e4efe43d45fe9c622cb68135b044fc58b3845 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 27 Jan 2018 18:24:29 +0000 Subject: [PATCH 13/50] Eliminate shadow warning --- unittest-cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittest-cpp b/unittest-cpp index 478b6545..d03b3971 160000 --- a/unittest-cpp +++ b/unittest-cpp @@ -1 +1 @@ -Subproject commit 478b6545b2d32b1686f71adf9b0ba765c78a7dcb +Subproject commit d03b3971ed1590bdbe35905f084023ce84e1224e From 39ecdfb72df9b46708d7086794259088b6ef285f Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 28 Jan 2018 13:02:54 +0000 Subject: [PATCH 14/50] Update unittest-cpp --- unittest-cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unittest-cpp b/unittest-cpp index d03b3971..bc5d87f4 160000 --- a/unittest-cpp +++ b/unittest-cpp @@ -1 +1 @@ -Subproject commit d03b3971ed1590bdbe35905f084023ce84e1224e +Subproject commit bc5d87f484cac2959b0a0eafbde228e69e828d74 From 0d34769247d68e89963efe869256c52213046942 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 29 Jan 2018 15:59:34 +0000 Subject: [PATCH 15/50] Re-write to avoid any possible static initialisation order issues. Made the count a signed int to detect 'over destruction'. Added missing copy constructor. Added reset_instance_count() to force the count to zero. Remove virtual from destructor. --- src/instance_count.h | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/instance_count.h b/src/instance_count.h index 4c389663..262510df 100644 --- a/src/instance_count.h +++ b/src/instance_count.h @@ -31,6 +31,8 @@ SOFTWARE. #ifndef __ETL_INSTANCE_COUNT__ #define __ETL_INSTANCE_COUNT__ +#include + #include "platform.h" ///\defgroup instance_count instance count @@ -52,33 +54,52 @@ namespace etl //************************************************************************* instance_count() { - ++how_many; + ++how_many(); + } + + //************************************************************************* + /// Copy construct and add 1. + //************************************************************************* + instance_count(const instance_count&) + { + ++how_many(); } //************************************************************************* /// Destruct and subtract 1. //************************************************************************* - virtual ~instance_count() + ~instance_count() { - --how_many; + --how_many(); } //************************************************************************* /// Get how many instances we have. //************************************************************************* - inline static size_t get_instance_count() + inline static int32_t get_instance_count() { - return how_many; + return how_many(); + } + + //************************************************************************* + /// Get how many instances we have. + //************************************************************************* + inline static void reset_instance_count() + { + how_many() = 0; } private: - /// The count for this type. - static size_t how_many; + //************************************************************************* + /// Get a referenceto the count. + //************************************************************************* + inline static int32_t& how_many() + { + static int32_t count = 0; + return count; + } }; - - /// Initialisation. - template size_t instance_count::how_many = 0; } #endif From eb222f54bb63b8cb410372ec9a05ebe7e3b49b88 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 30 Jan 2018 08:47:49 +0000 Subject: [PATCH 16/50] Containers are now deleteable through a pointer to their 'ixxxx' class. --- src/deque.h | 11 + src/flat_map.h | 11 + src/flat_multimap.h | 11 + src/flat_multiset.h | 11 + src/flat_set.h | 11 + src/forward_list.h | 11 + src/list.h | 11 + src/map.h | 10 + src/multimap.h | 10 + src/multiset.h | 10 + src/queue.h | 11 + src/set.h | 11 + src/stack.h | 11 + src/unordered_map.h | 11 + src/unordered_multimap.h | 11 + src/unordered_multiset.h | 11 + src/unordered_set.h | 11 + src/vector.h | 11 + test/codeblocks/ETL.layout | 1077 +++++++++++++------------ test/data.h | 6 +- test/test_deque.cpp | 13 + test/test_flat_map.cpp | 13 + test/test_flat_multimap.cpp | 15 +- test/test_flat_multiset.cpp | 13 + test/test_flat_set.cpp | 15 +- test/test_forward_list.cpp | 13 + test/test_instance_count.cpp | 26 +- test/test_list.cpp | 13 + test/test_map.cpp | 9 + test/test_multimap.cpp | 9 + test/test_multiset.cpp | 9 + test/test_priority_queue.cpp | 17 + test/test_queue.cpp | 15 + test/test_reference_flat_map.cpp | 11 + test/test_reference_flat_multimap.cpp | 11 + test/test_reference_flat_multiset.cpp | 11 + test/test_reference_flat_set.cpp | 11 + test/test_set.cpp | 9 + test/test_stack.cpp | 15 + test/test_unordered_map.cpp | 11 + test/test_unordered_multimap.cpp | 11 + test/test_unordered_multiset.cpp | 11 + test/test_unordered_set.cpp | 11 + test/test_vector_non_trivial.cpp | 32 +- 44 files changed, 1059 insertions(+), 543 deletions(-) diff --git a/src/deque.h b/src/deque.h index 6171131c..014ee89c 100644 --- a/src/deque.h +++ b/src/deque.h @@ -622,6 +622,17 @@ namespace etl typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; + //************************************************************************* + /// Destructor. + //************************************************************************* + ~ideque() + { + if (!empty()) + { + initialise(); + } + } + //************************************************************************* /// Assigns a range to the deque. //************************************************************************* diff --git a/src/flat_map.h b/src/flat_map.h index 6ca6f8ed..cdd454b2 100644 --- a/src/flat_map.h +++ b/src/flat_map.h @@ -108,6 +108,17 @@ namespace etl public: + //************************************************************************* + /// Destructor. + //************************************************************************* + ~iflat_map() + { + if (!empty()) + { + clear(); + } + } + //********************************************************************* /// Returns an iterator to the beginning of the flat_map. ///\return An iterator to the beginning of the flat_map. diff --git a/src/flat_multimap.h b/src/flat_multimap.h index 41246cb2..4d143951 100644 --- a/src/flat_multimap.h +++ b/src/flat_multimap.h @@ -110,6 +110,17 @@ namespace etl public: + //************************************************************************* + /// Destructor. + //************************************************************************* + ~iflat_multimap() + { + if (!empty()) + { + clear(); + } + } + //********************************************************************* /// Returns an iterator to the beginning of the flat_multimap. ///\return An iterator to the beginning of the flat_multimap. diff --git a/src/flat_multiset.h b/src/flat_multiset.h index ff88bb21..5c378a3c 100644 --- a/src/flat_multiset.h +++ b/src/flat_multiset.h @@ -86,6 +86,17 @@ namespace etl public: + //************************************************************************* + /// Destructor. + //************************************************************************* + ~iflat_multiset() + { + if (!empty()) + { + clear(); + } + } + //********************************************************************* /// Returns an iterator to the beginning of the flat_multiset. ///\return An iterator to the beginning of the flat_multiset. diff --git a/src/flat_set.h b/src/flat_set.h index dec75bc1..adb2de9f 100644 --- a/src/flat_set.h +++ b/src/flat_set.h @@ -86,6 +86,17 @@ namespace etl public: + //************************************************************************* + /// Destructor. + //************************************************************************* + ~iflat_set() + { + if (!empty()) + { + clear(); + } + } + //********************************************************************* /// Returns an iterator to the beginning of the flat_set. ///\return An iterator to the beginning of the flat_set. diff --git a/src/forward_list.h b/src/forward_list.h index 4be5bca8..23fa7b3f 100644 --- a/src/forward_list.h +++ b/src/forward_list.h @@ -477,6 +477,17 @@ namespace etl typedef typename std::iterator_traits::difference_type difference_type; + //************************************************************************* + /// Destructor. + //************************************************************************* + ~iforward_list() + { + if (!empty()) + { + clear(); + } + } + //************************************************************************* /// Gets the beginning of the forward_list. //************************************************************************* diff --git a/src/list.h b/src/list.h index 97c08724..f373fd29 100644 --- a/src/list.h +++ b/src/list.h @@ -583,6 +583,17 @@ namespace etl typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; + //************************************************************************* + /// Destructor. + //************************************************************************* + ~ilist() + { + if (!empty()) + { + initialise(); + } + } + //************************************************************************* /// Gets the beginning of the list. //************************************************************************* diff --git a/src/map.h b/src/map.h index cd1a0e2e..4c1dea50 100644 --- a/src/map.h +++ b/src/map.h @@ -801,6 +801,16 @@ namespace etl typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; + //************************************************************************* + /// Destructor. + //************************************************************************* + ~imap() + { + if (!empty()) + { + clear(); + } + } //************************************************************************* /// Gets the beginning of the map. diff --git a/src/multimap.h b/src/multimap.h index 1d2e7682..4139c264 100644 --- a/src/multimap.h +++ b/src/multimap.h @@ -952,6 +952,16 @@ namespace etl typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; + //************************************************************************* + /// Destructor. + //************************************************************************* + ~imultimap() + { + if (!empty()) + { + clear(); + } + } //************************************************************************* /// Gets the beginning of the multimap. diff --git a/src/multiset.h b/src/multiset.h index d2911291..23e265ba 100644 --- a/src/multiset.h +++ b/src/multiset.h @@ -932,6 +932,16 @@ namespace etl typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; + //************************************************************************* + /// Destructor. + //************************************************************************* + ~imultiset() + { + if (!empty()) + { + clear(); + } + } //************************************************************************* /// Gets the beginning of the multiset. diff --git a/src/queue.h b/src/queue.h index 16c3de56..757dda51 100644 --- a/src/queue.h +++ b/src/queue.h @@ -239,6 +239,17 @@ namespace etl public: + //************************************************************************* + /// Destructor. + //************************************************************************* + ~iqueue() + { + if (!empty()) + { + clear(); + } + } + //************************************************************************* /// Gets a reference to the value at the front of the queue.
/// \return A reference to the value at the front of the queue. diff --git a/src/set.h b/src/set.h index 32f58a9d..be0407c4 100644 --- a/src/set.h +++ b/src/set.h @@ -786,6 +786,17 @@ namespace etl return *this; } + //************************************************************************* + /// Destructor. + //************************************************************************* + ~iset() + { + if (!empty()) + { + clear(); + } + } + //************************************************************************* /// Gets the beginning of the set. //************************************************************************* diff --git a/src/stack.h b/src/stack.h index 5c2b0056..3bca539e 100644 --- a/src/stack.h +++ b/src/stack.h @@ -230,6 +230,17 @@ namespace etl public: + //************************************************************************* + /// Destructor. + //************************************************************************* + ~istack() + { + if (!empty()) + { + clear(); + } + } + //************************************************************************* /// Gets a reference to the value at the top of the stack.
/// \return A reference to the value at the top of the stack. diff --git a/src/unordered_map.h b/src/unordered_map.h index c3c03329..d90304a1 100644 --- a/src/unordered_map.h +++ b/src/unordered_map.h @@ -480,6 +480,17 @@ namespace etl typedef typename std::iterator_traits::difference_type difference_type; + //************************************************************************* + /// Destructor. + //************************************************************************* + ~iunordered_map() + { + if (!empty()) + { + clear(); + } + } + //********************************************************************* /// Returns an iterator to the beginning of the unordered_map. ///\return An iterator to the beginning of the unordered_map. diff --git a/src/unordered_multimap.h b/src/unordered_multimap.h index 4c2bfe74..a8a8a969 100644 --- a/src/unordered_multimap.h +++ b/src/unordered_multimap.h @@ -480,6 +480,17 @@ namespace etl typedef typename std::iterator_traits::difference_type difference_type; + //************************************************************************* + /// Destructor. + //************************************************************************* + ~iunordered_multimap() + { + if (!empty()) + { + clear(); + } + } + //********************************************************************* /// Returns an iterator to the beginning of the unordered_multimap. ///\return An iterator to the beginning of the unordered_multimap. diff --git a/src/unordered_multiset.h b/src/unordered_multiset.h index 405fe9f6..b42d3e4f 100644 --- a/src/unordered_multiset.h +++ b/src/unordered_multiset.h @@ -475,6 +475,17 @@ namespace etl typedef typename std::iterator_traits::difference_type difference_type; + //************************************************************************* + /// Destructor. + //************************************************************************* + ~iunordered_multiset() + { + if (!empty()) + { + clear(); + } + } + //********************************************************************* /// Returns an iterator to the beginning of the unordered_multiset. ///\return An iterator to the beginning of the unordered_multiset. diff --git a/src/unordered_set.h b/src/unordered_set.h index 68bb968d..d8d6087d 100644 --- a/src/unordered_set.h +++ b/src/unordered_set.h @@ -476,6 +476,17 @@ namespace etl typedef typename std::iterator_traits::difference_type difference_type; + //************************************************************************* + /// Destructor. + //************************************************************************* + ~iunordered_set() + { + if (!empty()) + { + clear(); + } + } + //********************************************************************* /// Returns an iterator to the beginning of the unordered_set. ///\return An iterator to the beginning of the unordered_set. diff --git a/src/vector.h b/src/vector.h index 547f8fdc..2cc369df 100644 --- a/src/vector.h +++ b/src/vector.h @@ -93,6 +93,17 @@ namespace etl public: + //************************************************************************* + /// Destructor. + //************************************************************************* + ~ivector() + { + if (!empty()) + { + clear(); + } + } + //********************************************************************* /// Returns an iterator to the beginning of the vector. ///\return An iterator to the beginning of the vector. diff --git a/test/codeblocks/ETL.layout b/test/codeblocks/ETL.layout index a0ca37fb..9c71eeb5 100644 --- a/test/codeblocks/ETL.layout +++ b/test/codeblocks/ETL.layout @@ -2,484 +2,14 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -487,59 +17,14 @@ - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -547,4 +32,554 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/data.h b/test/data.h index 8bd99496..b66d2f8f 100644 --- a/test/data.h +++ b/test/data.h @@ -31,11 +31,13 @@ SOFTWARE. #include +#include "instance_count.h" + //***************************************************************************** // Default constructor. //***************************************************************************** template -class TestDataDC +class TestDataDC : public etl::instance_count> { public: @@ -88,7 +90,7 @@ std::ostream& operator << (std::ostream& s, const TestDataDC& rhs) // No default constructor. //***************************************************************************** template -class TestDataNDC +class TestDataNDC : public etl::instance_count> { public: diff --git a/test/test_deque.cpp b/test/test_deque.cpp index 503e561d..0bd71a7e 100644 --- a/test/test_deque.cpp +++ b/test/test_deque.cpp @@ -107,6 +107,19 @@ namespace CHECK(std::equal(compare_data.begin(), compare_data.end(), data.begin())); } + //************************************************************************* + TEST(test_destruct_via_ideque) + { + int current_count = NDC::get_instance_count(); + + DataNDC* pdata = new DataNDC(SIZE, N999); + CHECK_EQUAL(int(current_count + SIZE), NDC::get_instance_count()); + + IDataNDC* pidata = pdata; + delete pidata; + CHECK_EQUAL(current_count, NDC::get_instance_count()); + } + //************************************************************************* TEST(test_constructor_fill_excess) { diff --git a/test/test_flat_map.cpp b/test/test_flat_map.cpp index 149b2406..cc09d1da 100644 --- a/test/test_flat_map.cpp +++ b/test/test_flat_map.cpp @@ -238,6 +238,19 @@ namespace CHECK_EQUAL(data.max_size(), SIZE); } + //************************************************************************* + TEST(test_destruct_via_iflat_map) + { + int current_count = NDC::get_instance_count(); + + DataNDC* pdata = new DataNDC(initial_data.begin(), initial_data.end()); + CHECK_EQUAL(int(current_count + initial_data.size()), NDC::get_instance_count()); + + IDataNDC* pidata = pdata; + delete pidata; + CHECK_EQUAL(current_count, NDC::get_instance_count()); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_constructor_range) { diff --git a/test/test_flat_multimap.cpp b/test/test_flat_multimap.cpp index 0e573278..59c3a32d 100644 --- a/test/test_flat_multimap.cpp +++ b/test/test_flat_multimap.cpp @@ -197,6 +197,19 @@ namespace CHECK_EQUAL(data.max_size(), SIZE); } + //************************************************************************* + TEST(test_destruct_via_iflat_multimap) + { + int current_count = NDC::get_instance_count(); + + DataNDC* pdata = new DataNDC(initial_data.begin(), initial_data.end()); + CHECK_EQUAL(int(current_count + initial_data.size()), NDC::get_instance_count()); + + IDataNDC* pidata = pdata; + delete pidata; + CHECK_EQUAL(current_count, NDC::get_instance_count()); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_constructor_range) { @@ -499,7 +512,7 @@ namespace DataNDC data(compare_data.begin(), compare_data.end()); data.clear(); CHECK_EQUAL(data.size(), size_t(0)); - + // Do it again to check that clear() didn't screw up the internals. data.assign(compare_data.begin(), compare_data.end()); CHECK_EQUAL(data.size(), compare_data.size()); diff --git a/test/test_flat_multiset.cpp b/test/test_flat_multiset.cpp index 882774d8..fb775560 100644 --- a/test/test_flat_multiset.cpp +++ b/test/test_flat_multiset.cpp @@ -154,6 +154,19 @@ namespace CHECK_EQUAL(data.max_size(), SIZE); } + //************************************************************************* + TEST(test_destruct_via_iflat_multiset) + { + int current_count = NDC::get_instance_count(); + + DataNDC* pdata = new DataNDC(initial_data.begin(), initial_data.end()); + CHECK_EQUAL(int(current_count + initial_data.size()), NDC::get_instance_count()); + + IDataNDC* pidata = pdata; + delete pidata; + CHECK_EQUAL(current_count, NDC::get_instance_count()); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_constructor_range) { diff --git a/test/test_flat_set.cpp b/test/test_flat_set.cpp index 35def29d..25ff5cc7 100644 --- a/test/test_flat_set.cpp +++ b/test/test_flat_set.cpp @@ -101,7 +101,7 @@ namespace std::vector initial_data; std::vector excess_data; std::vector different_data; - + std::vector int_data; //************************************************************************* @@ -147,6 +147,19 @@ namespace CHECK_EQUAL(data.max_size(), SIZE); } + //************************************************************************* + TEST(test_destruct_via_iflat_set) + { + int current_count = NDC::get_instance_count(); + + DataNDC* pdata = new DataNDC(initial_data.begin(), initial_data.end()); + CHECK_EQUAL(int(current_count + initial_data.size()), NDC::get_instance_count()); + + IDataNDC* pidata = pdata; + delete pidata; + CHECK_EQUAL(current_count, NDC::get_instance_count()); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_constructor_range) { diff --git a/test/test_forward_list.cpp b/test/test_forward_list.cpp index 11ca2e11..524150a7 100644 --- a/test/test_forward_list.cpp +++ b/test/test_forward_list.cpp @@ -129,6 +129,19 @@ namespace CHECK(!data.empty()); } + //************************************************************************* + TEST(test_destruct_via_iforward_list) + { + int current_count = ItemNDC::get_instance_count(); + + DataNDC* pdata = new DataNDC(sorted_data.begin(), sorted_data.end()); + CHECK_EQUAL(int(current_count + sorted_data.size()), ItemNDC::get_instance_count()); + + IDataNDC* pidata = pdata; + delete pidata; + CHECK_EQUAL(current_count, ItemNDC::get_instance_count()); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_copy_constructor) { diff --git a/test/test_instance_count.cpp b/test/test_instance_count.cpp index ea3a5816..72e5512c 100644 --- a/test/test_instance_count.cpp +++ b/test/test_instance_count.cpp @@ -35,7 +35,7 @@ SOFTWARE. #include namespace -{ +{ SUITE(test_instance_count) { //************************************************************************* @@ -47,25 +47,29 @@ namespace struct Test2 : public etl::instance_count {}; - CHECK_EQUAL(0U, Test1::get_instance_count()); - CHECK_EQUAL(0U, Test2::get_instance_count()); + CHECK_EQUAL(0, Test1::get_instance_count()); + CHECK_EQUAL(0, Test2::get_instance_count()); Test1 test1a; - CHECK_EQUAL(1U, Test1::get_instance_count()); - CHECK_EQUAL(0U, Test2::get_instance_count()); + CHECK_EQUAL(1, Test1::get_instance_count()); + CHECK_EQUAL(0, Test2::get_instance_count()); Test1 test1b; Test2 test2a; - CHECK_EQUAL(2U, Test1::get_instance_count()); - CHECK_EQUAL(1U, Test2::get_instance_count()); + CHECK_EQUAL(2, Test1::get_instance_count()); + CHECK_EQUAL(1, Test2::get_instance_count()); Test2* ptest2b = new Test2; - CHECK_EQUAL(2U, Test1::get_instance_count()); - CHECK_EQUAL(2U, Test2::get_instance_count()); + CHECK_EQUAL(2, Test1::get_instance_count()); + CHECK_EQUAL(2, Test2::get_instance_count()); + + Test2 test2c(test2a); + CHECK_EQUAL(2, Test1::get_instance_count()); + CHECK_EQUAL(3, Test2::get_instance_count()); delete ptest2b; - CHECK_EQUAL(2U, Test1::get_instance_count()); - CHECK_EQUAL(1U, Test2::get_instance_count()); + CHECK_EQUAL(2, Test1::get_instance_count()); + CHECK_EQUAL(2, Test2::get_instance_count()); } }; } diff --git a/test/test_list.cpp b/test/test_list.cpp index cef78918..c0aaf9bd 100644 --- a/test/test_list.cpp +++ b/test/test_list.cpp @@ -100,6 +100,19 @@ namespace CHECK_EQUAL(data.max_size(), SIZE); } + //************************************************************************* + TEST(test_destruct_via_ilist) + { + int current_count = ItemNDC::get_instance_count(); + + DataNDC* pdata = new DataNDC(sorted_data.begin(), sorted_data.end()); + CHECK_EQUAL(int(current_count + sorted_data.size()), ItemNDC::get_instance_count()); + + IDataNDC* pidata = pdata; + delete pidata; + CHECK_EQUAL(current_count, ItemNDC::get_instance_count()); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_constructor_size) { diff --git a/test/test_map.cpp b/test/test_map.cpp index bc6b1a0c..a23397b4 100644 --- a/test/test_map.cpp +++ b/test/test_map.cpp @@ -183,6 +183,15 @@ namespace CHECK_EQUAL(data.max_size(), MAX_SIZE); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_destruct_via_imap) + { + Data* pdata = new Data(initial_data.begin(), initial_data.end()); + + IData* pidata = pdata; + delete pidata; + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_constructor_range) { diff --git a/test/test_multimap.cpp b/test/test_multimap.cpp index 6e8a280e..d71dc01e 100644 --- a/test/test_multimap.cpp +++ b/test/test_multimap.cpp @@ -183,6 +183,15 @@ namespace CHECK_EQUAL(data.max_size(), MAX_SIZE); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_destruct_via_imultimap) + { + Data* pdata = new Data(initial_data.begin(), initial_data.end()); + + IData* pidata = pdata; + delete pidata; + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_constructor_range) { diff --git a/test/test_multiset.cpp b/test/test_multiset.cpp index 0e443075..ab454fbd 100644 --- a/test/test_multiset.cpp +++ b/test/test_multiset.cpp @@ -175,6 +175,15 @@ namespace CHECK_EQUAL(data.max_size(), MAX_SIZE); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_destruct_via_imultiset) + { + Data* pdata = new Data(initial_data.begin(), initial_data.end()); + + IData* pidata = pdata; + delete pidata; + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_constructor_range) { diff --git a/test/test_priority_queue.cpp b/test/test_priority_queue.cpp index 8db4ca9c..c8fd99e6 100644 --- a/test/test_priority_queue.cpp +++ b/test/test_priority_queue.cpp @@ -78,6 +78,23 @@ namespace CHECK_EQUAL(priority_queue.max_size(), SIZE); } + //************************************************************************* + TEST(test_delete_via_ipriority_queue) + { + typedef etl::priority_queue priority_queue_t; + + priority_queue_t* ppriority_queue = new etl::priority_queue; + + etl::ipriority_queue* pipriority_queue = ppriority_queue; + + pipriority_queue->push(1); + pipriority_queue->push(2); + pipriority_queue->push(3); + pipriority_queue->push(4); + + delete pipriority_queue; + } + //************************************************************************* TEST(test_copy_constructor) { diff --git a/test/test_queue.cpp b/test/test_queue.cpp index d6c3bc00..09333a5c 100644 --- a/test/test_queue.cpp +++ b/test/test_queue.cpp @@ -97,6 +97,21 @@ namespace } } + //************************************************************************* + TEST(test_delete_via_iqueue) + { + etl::queue* pqueue = new etl::queue; + + etl::iqueue* piqueue = pqueue; + + piqueue->push(1); + piqueue->push(2); + piqueue->push(3); + piqueue->push(4); + + delete piqueue; + } + //************************************************************************* TEST(test_size) { diff --git a/test/test_reference_flat_map.cpp b/test/test_reference_flat_map.cpp index 544686ea..976b28ea 100644 --- a/test/test_reference_flat_map.cpp +++ b/test/test_reference_flat_map.cpp @@ -227,6 +227,17 @@ namespace CHECK(!data.empty()); } + //************************************************************************* + TEST(test_destruct_via_ireference_flat_map) + { + int current_count = NDC::get_instance_count(); + + DataNDC* pdata = new DataNDC(initial_data.begin(), initial_data.end()); + + IDataNDC* pidata = pdata; + delete pidata; + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_begin) { diff --git a/test/test_reference_flat_multimap.cpp b/test/test_reference_flat_multimap.cpp index 3cb25a30..f433cea2 100644 --- a/test/test_reference_flat_multimap.cpp +++ b/test/test_reference_flat_multimap.cpp @@ -185,6 +185,17 @@ namespace CHECK(!data.empty()); } + //************************************************************************* + TEST(test_destruct_via_ireference_flat_multimap) + { + int current_count = NDC::get_instance_count(); + + DataNDC* pdata = new DataNDC(initial_data.begin(), initial_data.end()); + + IDataNDC* pidata = pdata; + delete pidata; + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_begin) { diff --git a/test/test_reference_flat_multiset.cpp b/test/test_reference_flat_multiset.cpp index 29d60d91..f3ad4a34 100644 --- a/test/test_reference_flat_multiset.cpp +++ b/test/test_reference_flat_multiset.cpp @@ -171,6 +171,17 @@ namespace CHECK(!data.empty()); } + //************************************************************************* + TEST(test_destruct_via_ireference_flat_multiset) + { + int current_count = NDC::get_instance_count(); + + DataNDC* pdata = new DataNDC(initial_data.begin(), initial_data.end()); + + IDataNDC* pidata = pdata; + delete pidata; + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_begin) { diff --git a/test/test_reference_flat_set.cpp b/test/test_reference_flat_set.cpp index aba3e2b0..ff943446 100644 --- a/test/test_reference_flat_set.cpp +++ b/test/test_reference_flat_set.cpp @@ -167,6 +167,17 @@ namespace CHECK(!data.empty()); } + //************************************************************************* + TEST(test_destruct_via_ireference_flat_set) + { + int current_count = NDC::get_instance_count(); + + DataNDC* pdata = new DataNDC(initial_data.begin(), initial_data.end()); + + IDataNDC* pidata = pdata; + delete pidata; + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_begin) { diff --git a/test/test_set.cpp b/test/test_set.cpp index 52735afb..06b5607a 100644 --- a/test/test_set.cpp +++ b/test/test_set.cpp @@ -186,6 +186,15 @@ namespace CHECK_EQUAL(data.max_size(), MAX_SIZE); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_destruct_via_iset) + { + Data* pdata = new Data(initial_data.begin(), initial_data.end()); + + IData* pidata = pdata; + delete pidata; + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_constructor_range) { diff --git a/test/test_stack.cpp b/test/test_stack.cpp index 4810c410..74a1a164 100644 --- a/test/test_stack.cpp +++ b/test/test_stack.cpp @@ -102,6 +102,21 @@ namespace } } + //************************************************************************* + TEST(test_delete_via_istack) + { + etl::stack* pstack = new etl::stack; + + etl::istack* pistack = pstack; + + pistack->push(1); + pistack->push(2); + pistack->push(3); + pistack->push(4); + + delete pistack; + } + //************************************************************************* TEST(test_empty) { diff --git a/test/test_unordered_map.cpp b/test/test_unordered_map.cpp index 36de8899..470fbecd 100644 --- a/test/test_unordered_map.cpp +++ b/test/test_unordered_map.cpp @@ -231,6 +231,17 @@ namespace CHECK(data.full()); } + //************************************************************************* + TEST(test_destruct_via_iunordered_map) + { + int current_count = NDC::get_instance_count(); + + DataNDC* pdata = new DataNDC(initial_data.begin(), initial_data.end()); + + IDataNDC* pidata = pdata; + delete pidata; + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_assignment) { diff --git a/test/test_unordered_multimap.cpp b/test/test_unordered_multimap.cpp index 1d72fde8..d04dc25f 100644 --- a/test/test_unordered_multimap.cpp +++ b/test/test_unordered_multimap.cpp @@ -208,6 +208,17 @@ namespace CHECK(data.full()); } + //************************************************************************* + TEST(test_destruct_via_iunordered_multimap) + { + int current_count = NDC::get_instance_count(); + + DataNDC* pdata = new DataNDC(initial_data.begin(), initial_data.end()); + + IDataNDC* pidata = pdata; + delete pidata; + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_assignment) { diff --git a/test/test_unordered_multiset.cpp b/test/test_unordered_multiset.cpp index 05a084a5..0fddfcee 100644 --- a/test/test_unordered_multiset.cpp +++ b/test/test_unordered_multiset.cpp @@ -142,6 +142,17 @@ namespace CHECK(data.full()); } + //************************************************************************* + TEST(test_destruct_via_iunordered_multiset) + { + int current_count = NDC::get_instance_count(); + + DataNDC* pdata = new DataNDC(initial_data.begin(), initial_data.end()); + + IDataNDC* pidata = pdata; + delete pidata; + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_assignment) { diff --git a/test/test_unordered_set.cpp b/test/test_unordered_set.cpp index 0bd1d20f..e658451c 100644 --- a/test/test_unordered_set.cpp +++ b/test/test_unordered_set.cpp @@ -134,6 +134,17 @@ namespace CHECK(data.full()); } + //************************************************************************* + TEST(test_destruct_via_iunordered_set) + { + int current_count = NDC::get_instance_count(); + + DataNDC* pdata = new DataNDC(initial_data.begin(), initial_data.end()); + + IDataNDC* pidata = pdata; + delete pidata; + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_assignment) { diff --git a/test/test_vector_non_trivial.cpp b/test/test_vector_non_trivial.cpp index 6d0c4c15..c7c00a8b 100644 --- a/test/test_vector_non_trivial.cpp +++ b/test/test_vector_non_trivial.cpp @@ -36,7 +36,7 @@ #include "data.h" namespace -{ +{ SUITE(test_vector_non_trivial) { static const size_t SIZE = 10; @@ -44,6 +44,8 @@ namespace typedef TestDataNDC NDC; typedef TestDataDC DC; + static NDC ndc("NDC"); + typedef etl::vector DataNDC; typedef etl::ivector IDataNDC; typedef std::vector CompareDataNDC; @@ -51,7 +53,7 @@ namespace typedef etl::vector DataDC; typedef etl::ivector IDataDC; typedef std::vector CompareDataDC; - + CompareDataNDC initial_data; CompareDataNDC less_data; CompareDataNDC greater_data; @@ -89,6 +91,22 @@ namespace CHECK_EQUAL(data.max_size(), SIZE); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_destruct_via_ivector) + { + const size_t INITIAL_SIZE = 5; + const NDC INITIAL_VALUE("1"); + + int current_count = NDC::get_instance_count(); + + DataNDC* pdata = new DataNDC(INITIAL_SIZE, INITIAL_VALUE); + CHECK_EQUAL(int(current_count + INITIAL_SIZE), NDC::get_instance_count()); + + IDataNDC* pidata = pdata; + delete pidata; + CHECK_EQUAL(current_count, NDC::get_instance_count()); + } + //************************************************************************* TEST(test_iterator_comparison_empty) { @@ -152,7 +170,7 @@ namespace DataNDC data(initial_data.begin(), initial_data.end()); DataNDC data2(data); CHECK(data2 == data); - + data2[2] = NDC("X"); CHECK(data2 != data); } @@ -400,7 +418,7 @@ namespace CHECK(data.back() == compare_data.back()); } - + //************************************************************************* TEST_FIXTURE(SetupFixture, test_data) { @@ -676,7 +694,7 @@ namespace const size_t INITIAL_SIZE = 5; const size_t INSERT_SIZE = 3; const NDC INITIAL_VALUE("1"); - + for (size_t offset = 0; offset <= INITIAL_SIZE; ++offset) { CompareDataNDC compare_data; @@ -770,7 +788,7 @@ namespace offset = 4; CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); - + offset = data.size(); CHECK_THROW(data.insert(data.begin() + offset, initial_data.begin(), initial_data.end()), etl::vector_full); @@ -813,7 +831,7 @@ namespace CHECK(is_equal); } - + //************************************************************************* TEST_FIXTURE(SetupFixture, test_clear) { From 6a964ee90f6a24b24ab462d13a96a2d608dfb03e Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 30 Jan 2018 08:48:43 +0000 Subject: [PATCH 17/50] Ignore output files from 'random' algorithms. --- test/vs2017/.gitignore | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 test/vs2017/.gitignore diff --git a/test/vs2017/.gitignore b/test/vs2017/.gitignore new file mode 100644 index 00000000..c1a708db --- /dev/null +++ b/test/vs2017/.gitignore @@ -0,0 +1,5 @@ +/random_clcg.csv +/random_lcg.csv +/random_lsfr.csv +/random_mwc.csv +/random_xorshift.csv From 9f84521da88a536b8d14e104c6441b5b1d8d5701 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 30 Jan 2018 08:50:31 +0000 Subject: [PATCH 18/50] Update to 10.12.0 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 41d610c6..4c003f19 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=10.12.0 +version=10.13.0 author= John Wellbelove maintainer=John Wellbelove sentence=A C++ template library tailored for embedded systems. From 8089f74387b07072a19dadb5476391b2a1b63b5b Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 1 Feb 2018 10:12:53 +0000 Subject: [PATCH 19/50] Added protected destructor to base class. --- src/debounce.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/debounce.h b/src/debounce.h index 19e26c20..3d3d78b3 100644 --- a/src/debounce.h +++ b/src/debounce.h @@ -99,7 +99,14 @@ namespace etl //************************************************************************* debounce_base(bool initial_state = false) : state(initial_state ? (CURRENT | LAST) : 0), - count(START_COUNT) + count(START_COUNT) + { + } + + //************************************************************************* + /// Destructor. + //************************************************************************* + ~debounce_base() { } From f9699d3cd494e5675827173859a06136fe10b624 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 1 Feb 2018 10:13:48 +0000 Subject: [PATCH 20/50] Added ETL_POLYMORPHIC_XXX defines --- test/etl_profile.h | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/test/etl_profile.h b/test/etl_profile.h index a321fa85..c4668ca7 100644 --- a/test/etl_profile.h +++ b/test/etl_profile.h @@ -39,6 +39,34 @@ SOFTWARE. #define ETL_IDEQUE_REPAIR_ENABLE #define ETL_IN_UNIT_TEST +#define ETL_POLYMORPHIC_BITSET +#define ETL_POLYMORPHIC_DEQUE +#define ETL_POLYMORPHIC_FLAT_MAP +#define ETL_POLYMORPHIC_FLAT_MULTIMAP +#define ETL_POLYMORPHIC_FLAT_SET +#define ETL_POLYMORPHIC_FLAT_MULTISET +#define ETL_POLYMORPHIC_FORWARD_LIST +#define ETL_POLYMORPHIC_LIST +#define ETL_POLYMORPHIC_MAP +#define ETL_POLYMORPHIC_MULTIMAP +#define ETL_POLYMORPHIC_SET +#define ETL_POLYMORPHIC_MULTISET +#define ETL_POLYMORPHIC_QUEUE +#define ETL_POLYMORPHIC_STACK +#define ETL_POLYMORPHIC_REFERENCE_FLAT_MAP +#define ETL_POLYMORPHIC_REFERENCE_FLAT_MULTIMAP +#define ETL_POLYMORPHIC_REFERENCE_FLAT_SET +#define ETL_POLYMORPHIC_REFERENCE_FLAT_MULTISET +#define ETL_POLYMORPHIC_UNORDERED_MAP +#define ETL_POLYMORPHIC_UNORDERED_MULTIMAP +#define ETL_POLYMORPHIC_UNORDERED_SET +#define ETL_POLYMORPHIC_UNORDERED_MULTISET +#define ETL_POLYMORPHIC_STRINGS +#define ETL_POLYMORPHIC_POOL +#define ETL_POLYMORPHIC_VECTOR + +//#define ETL_POLYMORPHIC_CONTAINERS + #ifdef _MSC_VER #include "profiles/msvc_x86.h" #else From 135506b53487fa126dd0b47c6312046cbd6a2d7c Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 1 Feb 2018 10:15:51 +0000 Subject: [PATCH 21/50] Re-written to avoid 'undefined behavior' by allowing containers to be polymorphic or not base on a compile time macro. --- src/basic_string.h | 22 +++++++++++++++++++ src/bitset.h | 15 +++++++++++++ src/deque.h | 33 ++++++++++++++++++---------- src/flat_map.h | 26 ++++++++++++---------- src/flat_multimap.h | 26 ++++++++++++---------- src/flat_multiset.h | 26 ++++++++++++---------- src/flat_set.h | 26 ++++++++++++---------- src/forward_list.h | 33 ++++++++++++++++++---------- src/intrusive_forward_list.h | 7 ++++++ src/intrusive_list.h | 7 ++++++ src/intrusive_queue.h | 7 ++++++ src/intrusive_stack.h | 7 ++++++ src/list.h | 30 ++++++++++++++++---------- src/map.h | 33 ++++++++++++++++++---------- src/multimap.h | 35 +++++++++++++++++++----------- src/multiset.h | 35 +++++++++++++++++++----------- src/pool.h | 15 +++++++++++++ src/private/vector_base.h | 7 ++++++ src/queue.h | 34 +++++++++++++++++++---------- src/reference_flat_map.h | 15 +++++++++++++ src/reference_flat_multimap.h | 15 +++++++++++++ src/reference_flat_multiset.h | 15 +++++++++++++ src/reference_flat_set.h | 15 +++++++++++++ src/set.h | 37 +++++++++++++++++++++----------- src/stack.h | 33 ++++++++++++++++++---------- src/unordered_map.h | 26 ++++++++++++---------- src/unordered_multimap.h | 26 ++++++++++++---------- src/unordered_multiset.h | 26 ++++++++++++---------- src/unordered_set.h | 26 ++++++++++++---------- src/vector.h | 26 ++++++++++++---------- test/test_vector_non_trivial.cpp | 3 +++ 31 files changed, 485 insertions(+), 202 deletions(-) diff --git a/src/basic_string.h b/src/basic_string.h index 4fde9ebd..106803c6 100644 --- a/src/basic_string.h +++ b/src/basic_string.h @@ -235,6 +235,13 @@ namespace etl { } + //************************************************************************* + /// Destructor. + //************************************************************************* + ~string_base() + { + } + bool is_truncated; ///< Set to true if the operation truncated the string. size_type current_size; ///< The current number of elements in the string. const size_type CAPACITY; ///< The maximum number of elements in the string. @@ -1970,6 +1977,21 @@ namespace etl ibasic_string(const ibasic_string&); T* p_buffer; + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_STRINGS) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~ibasic_string() + { + } +#else + protected: + ~ibasic_string() + { + } +#endif }; //*************************************************************************** diff --git a/src/bitset.h b/src/bitset.h index 584b97dc..bb61db38 100644 --- a/src/bitset.h +++ b/src/bitset.h @@ -718,6 +718,21 @@ namespace etl const size_t NBITS; const size_t SIZE; element_t* pdata; + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_BITSET) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~ibitset() + { + } +#else + protected: + ~ibitset() + { + } +#endif }; //************************************************************************* diff --git a/src/deque.h b/src/deque.h index 014ee89c..0d0966cd 100644 --- a/src/deque.h +++ b/src/deque.h @@ -200,6 +200,13 @@ namespace etl { } + //************************************************************************* + /// Destructor. + //************************************************************************* + ~deque_base() + { + } + size_type current_size; ///< The current number of elements in the deque. const size_type CAPACITY; ///< The maximum number of elements in the deque. const size_type BUFFER_SIZE; ///< The number of elements in the buffer. @@ -622,17 +629,6 @@ namespace etl typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; - //************************************************************************* - /// Destructor. - //************************************************************************* - ~ideque() - { - if (!empty()) - { - initialise(); - } - } - //************************************************************************* /// Assigns a range to the deque. //************************************************************************* @@ -1975,6 +1971,21 @@ namespace etl // Disable copy construction. ideque(const ideque&); + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_DEQUE) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~ideque() + { + } +#else + protected: + ~ideque() + { + } +#endif }; //*************************************************************************** diff --git a/src/flat_map.h b/src/flat_map.h index cdd454b2..821e3baf 100644 --- a/src/flat_map.h +++ b/src/flat_map.h @@ -108,17 +108,6 @@ namespace etl public: - //************************************************************************* - /// Destructor. - //************************************************************************* - ~iflat_map() - { - if (!empty()) - { - clear(); - } - } - //********************************************************************* /// Returns an iterator to the beginning of the flat_map. ///\return An iterator to the beginning of the flat_map. @@ -606,6 +595,21 @@ namespace etl /// Internal debugging. etl::debug_count construct_count; + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_FLAT_MAP) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~iflat_map() + { + } +#else + protected: + ~iflat_map() + { + } +#endif }; //*************************************************************************** diff --git a/src/flat_multimap.h b/src/flat_multimap.h index 4d143951..07f99def 100644 --- a/src/flat_multimap.h +++ b/src/flat_multimap.h @@ -110,17 +110,6 @@ namespace etl public: - //************************************************************************* - /// Destructor. - //************************************************************************* - ~iflat_multimap() - { - if (!empty()) - { - clear(); - } - } - //********************************************************************* /// Returns an iterator to the beginning of the flat_multimap. ///\return An iterator to the beginning of the flat_multimap. @@ -557,6 +546,21 @@ namespace etl /// Internal debugging. etl::debug_count construct_count; + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_FLAT_MULTIMAP) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~iflat_multimap() + { + } +#else + protected: + ~iflat_multimap() + { + } +#endif }; //*************************************************************************** diff --git a/src/flat_multiset.h b/src/flat_multiset.h index 5c378a3c..6d4a05a3 100644 --- a/src/flat_multiset.h +++ b/src/flat_multiset.h @@ -86,17 +86,6 @@ namespace etl public: - //************************************************************************* - /// Destructor. - //************************************************************************* - ~iflat_multiset() - { - if (!empty()) - { - clear(); - } - } - //********************************************************************* /// Returns an iterator to the beginning of the flat_multiset. ///\return An iterator to the beginning of the flat_multiset. @@ -535,6 +524,21 @@ namespace etl /// Internal debugging. etl::debug_count construct_count; + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_FLAT_MULTISET) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~iflat_multiset() + { + } +#else + protected: + ~iflat_multiset() + { + } +#endif }; //*************************************************************************** diff --git a/src/flat_set.h b/src/flat_set.h index adb2de9f..0b5f17f0 100644 --- a/src/flat_set.h +++ b/src/flat_set.h @@ -86,17 +86,6 @@ namespace etl public: - //************************************************************************* - /// Destructor. - //************************************************************************* - ~iflat_set() - { - if (!empty()) - { - clear(); - } - } - //********************************************************************* /// Returns an iterator to the beginning of the flat_set. ///\return An iterator to the beginning of the flat_set. @@ -540,6 +529,21 @@ namespace etl /// Internal debugging. etl::debug_count construct_count; + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_FLAT_SET) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~iflat_set() + { + } +#else + protected: + ~iflat_set() + { + } +#endif }; //*************************************************************************** diff --git a/src/forward_list.h b/src/forward_list.h index 23fa7b3f..e9a2fc08 100644 --- a/src/forward_list.h +++ b/src/forward_list.h @@ -222,6 +222,13 @@ namespace etl { } + //************************************************************************* + /// Destructor. + //************************************************************************* + ~forward_list_base() + { + } + //************************************************************************* /// Get the head node. //************************************************************************* @@ -477,17 +484,6 @@ namespace etl typedef typename std::iterator_traits::difference_type difference_type; - //************************************************************************* - /// Destructor. - //************************************************************************* - ~iforward_list() - { - if (!empty()) - { - clear(); - } - } - //************************************************************************* /// Gets the beginning of the forward_list. //************************************************************************* @@ -1343,6 +1339,21 @@ namespace etl // Disable copy construction. iforward_list(const iforward_list&); + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_FORWARD_LIST) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~iforward_list() + { + } +#else + protected: + ~iforward_list() + { + } +#endif }; //************************************************************************* diff --git a/src/intrusive_forward_list.h b/src/intrusive_forward_list.h index c2d91d2b..1ac767dd 100644 --- a/src/intrusive_forward_list.h +++ b/src/intrusive_forward_list.h @@ -237,6 +237,13 @@ namespace etl size_t current_size; ///< Counts the number of elements in the list. + //************************************************************************* + /// Destructor + //************************************************************************* + ~intrusive_forward_list_base() + { + } + //************************************************************************* /// Is the intrusive_forward_list a trivial length? //************************************************************************* diff --git a/src/intrusive_list.h b/src/intrusive_list.h index a3d3be91..e78a2669 100644 --- a/src/intrusive_list.h +++ b/src/intrusive_list.h @@ -242,6 +242,13 @@ namespace etl size_t current_size; ///< Counts the number of elements in the list. + //************************************************************************* + /// Destructor + //************************************************************************* + ~intrusive_list_base() + { + } + //************************************************************************* /// Is the intrusive_list a trivial length? //************************************************************************* diff --git a/src/intrusive_queue.h b/src/intrusive_queue.h index bc3edc71..315e25ee 100644 --- a/src/intrusive_queue.h +++ b/src/intrusive_queue.h @@ -181,6 +181,13 @@ namespace etl { } + //************************************************************************* + /// Destructor + //************************************************************************* + ~intrusive_queue_base() + { + } + link_type* p_front; ///< The current front of the queue. link_type* p_back; ///< The current back of the queue. diff --git a/src/intrusive_stack.h b/src/intrusive_stack.h index 020ca3a0..9ead1175 100644 --- a/src/intrusive_stack.h +++ b/src/intrusive_stack.h @@ -188,6 +188,13 @@ namespace etl { } + //************************************************************************* + /// Destructor + //************************************************************************* + ~intrusive_stack_base() + { + } + link_type* p_top; ///< The current top of the stack. size_t current_size; ///< Counts the number of elements in the list. diff --git a/src/list.h b/src/list.h index f373fd29..65f9efc0 100644 --- a/src/list.h +++ b/src/list.h @@ -306,6 +306,13 @@ namespace etl { } + //************************************************************************* + /// Destructor. + //************************************************************************* + ~list_base() + { + } + etl::ipool* p_node_pool; ///< The pool of data nodes used in the list. node_t terminal_node; ///< The node that acts as the list start and end. const size_type MAX_SIZE; ///< The maximum size of the list. @@ -583,17 +590,6 @@ namespace etl typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; - //************************************************************************* - /// Destructor. - //************************************************************************* - ~ilist() - { - if (!empty()) - { - initialise(); - } - } - //************************************************************************* /// Gets the beginning of the list. //************************************************************************* @@ -1566,6 +1562,18 @@ namespace etl // Disable copy construction. ilist(const ilist&); + +#if defined(ETL_POLYMORPHIC_LIST) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~ilist() + { + } +#else + protected: + ~ilist() + { + } +#endif }; //************************************************************************* diff --git a/src/map.h b/src/map.h index 4c1dea50..61695cec 100644 --- a/src/map.h +++ b/src/map.h @@ -233,6 +233,13 @@ namespace etl { } + //************************************************************************* + /// Destructor + //************************************************************************* + ~map_base() + { + } + //************************************************************************* /// Balance the critical node at the position provided as needed //************************************************************************* @@ -801,17 +808,6 @@ namespace etl typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; - //************************************************************************* - /// Destructor. - //************************************************************************* - ~imap() - { - if (!empty()) - { - clear(); - } - } - //************************************************************************* /// Gets the beginning of the map. //************************************************************************* @@ -2007,6 +2003,21 @@ namespace etl // Disable copy construction. imap(const imap&); + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_MAP) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~imap() + { + } +#else + protected: + ~imap() + { + } +#endif }; //************************************************************************* diff --git a/src/multimap.h b/src/multimap.h index 4139c264..b5a5a897 100644 --- a/src/multimap.h +++ b/src/multimap.h @@ -224,7 +224,13 @@ namespace etl : current_size(0) , CAPACITY(max_size_) , root_node(nullptr) - + { + } + + //************************************************************************* + /// The constructor that is called from derived classes. + //************************************************************************* + ~multimap_base() { } @@ -952,17 +958,6 @@ namespace etl typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; - //************************************************************************* - /// Destructor. - //************************************************************************* - ~imultimap() - { - if (!empty()) - { - clear(); - } - } - //************************************************************************* /// Gets the beginning of the multimap. //************************************************************************* @@ -1892,6 +1887,22 @@ namespace etl // Disable copy construction. imultimap(const imultimap&); + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_MULTIMAP) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~imultimap() + { + } +#else + protected: + ~imultimap() + { + } +#endif + }; //************************************************************************* diff --git a/src/multiset.h b/src/multiset.h index 23e265ba..abdfd2e5 100644 --- a/src/multiset.h +++ b/src/multiset.h @@ -226,7 +226,14 @@ namespace etl , root_node(nullptr) { } - + + //************************************************************************* + /// Destructor. + //************************************************************************* + ~multiset_base() + { + } + //************************************************************************* /// Attach the provided node to the position provided //************************************************************************* @@ -932,17 +939,6 @@ namespace etl typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; - //************************************************************************* - /// Destructor. - //************************************************************************* - ~imultiset() - { - if (!empty()) - { - clear(); - } - } - //************************************************************************* /// Gets the beginning of the multiset. //************************************************************************* @@ -1872,6 +1868,21 @@ namespace etl // Disable copy construction. imultiset(const imultiset&); + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_MULTISET) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~imultiset() + { + } +#else + protected: + ~imultiset() + { + } +#endif }; //************************************************************************* diff --git a/src/pool.h b/src/pool.h index a945767a..01ff1a13 100644 --- a/src/pool.h +++ b/src/pool.h @@ -321,6 +321,21 @@ namespace etl const uint32_t ITEM_SIZE; ///< The size of allocated items. const uint32_t MAX_SIZE; ///< The maximum number of objects that can be allocated. + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_POOL) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~ipool() + { + } +#else + protected: + ~ipool() + { + } +#endif }; //************************************************************************* diff --git a/src/private/vector_base.h b/src/private/vector_base.h index 732ec657..bcd131ab 100644 --- a/src/private/vector_base.h +++ b/src/private/vector_base.h @@ -154,6 +154,13 @@ namespace etl { } + //************************************************************************* + /// Destructor. + //************************************************************************* + ~vector_base() + { + } + const size_type CAPACITY; /// /// \return A reference to the value at the front of the queue. @@ -485,6 +482,21 @@ namespace etl iqueue(const iqueue&); T* p_buffer; ///< The internal buffer. + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_QUEUE) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~iqueue() + { + } +#else + protected: + ~iqueue() + { + } +#endif }; //*************************************************************************** diff --git a/src/reference_flat_map.h b/src/reference_flat_map.h index bfd66da4..0963e77f 100644 --- a/src/reference_flat_map.h +++ b/src/reference_flat_map.h @@ -854,6 +854,21 @@ namespace etl ireference_flat_map& operator = (const ireference_flat_map&); lookup_t& lookup; + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_REFERENCE_FLAT_MAP) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~ireference_flat_map() + { + } +#else + protected: + ~ireference_flat_map() + { + } +#endif }; //*************************************************************************** diff --git a/src/reference_flat_multimap.h b/src/reference_flat_multimap.h index 6076596d..1b428e11 100644 --- a/src/reference_flat_multimap.h +++ b/src/reference_flat_multimap.h @@ -767,6 +767,21 @@ namespace etl ireference_flat_multimap& operator = (const ireference_flat_multimap&); lookup_t& lookup; + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_REFERENCE_FLAT_MULTIMAP) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~ireference_flat_multimap() + { + } +#else + protected: + ~ireference_flat_multimap() + { + } +#endif }; //*************************************************************************** diff --git a/src/reference_flat_multiset.h b/src/reference_flat_multiset.h index d0a2cd53..bd72dc1e 100644 --- a/src/reference_flat_multiset.h +++ b/src/reference_flat_multiset.h @@ -780,6 +780,21 @@ namespace etl ireference_flat_multiset& operator =(const ireference_flat_multiset&); lookup_t& lookup; + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_REFERENCE_FLAT_MULTISET) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~ireference_flat_multiset() + { + } +#else + protected: + ~ireference_flat_multiset() + { + } +#endif }; //*************************************************************************** diff --git a/src/reference_flat_set.h b/src/reference_flat_set.h index ef9f6089..3f4f7cb5 100644 --- a/src/reference_flat_set.h +++ b/src/reference_flat_set.h @@ -762,6 +762,21 @@ namespace etl ireference_flat_set& operator =(const ireference_flat_set&); lookup_t& lookup; + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_REFERENCE_FLAT_SET) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~ireference_flat_set() + { + } +#else + protected: + ~ireference_flat_set() + { + } +#endif }; //*************************************************************************** diff --git a/src/set.h b/src/set.h index be0407c4..a3040c57 100644 --- a/src/set.h +++ b/src/set.h @@ -227,6 +227,13 @@ namespace etl { } + //************************************************************************* + /// The constructor that is called from derived classes. + //************************************************************************* + ~set_base() + { + } + //************************************************************************* /// Attach the provided node to the position provided //************************************************************************* @@ -437,6 +444,7 @@ namespace etl const size_type CAPACITY; ///< The maximum size of the set. Node* root_node; ///< The node that acts as the set root. etl::debug_count construct_count; + }; //*************************************************************************** @@ -771,8 +779,7 @@ namespace etl typedef std::reverse_iterator reverse_iterator; typedef std::reverse_iterator const_reverse_iterator; - - + //************************************************************************* /// Assignment operator. //************************************************************************* @@ -786,17 +793,6 @@ namespace etl return *this; } - //************************************************************************* - /// Destructor. - //************************************************************************* - ~iset() - { - if (!empty()) - { - clear(); - } - } - //************************************************************************* /// Gets the beginning of the set. //************************************************************************* @@ -1930,6 +1926,21 @@ namespace etl // Disable copy construction. iset(const iset&); + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_SET) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~iset() + { + } +#else + protected: + ~iset() + { + } +#endif }; //************************************************************************* diff --git a/src/stack.h b/src/stack.h index 3bca539e..e4a36702 100644 --- a/src/stack.h +++ b/src/stack.h @@ -165,6 +165,13 @@ namespace etl { } + //************************************************************************* + /// Destructor. + //************************************************************************* + ~stack_base() + { + } + //************************************************************************* /// Increments the indexes value to record a stack addition. //************************************************************************* @@ -230,17 +237,6 @@ namespace etl public: - //************************************************************************* - /// Destructor. - //************************************************************************* - ~istack() - { - if (!empty()) - { - clear(); - } - } - //************************************************************************* /// Gets a reference to the value at the top of the stack.
/// \return A reference to the value at the top of the stack. @@ -454,6 +450,21 @@ namespace etl istack(const istack&); T* p_buffer; ///< The internal buffer. + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_STACK) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~istack() + { + } +#else + protected: + ~istack() + { + } +#endif }; //*************************************************************************** diff --git a/src/unordered_map.h b/src/unordered_map.h index d90304a1..c1d4d331 100644 --- a/src/unordered_map.h +++ b/src/unordered_map.h @@ -480,17 +480,6 @@ namespace etl typedef typename std::iterator_traits::difference_type difference_type; - //************************************************************************* - /// Destructor. - //************************************************************************* - ~iunordered_map() - { - if (!empty()) - { - clear(); - } - } - //********************************************************************* /// Returns an iterator to the beginning of the unordered_map. ///\return An iterator to the beginning of the unordered_map. @@ -1294,6 +1283,21 @@ namespace etl /// For library debugging purposes only. etl::debug_count construct_count; + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_UNORDERED_MAP) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~iunordered_map() + { + } +#else + protected: + ~iunordered_map() + { + } +#endif }; //*************************************************************************** diff --git a/src/unordered_multimap.h b/src/unordered_multimap.h index a8a8a969..ea8c5792 100644 --- a/src/unordered_multimap.h +++ b/src/unordered_multimap.h @@ -480,17 +480,6 @@ namespace etl typedef typename std::iterator_traits::difference_type difference_type; - //************************************************************************* - /// Destructor. - //************************************************************************* - ~iunordered_multimap() - { - if (!empty()) - { - clear(); - } - } - //********************************************************************* /// Returns an iterator to the beginning of the unordered_multimap. ///\return An iterator to the beginning of the unordered_multimap. @@ -1204,6 +1193,21 @@ namespace etl /// For library debugging purposes only. etl::debug_count construct_count; + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_UNORDERED_MULTIMAP) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~iunordered_multimap() + { + } +#else + protected: + ~iunordered_multimap() + { + } +#endif }; //*************************************************************************** diff --git a/src/unordered_multiset.h b/src/unordered_multiset.h index b42d3e4f..829849da 100644 --- a/src/unordered_multiset.h +++ b/src/unordered_multiset.h @@ -475,17 +475,6 @@ namespace etl typedef typename std::iterator_traits::difference_type difference_type; - //************************************************************************* - /// Destructor. - //************************************************************************* - ~iunordered_multiset() - { - if (!empty()) - { - clear(); - } - } - //********************************************************************* /// Returns an iterator to the beginning of the unordered_multiset. ///\return An iterator to the beginning of the unordered_multiset. @@ -1198,6 +1187,21 @@ namespace etl /// For library debugging purposes only. etl::debug_count construct_count; + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_UNORDERED_MULTISET) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~iunordered_multiset() + { + } +#else + protected: + ~iunordered_multiset() + { + } +#endif }; //*************************************************************************** diff --git a/src/unordered_set.h b/src/unordered_set.h index d8d6087d..5cf2bc86 100644 --- a/src/unordered_set.h +++ b/src/unordered_set.h @@ -476,17 +476,6 @@ namespace etl typedef typename std::iterator_traits::difference_type difference_type; - //************************************************************************* - /// Destructor. - //************************************************************************* - ~iunordered_set() - { - if (!empty()) - { - clear(); - } - } - //********************************************************************* /// Returns an iterator to the beginning of the unordered_set. ///\return An iterator to the beginning of the unordered_set. @@ -1175,6 +1164,21 @@ namespace etl /// For library debugging purposes only. etl::debug_count construct_count; + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_UNORDERED_SET) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~iunordered_set() + { + } +#else + protected: + ~iunordered_set() + { + } +#endif }; //*************************************************************************** diff --git a/src/vector.h b/src/vector.h index 2cc369df..bbc8b820 100644 --- a/src/vector.h +++ b/src/vector.h @@ -93,17 +93,6 @@ namespace etl public: - //************************************************************************* - /// Destructor. - //************************************************************************* - ~ivector() - { - if (!empty()) - { - clear(); - } - } - //********************************************************************* /// Returns an iterator to the beginning of the vector. ///\return An iterator to the beginning of the vector. @@ -968,6 +957,21 @@ namespace etl // Disable copy construction. ivector(const ivector&); + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_VECTOR) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual ~ivector() + { + } +#else + protected: + ~ivector() + { + } +#endif }; //*************************************************************************** diff --git a/test/test_vector_non_trivial.cpp b/test/test_vector_non_trivial.cpp index c7c00a8b..88c1e7f4 100644 --- a/test/test_vector_non_trivial.cpp +++ b/test/test_vector_non_trivial.cpp @@ -99,6 +99,9 @@ namespace int current_count = NDC::get_instance_count(); + DataNDC* p = new DataNDC(INITIAL_SIZE, INITIAL_VALUE); + delete p; + DataNDC* pdata = new DataNDC(INITIAL_SIZE, INITIAL_VALUE); CHECK_EQUAL(int(current_count + INITIAL_SIZE), NDC::get_instance_count()); From 61b872250074127f1614e4b8cba48ae5578344e7 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 1 Feb 2018 17:28:49 +0000 Subject: [PATCH 22/50] Added variant_pool generator. --- src/generate_variant_pool.bat | 1 + src/variant_pool.h | 70 +- src/variant_pool_generator.h | 479 ++++++++++++++ test/codeblocks/.gitignore | 1 + test/codeblocks/ETL.layout | 1052 +++++++++++++++---------------- test/vs2017/etl.vcxproj | 2 + test/vs2017/etl.vcxproj.filters | 9 + 7 files changed, 1064 insertions(+), 550 deletions(-) create mode 100644 src/generate_variant_pool.bat create mode 100644 src/variant_pool_generator.h diff --git a/src/generate_variant_pool.bat b/src/generate_variant_pool.bat new file mode 100644 index 00000000..87d1fba7 --- /dev/null +++ b/src/generate_variant_pool.bat @@ -0,0 +1 @@ +python -m cogapp -d -e -ovariant_pool.h -DNTypes=16 variant_pool_generator.h diff --git a/src/variant_pool.h b/src/variant_pool.h index f671776a..55e1a45a 100644 --- a/src/variant_pool.h +++ b/src/variant_pool.h @@ -26,6 +26,28 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ******************************************************************************/ +#if 0 +#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE. +#endif + +//*************************************************************************** +// This file has been auto generated. Do not edit this file. +//*************************************************************************** + +//*************************************************************************** +// To generate to header file, run this at the command line. +// Note: You will need Python and COG installed. +// +// python -m cogapp -d -e -ovariant_pool.h -DNTypes= variant_pool_generator.h +// Where is the number of types to support. +// +// e.g. +// To generate handlers for up to 16 types... +// python -m cogapp -d -e -ovariant_pool.h -DNTypes=16 variant_pool_generator.h +// +// See generate.bat +//*************************************************************************** + #ifndef __ETL_VARIANT_POOL__ #define __ETL_VARIANT_POOL__ @@ -82,21 +104,21 @@ namespace etl //*************************************************************************** template class variant_pool { @@ -282,15 +304,15 @@ namespace etl bool destroy(const T* const p) { STATIC_ASSERT((etl::is_one_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || - etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || + etl::is_base_of::value || etl::is_base_of::value || etl::is_base_of::value || etl::is_base_of::value || diff --git a/src/variant_pool_generator.h b/src/variant_pool_generator.h new file mode 100644 index 00000000..6ca24891 --- /dev/null +++ b/src/variant_pool_generator.h @@ -0,0 +1,479 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2017 jwellbelove + +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. +******************************************************************************/ + +/*[[[cog +import cog +cog.outl("#if 0") +]]]*/ +/*[[[end]]]*/ +#error THIS HEADER IS A GENERATOR. DO NOT INCLUDE. +/*[[[cog +import cog +cog.outl("#endif") +]]]*/ +/*[[[end]]]*/ + +/*[[[cog +import cog +cog.outl("//***************************************************************************") +cog.outl("// This file has been auto generated. Do not edit this file.") +cog.outl("//***************************************************************************") +]]]*/ +/*[[[end]]]*/ + +//*************************************************************************** +// To generate to header file, run this at the command line. +// Note: You will need Python and COG installed. +// +// python -m cogapp -d -e -ovariant_pool.h -DNTypes= variant_pool_generator.h +// Where is the number of types to support. +// +// e.g. +// To generate handlers for up to 16 types... +// python -m cogapp -d -e -ovariant_pool.h -DNTypes=16 variant_pool_generator.h +// +// See generate.bat +//*************************************************************************** + +#ifndef __ETL_VARIANT_POOL__ +#define __ETL_VARIANT_POOL__ + +#include +#include + +#include "platform.h" +#include "error_handler.h" +#include "exception.h" +#include "largest.h" +#include "type_traits.h" +#include "alignment.h" +#include "static_assert.h" +#include "type_lookup.h" +#include + +#undef ETL_FILE +#define ETL_FILE "40" + +namespace etl +{ + //*************************************************************************** + class variant_pool_exception : public etl::exception + { + public: + + variant_pool_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + : exception(reason_, file_name_, line_number_) + { + } + }; + + //*************************************************************************** + class variant_pool_cannot_create : public etl::variant_pool_exception + { + public: + + variant_pool_cannot_create(string_type file_name_, numeric_type line_number_) + : variant_pool_exception(ETL_ERROR_TEXT("variant_pool:cannot create", ETL_FILE"A"), file_name_, line_number_) + { + } + }; + + //*************************************************************************** + class variant_pool_did_not_create : public etl::variant_pool_exception + { + public: + + variant_pool_did_not_create(string_type file_name_, numeric_type line_number_) + : variant_pool_exception(ETL_ERROR_TEXT("variant_pool:did not create", ETL_FILE"B"), file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /*[[[cog + import cog + cog.outl("template " % int(NTypes)) + ]]]*/ + /*[[[end]]]*/ + class variant_pool + { + public: + + static const size_t MAX_SIZE = MAX_SIZE_; + + //************************************************************************* + /// Default constructor. + //************************************************************************* + variant_pool() + { + } + +#if !ETL_CPP11_SUPPORTED + //************************************************************************* + /// Creates the object. Default constructor. + //************************************************************************* + template + T* create() + { + /*[[[cog + import cog + cog.out("STATIC_ASSERT((etl::is_one_of::value), \"Unsupported type\");" % int(NTypes)) + ]]]*/ + /*[[[end]]]*/ + + T* p = nullptr; + + if (pool.full()) + { + ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create)); + } + else + { + p = pool.template allocate(); + + if (p != nullptr) + { + new (p) T(); + } + } + + return p; + } + + //************************************************************************* + /// Creates the object. One parameter constructor. + //************************************************************************* + template + T* create(const TP1& p1) + { + /*[[[cog + import cog + cog.out("STATIC_ASSERT((etl::is_one_of::value), \"Unsupported type\");" % int(NTypes)) + ]]]*/ + /*[[[end]]]*/ + + T* p = nullptr; + + if (pool.full()) + { + ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create)); + } + else + { + p = pool.template allocate(); + + if (p != nullptr) + { + new (p) T(p1); + } + } + + return p; + } + + //************************************************************************* + /// Creates the object. Two parameter constructor. + //************************************************************************* + template + T* create(const TP1& p1, const TP2& p2) + { + /*[[[cog + import cog + cog.out("STATIC_ASSERT((etl::is_one_of::value), \"Unsupported type\");" % int(NTypes)) + ]]]*/ + /*[[[end]]]*/ + + T* p = nullptr; + + if (pool.full()) + { + ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create)); + } + else + { + p = pool.template allocate(); + + if (p != nullptr) + { + new (p) T(p1, p2); + } + } + + return p; + } + + //************************************************************************* + /// Creates the object. Three parameter constructor. + //************************************************************************* + template + T* create(const TP1& p1, const TP2& p2, const TP3& p3) + { + /*[[[cog + import cog + cog.out("STATIC_ASSERT((etl::is_one_of::value), \"Unsupported type\");" % int(NTypes)) + ]]]*/ + /*[[[end]]]*/ + + T* p = nullptr; + + if (pool.full()) + { + ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create)); + } + else + { + p = pool.template allocate(); + + if (p != nullptr) + { + new (p) T(p1, p2, p3); + } + } + + return p; + } + + //************************************************************************* + /// Creates the object. Four parameter constructor. + //************************************************************************* + template + T* create(const TP1& p1, const TP2& p2, const TP3& p3, const TP4& p4) + { + /*[[[cog + import cog + cog.out("STATIC_ASSERT((etl::is_one_of::value), \"Unsupported type\");" % int(NTypes)) + ]]]*/ + /*[[[end]]]*/ + + T* p = nullptr; + + if (pool.full()) + { + ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create)); + } + else + { + p = pool.template allocate(); + + if (p != nullptr) + { + new (p) T(p1, p2, p3, p4); + } + } + + return p; + } +#else + //************************************************************************* + /// Creates the object from a type. Variadic parameter constructor. + //************************************************************************* + template + T* create(Args&&... args) + { + /*[[[cog + import cog + cog.out("STATIC_ASSERT((etl::is_one_of::value), \"Unsupported type\");" % int(NTypes)) + ]]]*/ + /*[[[end]]]*/ + + T* p = nullptr; + + if (pool.full()) + { + ETL_ASSERT(false, ETL_ERROR(etl::variant_pool_cannot_create)); + } + else + { + p = pool.template allocate(); + + if (p != nullptr) + { + new (p) T(std::forward(args)...); + } + } + + return p; + } +#endif + + //************************************************************************* + /// Destroys the object. + //************************************************************************* + template + bool destroy(const T* const p) + { + /*[[[cog + import cog + cog.out("STATIC_ASSERT((etl::is_one_of::value ||" % int(NTypes)) + + for n in range(1, int(NTypes)): + cog.outl(" etl::is_base_of::value ||" % n) + cog.outl(" etl::is_base_of::value), \"Invalid type\");" % int(NTypes)) + + ]]]*/ + /*[[[end]]]*/ + + p->~T(); + + void* vp = reinterpret_cast(const_cast(p)); + + if (pool.is_in_pool(vp)) + { + pool.release(vp); + return true; + } + else + { + ETL_ASSERT(false, ETL_ERROR(variant_pool_did_not_create)); + return false; + } + } + + //************************************************************************* + /// Returns the maximum number of items in the variant_pool. + //************************************************************************* + size_t max_size() const + { + return MAX_SIZE; + } + + //************************************************************************* + /// Returns the number of free items in the variant_pool. + //************************************************************************* + size_t available() const + { + return pool.available(); + } + + //************************************************************************* + /// Returns the number of allocated items in the variant_pool. + //************************************************************************* + size_t size() const + { + return pool.size(); + } + + //************************************************************************* + /// Checks to see if there are no allocated items in the variant_pool. + /// \return true if there are none allocated. + //************************************************************************* + bool empty() const + { + return pool.empty(); + } + + //************************************************************************* + /// Checks to see if there are no free items in the variant_pool. + /// \return true if there are none free. + //************************************************************************* + bool full() const + { + return pool.full(); + } + + private: + + variant_pool(const variant_pool&); + variant_pool& operator =(const variant_pool&); + + // The pool. + /*[[[cog + import cog + cog.out("etl::generic_pool::size," % int(NTypes)) + + cog.out(" etl::largest<") + for n in range(1, int(NTypes)): + cog.out("T%s, " % n) + if n % 16 == 0: + cog.outl("") + cog.out(" ") + cog.outl("T%s>::alignment," % int(NTypes)) + cog.outl(" MAX_SIZE> pool;") + ]]]*/ + /*[[[end]]]*/ + }; +} + +#undef ETL_FILE + +#endif diff --git a/test/codeblocks/.gitignore b/test/codeblocks/.gitignore index 1c0f0f11..bb6d6ef9 100644 --- a/test/codeblocks/.gitignore +++ b/test/codeblocks/.gitignore @@ -2,3 +2,4 @@ random_*.csv /ETL.depend /ETL.layout *.depend +*.layout diff --git a/test/codeblocks/ETL.layout b/test/codeblocks/ETL.layout index 9c71eeb5..5b77f6af 100644 --- a/test/codeblocks/ETL.layout +++ b/test/codeblocks/ETL.layout @@ -2,439 +2,49 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + @@ -442,9 +52,154 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -457,124 +212,19 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -582,4 +232,354 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/vs2017/etl.vcxproj b/test/vs2017/etl.vcxproj index 49eab9a4..46b66b98 100644 --- a/test/vs2017/etl.vcxproj +++ b/test/vs2017/etl.vcxproj @@ -171,6 +171,7 @@ + @@ -478,6 +479,7 @@ + diff --git a/test/vs2017/etl.vcxproj.filters b/test/vs2017/etl.vcxproj.filters index dea71e14..77db216e 100644 --- a/test/vs2017/etl.vcxproj.filters +++ b/test/vs2017/etl.vcxproj.filters @@ -58,6 +58,9 @@ {4ac80fd1-3eca-4775-8695-eb1ea39c93f1} + + {e4a699ae-e7f3-418e-bf9f-211c21f7f4b2} + @@ -570,6 +573,9 @@ ETL\Containers + + ETL\Containers\Generators + @@ -985,6 +991,9 @@ Resource Files + + Resource Files + From 857932352e33500bc943dbdebf8f6e3e40f6abf7 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 1 Feb 2018 17:29:44 +0000 Subject: [PATCH 23/50] Make code match master --- src/container.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/container.h b/src/container.h index 5e622566..5fffc7b7 100644 --- a/src/container.h +++ b/src/container.h @@ -295,11 +295,11 @@ namespace etl char(&array_size(T(&array)[ARRAY_SIZE]))[ARRAY_SIZE]; } -//#if ETL_CPP11_SUPPORTED -// #define ETL_ARRAY_SIZE(a) (etl::size(a)) -//#else +#if ETL_CPP11_SUPPORTED + #define ETL_ARRAY_SIZE(a) (etl::size(a)) +#else #define ETL_ARRAY_SIZE(a) sizeof(etl::array_size(a)) -//#endif +#endif #endif From fb43e3feb859df139c7b59d20c84bb89fdd884eb Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 1 Feb 2018 17:48:04 +0000 Subject: [PATCH 24/50] Update to 10.14.0 --- library.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 4c003f19..b5e1ea58 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=10.13.0 +version=10.14.0 author= John Wellbelove maintainer=John Wellbelove sentence=A C++ template library tailored for embedded systems. From 246eeef00d0460829e2a4584e7fcf488414664e0 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 2 Feb 2018 13:48:03 +0000 Subject: [PATCH 25/50] Added protected destructors to FSM & message_timer and code to message router packet destructor to choose correct method of destruction. --- library.properties | 2 +- src/fsm.h | 87 +-- src/fsm_generator.h | 9 +- src/message.h | 18 +- src/message_router.h | 344 ++++++++++- src/message_router_generator.h | 30 +- src/message_timer.h | 7 + test/codeblocks/ETL.layout | 1026 ++++++++++++++++---------------- test/etl_profile.h | 3 + 9 files changed, 947 insertions(+), 579 deletions(-) diff --git a/library.properties b/library.properties index b5e1ea58..d15af2ef 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=10.14.0 +version=10.15.0 author= John Wellbelove maintainer=John Wellbelove sentence=A C++ template library tailored for embedded systems. diff --git a/src/fsm.h b/src/fsm.h index 8a9a9a7f..51a48f0a 100644 --- a/src/fsm.h +++ b/src/fsm.h @@ -165,6 +165,13 @@ namespace etl { } + //******************************************* + /// Destructor. + //******************************************* + ~ifsm_state() + { + } + //******************************************* inline etl::fsm& get_fsm_context() const { @@ -346,10 +353,10 @@ namespace etl //*************************************************************************** // The definition for all 16 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -407,10 +414,10 @@ namespace etl //*************************************************************************** // Specialisation for 15 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -467,10 +474,10 @@ namespace etl //*************************************************************************** // Specialisation for 14 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -526,10 +533,10 @@ namespace etl //*************************************************************************** // Specialisation for 13 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -584,9 +591,9 @@ namespace etl //*************************************************************************** // Specialisation for 12 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -640,9 +647,9 @@ namespace etl //*************************************************************************** // Specialisation for 11 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -695,9 +702,9 @@ namespace etl //*************************************************************************** // Specialisation for 10 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -749,9 +756,9 @@ namespace etl //*************************************************************************** // Specialisation for 9 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -802,8 +809,8 @@ namespace etl //*************************************************************************** // Specialisation for 8 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -853,8 +860,8 @@ namespace etl //*************************************************************************** // Specialisation for 7 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -903,8 +910,8 @@ namespace etl //*************************************************************************** // Specialisation for 6 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -952,8 +959,8 @@ namespace etl //*************************************************************************** // Specialisation for 5 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -1000,7 +1007,7 @@ namespace etl //*************************************************************************** // Specialisation for 4 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -1046,7 +1053,7 @@ namespace etl //*************************************************************************** // Specialisation for 3 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -1091,7 +1098,7 @@ namespace etl //*************************************************************************** // Specialisation for 2 message types. //*************************************************************************** - template class fsm_state : public ifsm_state { @@ -1135,7 +1142,7 @@ namespace etl //*************************************************************************** // Specialisation for 1 message type. //*************************************************************************** - template class fsm_state : public ifsm_state { diff --git a/src/fsm_generator.h b/src/fsm_generator.h index 20c06789..4f50006e 100644 --- a/src/fsm_generator.h +++ b/src/fsm_generator.h @@ -177,6 +177,13 @@ namespace etl { } + //******************************************* + /// Destructor. + //******************************************* + ~ifsm_state() + { + } + //******************************************* inline etl::fsm& get_fsm_context() const { @@ -300,7 +307,7 @@ namespace etl /// Does this FSM accept the message id? /// Yes, it accepts everything! //******************************************* - bool accepts(etl::message_id_t id) const + bool accepts(etl::message_id_t) const { return true; } diff --git a/src/message.h b/src/message.h index 1667a0e5..4d83fb7b 100644 --- a/src/message.h +++ b/src/message.h @@ -68,18 +68,24 @@ namespace etl { public: -#ifdef ETL_MESSAGES_ARE_VIRTUAL - virtual ~imessage() - { - } -#endif - imessage(etl::message_id_t id) : message_id(id) { } const etl::message_id_t message_id; + +#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) + public: + virtual ~imessage() + { + } +#else + protected: + ~imessage() + { + } +#endif }; //*************************************************************************** diff --git a/src/message_router.h b/src/message_router.h index d7c7b5c7..0cf4a4f7 100644 --- a/src/message_router.h +++ b/src/message_router.h @@ -295,7 +295,34 @@ namespace etl //******************************************** ~message_packet() { - static_cast(data)->~imessage(); + etl::imessage* pmsg = static_cast(data); + + #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) + pmsg->~imessage(); + #else + size_t id = pmsg->message_id; + + switch (id) + { + case T1::ID: static_cast(pmsg)->~T1(); break; + case T2::ID: static_cast(pmsg)->~T2(); break; + case T3::ID: static_cast(pmsg)->~T3(); break; + case T4::ID: static_cast(pmsg)->~T4(); break; + case T5::ID: static_cast(pmsg)->~T5(); break; + case T6::ID: static_cast(pmsg)->~T6(); break; + case T7::ID: static_cast(pmsg)->~T7(); break; + case T8::ID: static_cast(pmsg)->~T8(); break; + case T9::ID: static_cast(pmsg)->~T9(); break; + case T10::ID: static_cast(pmsg)->~T10(); break; + case T11::ID: static_cast(pmsg)->~T11(); break; + case T12::ID: static_cast(pmsg)->~T12(); break; + case T13::ID: static_cast(pmsg)->~T13(); break; + case T14::ID: static_cast(pmsg)->~T14(); break; + case T15::ID: static_cast(pmsg)->~T15(); break; + case T16::ID: static_cast(pmsg)->~T16(); break; + default: assert(false); break; + } + #endif } //******************************************** @@ -454,7 +481,33 @@ namespace etl //******************************************** ~message_packet() { - static_cast(data)->~imessage(); + etl::imessage* pmsg = static_cast(data); + + #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) + pmsg->~imessage(); + #else + size_t id = pmsg->message_id; + + switch (id) + { + case T1::ID: static_cast(pmsg)->~T1(); break; + case T2::ID: static_cast(pmsg)->~T2(); break; + case T3::ID: static_cast(pmsg)->~T3(); break; + case T4::ID: static_cast(pmsg)->~T4(); break; + case T5::ID: static_cast(pmsg)->~T5(); break; + case T6::ID: static_cast(pmsg)->~T6(); break; + case T7::ID: static_cast(pmsg)->~T7(); break; + case T8::ID: static_cast(pmsg)->~T8(); break; + case T9::ID: static_cast(pmsg)->~T9(); break; + case T10::ID: static_cast(pmsg)->~T10(); break; + case T11::ID: static_cast(pmsg)->~T11(); break; + case T12::ID: static_cast(pmsg)->~T12(); break; + case T13::ID: static_cast(pmsg)->~T13(); break; + case T14::ID: static_cast(pmsg)->~T14(); break; + case T15::ID: static_cast(pmsg)->~T15(); break; + default: assert(false); break; + } + #endif } //******************************************** @@ -611,7 +664,32 @@ namespace etl //******************************************** ~message_packet() { - static_cast(data)->~imessage(); + etl::imessage* pmsg = static_cast(data); + + #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) + pmsg->~imessage(); + #else + size_t id = pmsg->message_id; + + switch (id) + { + case T1::ID: static_cast(pmsg)->~T1(); break; + case T2::ID: static_cast(pmsg)->~T2(); break; + case T3::ID: static_cast(pmsg)->~T3(); break; + case T4::ID: static_cast(pmsg)->~T4(); break; + case T5::ID: static_cast(pmsg)->~T5(); break; + case T6::ID: static_cast(pmsg)->~T6(); break; + case T7::ID: static_cast(pmsg)->~T7(); break; + case T8::ID: static_cast(pmsg)->~T8(); break; + case T9::ID: static_cast(pmsg)->~T9(); break; + case T10::ID: static_cast(pmsg)->~T10(); break; + case T11::ID: static_cast(pmsg)->~T11(); break; + case T12::ID: static_cast(pmsg)->~T12(); break; + case T13::ID: static_cast(pmsg)->~T13(); break; + case T14::ID: static_cast(pmsg)->~T14(); break; + default: assert(false); break; + } + #endif } //******************************************** @@ -766,7 +844,31 @@ namespace etl //******************************************** ~message_packet() { - static_cast(data)->~imessage(); + etl::imessage* pmsg = static_cast(data); + + #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) + pmsg->~imessage(); + #else + size_t id = pmsg->message_id; + + switch (id) + { + case T1::ID: static_cast(pmsg)->~T1(); break; + case T2::ID: static_cast(pmsg)->~T2(); break; + case T3::ID: static_cast(pmsg)->~T3(); break; + case T4::ID: static_cast(pmsg)->~T4(); break; + case T5::ID: static_cast(pmsg)->~T5(); break; + case T6::ID: static_cast(pmsg)->~T6(); break; + case T7::ID: static_cast(pmsg)->~T7(); break; + case T8::ID: static_cast(pmsg)->~T8(); break; + case T9::ID: static_cast(pmsg)->~T9(); break; + case T10::ID: static_cast(pmsg)->~T10(); break; + case T11::ID: static_cast(pmsg)->~T11(); break; + case T12::ID: static_cast(pmsg)->~T12(); break; + case T13::ID: static_cast(pmsg)->~T13(); break; + default: assert(false); break; + } + #endif } //******************************************** @@ -918,7 +1020,30 @@ namespace etl //******************************************** ~message_packet() { - static_cast(data)->~imessage(); + etl::imessage* pmsg = static_cast(data); + + #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) + pmsg->~imessage(); + #else + size_t id = pmsg->message_id; + + switch (id) + { + case T1::ID: static_cast(pmsg)->~T1(); break; + case T2::ID: static_cast(pmsg)->~T2(); break; + case T3::ID: static_cast(pmsg)->~T3(); break; + case T4::ID: static_cast(pmsg)->~T4(); break; + case T5::ID: static_cast(pmsg)->~T5(); break; + case T6::ID: static_cast(pmsg)->~T6(); break; + case T7::ID: static_cast(pmsg)->~T7(); break; + case T8::ID: static_cast(pmsg)->~T8(); break; + case T9::ID: static_cast(pmsg)->~T9(); break; + case T10::ID: static_cast(pmsg)->~T10(); break; + case T11::ID: static_cast(pmsg)->~T11(); break; + case T12::ID: static_cast(pmsg)->~T12(); break; + default: assert(false); break; + } + #endif } //******************************************** @@ -1068,7 +1193,29 @@ namespace etl //******************************************** ~message_packet() { - static_cast(data)->~imessage(); + etl::imessage* pmsg = static_cast(data); + + #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) + pmsg->~imessage(); + #else + size_t id = pmsg->message_id; + + switch (id) + { + case T1::ID: static_cast(pmsg)->~T1(); break; + case T2::ID: static_cast(pmsg)->~T2(); break; + case T3::ID: static_cast(pmsg)->~T3(); break; + case T4::ID: static_cast(pmsg)->~T4(); break; + case T5::ID: static_cast(pmsg)->~T5(); break; + case T6::ID: static_cast(pmsg)->~T6(); break; + case T7::ID: static_cast(pmsg)->~T7(); break; + case T8::ID: static_cast(pmsg)->~T8(); break; + case T9::ID: static_cast(pmsg)->~T9(); break; + case T10::ID: static_cast(pmsg)->~T10(); break; + case T11::ID: static_cast(pmsg)->~T11(); break; + default: assert(false); break; + } + #endif } //******************************************** @@ -1216,7 +1363,28 @@ namespace etl //******************************************** ~message_packet() { - static_cast(data)->~imessage(); + etl::imessage* pmsg = static_cast(data); + + #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) + pmsg->~imessage(); + #else + size_t id = pmsg->message_id; + + switch (id) + { + case T1::ID: static_cast(pmsg)->~T1(); break; + case T2::ID: static_cast(pmsg)->~T2(); break; + case T3::ID: static_cast(pmsg)->~T3(); break; + case T4::ID: static_cast(pmsg)->~T4(); break; + case T5::ID: static_cast(pmsg)->~T5(); break; + case T6::ID: static_cast(pmsg)->~T6(); break; + case T7::ID: static_cast(pmsg)->~T7(); break; + case T8::ID: static_cast(pmsg)->~T8(); break; + case T9::ID: static_cast(pmsg)->~T9(); break; + case T10::ID: static_cast(pmsg)->~T10(); break; + default: assert(false); break; + } + #endif } //******************************************** @@ -1362,7 +1530,27 @@ namespace etl //******************************************** ~message_packet() { - static_cast(data)->~imessage(); + etl::imessage* pmsg = static_cast(data); + + #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) + pmsg->~imessage(); + #else + size_t id = pmsg->message_id; + + switch (id) + { + case T1::ID: static_cast(pmsg)->~T1(); break; + case T2::ID: static_cast(pmsg)->~T2(); break; + case T3::ID: static_cast(pmsg)->~T3(); break; + case T4::ID: static_cast(pmsg)->~T4(); break; + case T5::ID: static_cast(pmsg)->~T5(); break; + case T6::ID: static_cast(pmsg)->~T6(); break; + case T7::ID: static_cast(pmsg)->~T7(); break; + case T8::ID: static_cast(pmsg)->~T8(); break; + case T9::ID: static_cast(pmsg)->~T9(); break; + default: assert(false); break; + } + #endif } //******************************************** @@ -1505,7 +1693,26 @@ namespace etl //******************************************** ~message_packet() { - static_cast(data)->~imessage(); + etl::imessage* pmsg = static_cast(data); + + #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) + pmsg->~imessage(); + #else + size_t id = pmsg->message_id; + + switch (id) + { + case T1::ID: static_cast(pmsg)->~T1(); break; + case T2::ID: static_cast(pmsg)->~T2(); break; + case T3::ID: static_cast(pmsg)->~T3(); break; + case T4::ID: static_cast(pmsg)->~T4(); break; + case T5::ID: static_cast(pmsg)->~T5(); break; + case T6::ID: static_cast(pmsg)->~T6(); break; + case T7::ID: static_cast(pmsg)->~T7(); break; + case T8::ID: static_cast(pmsg)->~T8(); break; + default: assert(false); break; + } + #endif } //******************************************** @@ -1646,7 +1853,25 @@ namespace etl //******************************************** ~message_packet() { - static_cast(data)->~imessage(); + etl::imessage* pmsg = static_cast(data); + + #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) + pmsg->~imessage(); + #else + size_t id = pmsg->message_id; + + switch (id) + { + case T1::ID: static_cast(pmsg)->~T1(); break; + case T2::ID: static_cast(pmsg)->~T2(); break; + case T3::ID: static_cast(pmsg)->~T3(); break; + case T4::ID: static_cast(pmsg)->~T4(); break; + case T5::ID: static_cast(pmsg)->~T5(); break; + case T6::ID: static_cast(pmsg)->~T6(); break; + case T7::ID: static_cast(pmsg)->~T7(); break; + default: assert(false); break; + } + #endif } //******************************************** @@ -1784,7 +2009,24 @@ namespace etl //******************************************** ~message_packet() { - static_cast(data)->~imessage(); + etl::imessage* pmsg = static_cast(data); + + #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) + pmsg->~imessage(); + #else + size_t id = pmsg->message_id; + + switch (id) + { + case T1::ID: static_cast(pmsg)->~T1(); break; + case T2::ID: static_cast(pmsg)->~T2(); break; + case T3::ID: static_cast(pmsg)->~T3(); break; + case T4::ID: static_cast(pmsg)->~T4(); break; + case T5::ID: static_cast(pmsg)->~T5(); break; + case T6::ID: static_cast(pmsg)->~T6(); break; + default: assert(false); break; + } + #endif } //******************************************** @@ -1920,7 +2162,23 @@ namespace etl //******************************************** ~message_packet() { - static_cast(data)->~imessage(); + etl::imessage* pmsg = static_cast(data); + + #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) + pmsg->~imessage(); + #else + size_t id = pmsg->message_id; + + switch (id) + { + case T1::ID: static_cast(pmsg)->~T1(); break; + case T2::ID: static_cast(pmsg)->~T2(); break; + case T3::ID: static_cast(pmsg)->~T3(); break; + case T4::ID: static_cast(pmsg)->~T4(); break; + case T5::ID: static_cast(pmsg)->~T5(); break; + default: assert(false); break; + } + #endif } //******************************************** @@ -2053,7 +2311,22 @@ namespace etl //******************************************** ~message_packet() { - static_cast(data)->~imessage(); + etl::imessage* pmsg = static_cast(data); + + #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) + pmsg->~imessage(); + #else + size_t id = pmsg->message_id; + + switch (id) + { + case T1::ID: static_cast(pmsg)->~T1(); break; + case T2::ID: static_cast(pmsg)->~T2(); break; + case T3::ID: static_cast(pmsg)->~T3(); break; + case T4::ID: static_cast(pmsg)->~T4(); break; + default: assert(false); break; + } + #endif } //******************************************** @@ -2184,7 +2457,21 @@ namespace etl //******************************************** ~message_packet() { - static_cast(data)->~imessage(); + etl::imessage* pmsg = static_cast(data); + + #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) + pmsg->~imessage(); + #else + size_t id = pmsg->message_id; + + switch (id) + { + case T1::ID: static_cast(pmsg)->~T1(); break; + case T2::ID: static_cast(pmsg)->~T2(); break; + case T3::ID: static_cast(pmsg)->~T3(); break; + default: assert(false); break; + } + #endif } //******************************************** @@ -2313,7 +2600,20 @@ namespace etl //******************************************** ~message_packet() { - static_cast(data)->~imessage(); + etl::imessage* pmsg = static_cast(data); + + #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) + pmsg->~imessage(); + #else + size_t id = pmsg->message_id; + + switch (id) + { + case T1::ID: static_cast(pmsg)->~T1(); break; + case T2::ID: static_cast(pmsg)->~T2(); break; + default: assert(false); break; + } + #endif } //******************************************** @@ -2440,7 +2740,19 @@ namespace etl //******************************************** ~message_packet() { - static_cast(data)->~imessage(); + etl::imessage* pmsg = static_cast(data); + + #if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES) + pmsg->~imessage(); + #else + size_t id = pmsg->message_id; + + switch (id) + { + case T1::ID: static_cast(pmsg)->~T1(); break; + default: assert(false); break; + } + #endif } //******************************************** diff --git a/src/message_router_generator.h b/src/message_router_generator.h index 26d67413..9b43caec 100644 --- a/src/message_router_generator.h +++ b/src/message_router_generator.h @@ -309,7 +309,20 @@ namespace etl cog.outl(" //********************************************") cog.outl(" ~message_packet()") cog.outl(" {") - cog.outl(" static_cast(data)->~imessage();") + cog.outl(" etl::imessage* pmsg = static_cast(data);") + cog.outl("") + cog.outl("#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)") + cog.outl(" pmsg->~imessage();") + cog.outl("#else") + cog.outl(" size_t id = pmsg->message_id;") + cog.outl("") + cog.outl(" switch (id)") + cog.outl(" {") + for n in range(1, int(Handlers) + 1): + cog.outl(" case T%s::ID: static_cast(pmsg)->~T%s(); break;" % (n, n, n)) + cog.outl(" default: assert(false); break;") + cog.outl(" }") + cog.outl("#endif") cog.outl(" }") cog.outl("") cog.outl(" //********************************************") @@ -481,7 +494,20 @@ namespace etl cog.outl(" //********************************************") cog.outl(" ~message_packet()") cog.outl(" {") - cog.outl(" static_cast(data)->~imessage();") + cog.outl(" etl::imessage* pmsg = static_cast(data);") + cog.outl("") + cog.outl("#if defined(ETL_MESSAGES_ARE_VIRTUAL) || defined(ETL_POLYMORPHIC_MESSAGES)") + cog.outl(" pmsg->~imessage();") + cog.outl("#else") + cog.outl(" size_t id = pmsg->message_id;") + cog.outl("") + cog.outl(" switch (id)") + cog.outl(" {") + for t in range(1, n + 1): + cog.outl(" case T%s::ID: static_cast(pmsg)->~T%s(); break;" % (t, t, t)) + cog.outl(" default: assert(false); break;") + cog.outl(" }") + cog.outl("#endif") cog.outl(" }") cog.outl("") cog.outl(" //********************************************") diff --git a/src/message_timer.h b/src/message_timer.h index f9b863f7..03a6a19c 100644 --- a/src/message_timer.h +++ b/src/message_timer.h @@ -596,6 +596,13 @@ namespace etl { } + //******************************************* + /// Destructor. + //******************************************* + ~imessage_timer() + { + } + private: //******************************************* diff --git a/test/codeblocks/ETL.layout b/test/codeblocks/ETL.layout index 5b77f6af..eac65713 100644 --- a/test/codeblocks/ETL.layout +++ b/test/codeblocks/ETL.layout @@ -2,514 +2,29 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - + @@ -517,59 +32,79 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + @@ -577,9 +112,474 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/etl_profile.h b/test/etl_profile.h index c4668ca7..ab9df17e 100644 --- a/test/etl_profile.h +++ b/test/etl_profile.h @@ -67,6 +67,9 @@ SOFTWARE. //#define ETL_POLYMORPHIC_CONTAINERS +//#define ETL_MESSAGES_ARE_VIRTUAL +//#define ETL_POLYMORPHIC_MESSAGES + #ifdef _MSC_VER #include "profiles/msvc_x86.h" #else From 7ce4fedf589985d0af51977e7d44b665403b9448 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 3 Feb 2018 21:09:22 +0000 Subject: [PATCH 26/50] Added emplace member functions to flat_map, flat_multimap, flat_set and flat_multiset --- src/flat_map.h | 188 ++++++++ src/flat_multimap.h | 106 ++++- src/flat_multiset.h | 92 +++- src/flat_set.h | 164 +++++++ test/codeblocks/ETL.layout | 918 ++++++++++++++++++------------------ test/test_flat_map.cpp | 305 +++++++++++- test/test_flat_multimap.cpp | 243 ++++++++++ test/test_flat_multiset.cpp | 239 ++++++++++ test/test_flat_set.cpp | 234 +++++++++ test/test_set.cpp | 43 ++ 10 files changed, 2052 insertions(+), 480 deletions(-) diff --git a/src/flat_map.h b/src/flat_map.h index 821e3baf..c257ec7d 100644 --- a/src/flat_map.h +++ b/src/flat_map.h @@ -336,6 +336,194 @@ namespace etl } } + //************************************************************************* + /// Emplaces a value to the map. + //************************************************************************* + std::pair emplace(const value_type& value) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_map_full)); + + // Create it. + value_type* pvalue = storage.allocate(); + ::new (pvalue) value_type(value); + + iterator i_element = lower_bound(value.first); + + std::pair result(i_element, false); + + // Doesn't already exist? + if ((i_element == end() || (i_element->first != value.first))) + { + ++construct_count; + result = refmap_t::insert_at(i_element, *pvalue); + } + else + { + pvalue->~value_type(); + storage.release(pvalue); + } + + return result; + } + + //************************************************************************* + /// Emplaces a value to the map. + //************************************************************************* + std::pair emplace(const key_type& key, const mapped_type& value) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_map_full)); + + // Create it. + value_type* pvalue = storage.allocate(); + ::new (pvalue) value_type(key, value); + + iterator i_element = lower_bound(key); + + std::pair result(i_element, false); + + // Doesn't already exist? + if ((i_element == end() || (i_element->first != key))) + { + ++construct_count; + result = refmap_t::insert_at(i_element, *pvalue); + } + else + { + pvalue->~value_type(); + storage.release(pvalue); + } + + return result; + } + + //************************************************************************* + /// Emplaces a value to the map. + //************************************************************************* + template + std::pair emplace(const key_type& key, const T1& value1) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_map_full)); + + // Create it. + value_type* pvalue = storage.allocate(); + ::new ((void*)etl::addressof(pvalue->first)) key_type(key); + ::new ((void*)etl::addressof(pvalue->second)) mapped_type(value1); + + iterator i_element = lower_bound(key); + + std::pair result(i_element, false); + + // Doesn't already exist? + if ((i_element == end() || (i_element->first != key))) + { + ++construct_count; + result = refmap_t::insert_at(i_element, *pvalue); + } + else + { + pvalue->~value_type(); + storage.release(pvalue); + } + + return result; + } + + //************************************************************************* + /// Emplaces a value to the map. + //************************************************************************* + template + std::pair emplace(const key_type& key, const T1& value1, const T2& value2) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_map_full)); + + // Create it. + value_type* pvalue = storage.allocate(); + ::new ((void*)etl::addressof(pvalue->first)) key_type(key); + ::new ((void*)etl::addressof(pvalue->second)) mapped_type(value1, value2); + + iterator i_element = lower_bound(key); + + std::pair result(i_element, false); + + // Doesn't already exist? + if ((i_element == end() || (i_element->first != key))) + { + ++construct_count; + result = refmap_t::insert_at(i_element, *pvalue); + } + else + { + pvalue->~value_type(); + storage.release(pvalue); + } + + return result; + } + + //************************************************************************* + /// Emplaces a value to the map. + //************************************************************************* + template + std::pair emplace(const key_type& key, const T1& value1, const T2& value2, const T3& value3) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_map_full)); + + // Create it. + value_type* pvalue = storage.allocate(); + ::new ((void*)etl::addressof(pvalue->first)) key_type(key); + ::new ((void*)etl::addressof(pvalue->second)) mapped_type(value1, value2, value3); + + iterator i_element = lower_bound(key); + + std::pair result(i_element, false); + + // Doesn't already exist? + if ((i_element == end() || (i_element->first != key))) + { + ++construct_count; + result = refmap_t::insert_at(i_element, *pvalue); + } + else + { + pvalue->~value_type(); + storage.release(pvalue); + } + + return result; + } + + //************************************************************************* + /// Emplaces a value to the map. + //************************************************************************* + template + std::pair emplace(const key_type& key, const T1& value1, const T2& value2, const T3& value3, const T4& value4) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_map_full)); + + // Create it. + value_type* pvalue = storage.allocate(); + ::new ((void*)etl::addressof(pvalue->first)) key_type(key); + ::new ((void*)etl::addressof(pvalue->second)) mapped_type(value1, value2, value3, value4); + + iterator i_element = lower_bound(key); + + std::pair result(i_element, false); + + // Doesn't already exist? + if ((i_element == end() || (i_element->first != key))) + { + ++construct_count; + result = refmap_t::insert_at(i_element, *pvalue); + } + else + { + pvalue->~value_type(); + storage.release(pvalue); + } + + return result; + } + //********************************************************************* /// Erases an element. ///\param key The key to erase. diff --git a/src/flat_multimap.h b/src/flat_multimap.h index 07f99def..b8fecd82 100644 --- a/src/flat_multimap.h +++ b/src/flat_multimap.h @@ -264,7 +264,7 @@ namespace etl //********************************************************************* /// Inserts a value to the flast_multi. - /// If asserts or exceptions are enabled, emits flat_map_full if the flat_map is already full. + /// If asserts or exceptions are enabled, emits flat_multimap_full if the flat_map is already full. ///\param position The position to insert at. ///\param value The value to insert. //********************************************************************* @@ -289,6 +289,110 @@ namespace etl } } + //************************************************************************* + /// Emplaces a value to the map. + //************************************************************************* + std::pair emplace(const value_type& value) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_multimap_full)); + + // Create it. + value_type* pvalue = storage.allocate(); + ::new (pvalue) value_type(value); + iterator i_element = lower_bound(value.first); + ++construct_count; + + return refmap_t::insert_at(i_element, *pvalue); + } + + //************************************************************************* + /// Emplaces a value to the map. + //************************************************************************* + std::pair emplace(const key_type& key, const mapped_type& value) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_multimap_full)); + + // Create it. + value_type* pvalue = storage.allocate(); + ::new (pvalue) value_type(key, value); + iterator i_element = lower_bound(key); + ++construct_count; + + return refmap_t::insert_at(i_element, *pvalue); + } + + //************************************************************************* + /// Emplaces a value to the map. + //************************************************************************* + template + std::pair emplace(const key_type& key, const T1& value1) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_multimap_full)); + + // Create it. + value_type* pvalue = storage.allocate(); + ::new ((void*)etl::addressof(pvalue->first)) key_type(key); + ::new ((void*)etl::addressof(pvalue->second)) mapped_type(value1); + iterator i_element = lower_bound(key); + ++construct_count; + + return refmap_t::insert_at(i_element, *pvalue); + } + + //************************************************************************* + /// Emplaces a value to the map. + //************************************************************************* + template + std::pair emplace(const key_type& key, const T1& value1, const T2& value2) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_multimap_full)); + + // Create it. + value_type* pvalue = storage.allocate(); + ::new ((void*)etl::addressof(pvalue->first)) key_type(key); + ::new ((void*)etl::addressof(pvalue->second)) mapped_type(value1, value2); + iterator i_element = lower_bound(key); + ++construct_count; + + return refmap_t::insert_at(i_element, *pvalue); + } + + //************************************************************************* + /// Emplaces a value to the map. + //************************************************************************* + template + std::pair emplace(const key_type& key, const T1& value1, const T2& value2, const T3& value3) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_multimap_full)); + + // Create it. + value_type* pvalue = storage.allocate(); + ::new ((void*)etl::addressof(pvalue->first)) key_type(key); + ::new ((void*)etl::addressof(pvalue->second)) mapped_type(value1, value2, value3); + iterator i_element = lower_bound(key); + ++construct_count; + + return refmap_t::insert_at(i_element, *pvalue); + } + + //************************************************************************* + /// Emplaces a value to the map. + //************************************************************************* + template + std::pair emplace(const key_type& key, const T1& value1, const T2& value2, const T3& value3, const T4& value4) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_multimap_full)); + + // Create it. + value_type* pvalue = storage.allocate(); + ::new ((void*)etl::addressof(pvalue->first)) key_type(key); + ::new ((void*)etl::addressof(pvalue->second)) mapped_type(value1, value2, value3, value4); + iterator i_element = lower_bound(key); + ++construct_count; + + return refmap_t::insert_at(i_element, *pvalue); + } + //********************************************************************* /// Erases an element. ///\param key The key to erase. diff --git a/src/flat_multiset.h b/src/flat_multiset.h index 6d4a05a3..63d44b02 100644 --- a/src/flat_multiset.h +++ b/src/flat_multiset.h @@ -230,8 +230,6 @@ namespace etl iterator i_element = std::lower_bound(begin(), end(), value, TKeyCompare()); - ETL_ASSERT(!full(), ETL_ERROR(flat_multiset_full)); - value_type* pvalue = storage.allocate(); ::new (pvalue) value_type(value); ++construct_count; @@ -267,6 +265,96 @@ namespace etl } } + //************************************************************************* + /// Emplaces a value to the set. + //************************************************************************* + template + std::pair emplace(parameter_t value) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_multiset_full)); + + // Create it. + value_type* pvalue = storage.allocate(); + ::new (pvalue) value_type(value); + + iterator i_element = lower_bound(*pvalue); + + ++construct_count; + return std::pair(refset_t::insert_at(i_element, *pvalue)); + } + + //************************************************************************* + /// Emplaces a value to the set. + //************************************************************************* + template + std::pair emplace(const T1& value1) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_multiset_full)); + + // Create it. + value_type* pvalue = storage.allocate(); + ::new (pvalue) value_type(value1); + + iterator i_element = lower_bound(*pvalue); + + ++construct_count; + return std::pair(refset_t::insert_at(i_element, *pvalue)); + } + + //************************************************************************* + /// Emplaces a value to the set. + //************************************************************************* + template + std::pair emplace(const T1& value1, const T2& value2) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_multiset_full)); + + // Create it. + value_type* pvalue = storage.allocate(); + ::new (pvalue) value_type(value1, value2); + + iterator i_element = lower_bound(*pvalue); + + ++construct_count; + return std::pair(refset_t::insert_at(i_element, *pvalue)); + } + + //************************************************************************* + /// Emplaces a value to the set. + //************************************************************************* + template + std::pair emplace(const T1& value1, const T2& value2, const T3& value3) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_multiset_full)); + + // Create it. + value_type* pvalue = storage.allocate(); + ::new (pvalue) value_type(value1, value2, value3); + + iterator i_element = lower_bound(*pvalue); + + ++construct_count; + return std::pair(refset_t::insert_at(i_element, *pvalue)); + } + + //************************************************************************* + /// Emplaces a value to the set. + //************************************************************************* + template + std::pair emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_multiset_full)); + + // Create it. + value_type* pvalue = storage.allocate(); + ::new (pvalue) value_type(value1, value2, value3, value4); + + iterator i_element = lower_bound(*pvalue); + + ++construct_count; + return std::pair(refset_t::insert_at(i_element, *pvalue)); + } + //********************************************************************* /// Erases an element. ///\param key The key to erase. diff --git a/src/flat_set.h b/src/flat_set.h index 0b5f17f0..29d16801 100644 --- a/src/flat_set.h +++ b/src/flat_set.h @@ -269,6 +269,170 @@ namespace etl } } + //************************************************************************* + /// Emplaces a value to the set. + //************************************************************************* + std::pair emplace(parameter_t value) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_set_full)); + + std::pair result; + + // Create it. + value_type* pvalue = storage.allocate(); + ::new (pvalue) value_type(value); + + iterator i_element = lower_bound(*pvalue); + + // Doesn't already exist? + if ((i_element == end() || (*i_element != *pvalue))) + { + ++construct_count; + result = refset_t::insert_at(i_element, *pvalue); + } + else + { + // Destroy it. + pvalue->~value_type(); + storage.release(pvalue); + result = std::pair(end(), false); + } + + return result; + } + + //************************************************************************* + /// Emplaces a value to the set. + //************************************************************************* + template + std::pair emplace(const T1& value1) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_set_full)); + + std::pair result; + + // Create it. + value_type* pvalue = storage.allocate(); + ::new (pvalue) value_type(value1); + + iterator i_element = lower_bound(*pvalue); + + // Doesn't already exist? + if ((i_element == end() || (*i_element != *pvalue))) + { + ++construct_count; + result = refset_t::insert_at(i_element, *pvalue); + } + else + { + // Destroy it. + pvalue->~value_type(); + storage.release(pvalue); + result = std::pair(end(), false); + } + + return result; + } + + //************************************************************************* + /// Emplaces a value to the set. + //************************************************************************* + template + std::pair emplace(const T1& value1, const T2& value2) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_set_full)); + + std::pair result; + + // Create it. + value_type* pvalue = storage.allocate(); + ::new (pvalue) value_type(value1, value2); + + iterator i_element = lower_bound(*pvalue); + + // Doesn't already exist? + if ((i_element == end() || (*i_element != *pvalue))) + { + ++construct_count; + result = refset_t::insert_at(i_element, *pvalue); + } + else + { + // Destroy it. + pvalue->~value_type(); + storage.release(pvalue); + result = std::pair(end(), false); + } + + return result; + } + + //************************************************************************* + /// Emplaces a value to the set. + //************************************************************************* + template + std::pair emplace(const T1& value1, const T2& value2, const T3& value3) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_set_full)); + + std::pair result; + + // Create it. + value_type* pvalue = storage.allocate(); + ::new (pvalue) value_type(value1, value2, value3); + + iterator i_element = lower_bound(*pvalue); + + // Doesn't already exist? + if ((i_element == end() || (*i_element != *pvalue))) + { + ++construct_count; + result = refset_t::insert_at(i_element, *pvalue); + } + else + { + // Destroy it. + pvalue->~value_type(); + storage.release(pvalue); + result = std::pair(end(), false); + } + + return result; + } + + //************************************************************************* + /// Emplaces a value to the set. + //************************************************************************* + template + std::pair emplace(const T1& value1, const T2& value2, const T3& value3, const T4& value4) + { + ETL_ASSERT(!full(), ETL_ERROR(flat_set_full)); + + std::pair result; + + // Create it. + value_type* pvalue = storage.allocate(); + ::new (pvalue) value_type(value1, value2, value3, value4); + + iterator i_element = lower_bound(*pvalue); + + // Doesn't already exist? + if ((i_element == end() || (*i_element != *pvalue))) + { + ++construct_count; + result = refset_t::insert_at(i_element, *pvalue); + } + else + { + // Destroy it. + pvalue->~value_type(); + storage.release(pvalue); + result = std::pair(end(), false); + } + + return result; + } + //********************************************************************* /// Erases an element. ///\param key The key to erase. diff --git a/test/codeblocks/ETL.layout b/test/codeblocks/ETL.layout index eac65713..7fb40ace 100644 --- a/test/codeblocks/ETL.layout +++ b/test/codeblocks/ETL.layout @@ -2,474 +2,69 @@ - + - + - + - + - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -477,14 +72,14 @@ - + - + - + - + @@ -492,19 +87,49 @@ - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -517,44 +142,64 @@ - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -567,19 +212,374 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/test_flat_map.cpp b/test/test_flat_map.cpp index cc09d1da..d00387e0 100644 --- a/test/test_flat_map.cpp +++ b/test/test_flat_map.cpp @@ -64,6 +64,113 @@ namespace typedef std::map Compare_DataDC; typedef std::map Compare_DataNDC; + struct D1 + { + D1(const std::string& a_) + : a(a_) + { + } + + std::string a; + }; + + struct D2 + { + D2(const std::string& a_, const std::string& b_) + : a(a_), + b(b_) + { + } + + std::string a; + std::string b; + }; + + struct D3 + { + D3(const std::string& a_, const std::string& b_, const std::string& c_) + : a(a_), + b(b_), + c(c_) + { + } + + std::string a; + std::string b; + std::string c; + }; + + struct D4 + { + D4(const std::string& a_, const std::string& b_, const std::string& c_, const std::string& d_) + : a(a_), + b(b_), + c(c_), + d(d_) + { + } + + std::string a; + std::string b; + std::string c; + std::string d; + }; + + bool operator == (const D1& lhs, const D1& rhs) + { + return (lhs.a == rhs.a); + } + + bool operator == (const D2& lhs, const D2& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b); + } + + bool operator == (const D3& lhs, const D3& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c); + } + + bool operator == (const D4& lhs, const D4& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c) && (lhs.d == rhs.d); + } + + bool operator != (const D1& lhs, const D1& rhs) + { + return !(lhs == rhs); + } + + bool operator != (const D2& lhs, const D2& rhs) + { + return !(lhs == rhs); + } + + bool operator != (const D3& lhs, const D3& rhs) + { + return !(lhs == rhs); + } + + bool operator != (const D4& lhs, const D4& rhs) + { + return !(lhs == rhs); + } + + typedef std::pair Element1; + typedef std::pair Element2; + typedef std::pair Element3; + typedef std::pair Element4; + + typedef etl::flat_map Data1; + typedef etl::flat_map Data2; + typedef etl::flat_map Data3; + typedef etl::flat_map Data4; + + typedef std::map Compare1; + typedef std::map Compare2; + typedef std::map Compare3; + typedef std::map Compare4; + //************************************************************************* template bool Check_Equal(T1 begin1, T1 end1, T2 begin2) @@ -165,24 +272,6 @@ namespace std::vector int_data; - //************************************************************************* - 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; - } - //************************************************************************* struct SetupFixture { @@ -606,6 +695,186 @@ namespace CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::flat_map_full); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_value1) + { + Compare1 compare; + Data1 data; + + std::pair result; + + result = data.emplace(0, "0"); + compare.emplace(0, D1("0")); + + bool isEqual = Check_Equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + CHECK(result.second); + CHECK(*result.first == Element1(0, D1("0"))); + + result = data.emplace(std::make_pair(2, D1("2"))); + compare.emplace(std::make_pair(2, D1("2"))); + + isEqual = Check_Equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + CHECK(result.second); + CHECK(*result.first == Element1(2, D1("2"))); + + result = data.emplace(1, "1"); + compare.emplace(1, D1("1")); + + isEqual = Check_Equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + CHECK(result.second); + CHECK(*result.first == Element1(1, D1("1"))); + + result = data.emplace(1, D1("1")); + CHECK(!result.second); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_value2) + { + Compare2 compare; + Data2 data; + + std::pair result; + + result = data.emplace(0, "0", "1"); + compare.emplace(0, D2("0", "1")); + + bool isEqual = Check_Equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + CHECK(result.second); + CHECK(*result.first == Element2(0, D2("0", "1"))); + + result = data.emplace(std::make_pair(2, D2("2", "3"))); + compare.emplace(std::make_pair(2, D2("2", "3"))); + + isEqual = Check_Equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + CHECK(result.second); + CHECK(*result.first == Element2(2, D2("2", "3"))); + + result = data.emplace(1, D2("1", "2")); + compare.emplace(1, D2("1", "2")); + + isEqual = Check_Equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + CHECK(result.second); + CHECK(*result.first == Element2(1, D2("1", "2"))); + + result = data.emplace(1, D2("1", "2")); + CHECK(!result.second); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_value3) + { + Compare3 compare; + Data3 data; + + std::pair result; + + result = data.emplace(0, "0", "1", "2"); + compare.emplace(0, D3("0", "1", "2")); + + bool isEqual = Check_Equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + CHECK(result.second); + CHECK(*result.first == Element3(0, D3("0", "1", "2"))); + + result = data.emplace(std::make_pair(2, D3("2", "3", "4"))); + compare.emplace(std::make_pair(2, D3("2", "3", "4"))); + + isEqual = Check_Equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + CHECK(result.second); + CHECK(*result.first == Element3(2, D3("2", "3", "4"))); + + result = data.emplace(1, D3("1", "2", "3")); + compare.emplace(1, D3("1", "2", "3")); + + isEqual = Check_Equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + CHECK(result.second); + CHECK(*result.first == Element3(1, D3("1", "2", "3"))); + + result = data.emplace(1, D3("1", "2", "3")); + CHECK(!result.second); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_value4) + { + Compare4 compare; + Data4 data; + + std::pair result; + + result = data.emplace(0, "0", "1", "2", "3"); + compare.emplace(0, D4("0", "1", "2", "3")); + + bool isEqual = Check_Equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + CHECK(result.second); + CHECK(*result.first == Element4(0, D4("0", "1", "2", "3"))); + + result = data.emplace(std::make_pair(2, D4("2", "3", "4", "5"))); + compare.emplace(std::make_pair(2, D4("2", "3", "4", "5"))); + + isEqual = Check_Equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + CHECK(result.second); + CHECK(*result.first == Element4(2, D4("2", "3", "4", "5"))); + + result = data.emplace(1, D4("1", "2", "3", "4")); + compare.emplace(1, D4("1", "2", "3", "4")); + + isEqual = Check_Equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + CHECK(result.second); + CHECK(*result.first == Element4(1, D4("1", "2", "3", "4"))); + + result = data.emplace(1, D4("1", "2", "3", "4")); + CHECK(!result.second); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_key) { diff --git a/test/test_flat_multimap.cpp b/test/test_flat_multimap.cpp index 59c3a32d..afec18e1 100644 --- a/test/test_flat_multimap.cpp +++ b/test/test_flat_multimap.cpp @@ -90,6 +90,113 @@ namespace std::vector int_data; + struct D1 + { + D1(const std::string& a_) + : a(a_) + { + } + + std::string a; + }; + + struct D2 + { + D2(const std::string& a_, const std::string& b_) + : a(a_), + b(b_) + { + } + + std::string a; + std::string b; + }; + + struct D3 + { + D3(const std::string& a_, const std::string& b_, const std::string& c_) + : a(a_), + b(b_), + c(c_) + { + } + + std::string a; + std::string b; + std::string c; + }; + + struct D4 + { + D4(const std::string& a_, const std::string& b_, const std::string& c_, const std::string& d_) + : a(a_), + b(b_), + c(c_), + d(d_) + { + } + + std::string a; + std::string b; + std::string c; + std::string d; + }; + + bool operator == (const D1& lhs, const D1& rhs) + { + return (lhs.a == rhs.a); + } + + bool operator == (const D2& lhs, const D2& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b); + } + + bool operator == (const D3& lhs, const D3& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c); + } + + bool operator == (const D4& lhs, const D4& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c) && (lhs.d == rhs.d); + } + + bool operator != (const D1& lhs, const D1& rhs) + { + return !(lhs == rhs); + } + + bool operator != (const D2& lhs, const D2& rhs) + { + return !(lhs == rhs); + } + + bool operator != (const D3& lhs, const D3& rhs) + { + return !(lhs == rhs); + } + + bool operator != (const D4& lhs, const D4& rhs) + { + return !(lhs == rhs); + } + + typedef std::pair Element1; + typedef std::pair Element2; + typedef std::pair Element3; + typedef std::pair Element4; + + typedef etl::flat_multimap Data1; + typedef etl::flat_multimap Data2; + typedef etl::flat_multimap Data3; + typedef etl::flat_multimap Data4; + + typedef std::multimap Compare1; + typedef std::multimap Compare2; + typedef std::multimap Compare3; + typedef std::multimap Compare4; + //************************************************************************* template bool Check_Equal(T1 begin1, T1 end1, T2 begin2) @@ -436,6 +543,142 @@ namespace CHECK(std::is_sorted(data.begin(), data.end())); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_value1) + { + Compare1 compare; + Data1 data; + + data.emplace(0, "0"); + compare.emplace(0, D1("0")); + + data.emplace(1, D1("1")); + compare.emplace(1, D1("1")); + + data.emplace(std::make_pair(2, D1("2"))); + compare.emplace(std::make_pair(2, D1("2"))); + + // Do it again. + data.emplace(0, "0"); + compare.emplace(0, D1("0")); + + data.emplace(1, D1("1")); + compare.emplace(1, D1("1")); + + data.emplace(std::make_pair(2, D1("2"))); + compare.emplace(std::make_pair(2, D1("2"))); + + CHECK_EQUAL(compare.size(), data.size()); + + bool isEqual = Check_Equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_value2) + { + Compare2 compare; + Data2 data; + + data.emplace(0, "0", "1"); + compare.emplace(0, D2("0", "1")); + + data.emplace(1, D2("1", "2")); + compare.emplace(1, D2("1", "2")); + + data.emplace(std::make_pair(2, D2("2", "3"))); + compare.emplace(std::make_pair(2, D2("2", "3"))); + + // Do it again. + data.emplace(0, "0", "1"); + compare.emplace(0, D2("0", "1")); + + data.emplace(1, D2("1", "2")); + compare.emplace(1, D2("1", "2")); + + data.emplace(std::make_pair(2, D2("2", "3"))); + compare.emplace(std::make_pair(2, D2("2", "3"))); + + CHECK_EQUAL(compare.size(), data.size()); + + bool isEqual = Check_Equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_value3) + { + Compare3 compare; + Data3 data; + + data.emplace(0, "0", "1", "2"); + compare.emplace(0, D3("0", "1", "2")); + + data.emplace(1, D3("1", "2", "3")); + compare.emplace(1, D3("1", "2", "3")); + + data.emplace(std::make_pair(2, D3("2", "3", "4"))); + compare.emplace(std::make_pair(2, D3("2", "3", "4"))); + + // Do it again. + data.emplace(0, "0", "1", "2"); + compare.emplace(0, D3("0", "1", "2")); + + data.emplace(1, D3("1", "2", "3")); + compare.emplace(1, D3("1", "2", "3")); + + data.emplace(std::make_pair(2, D3("2", "3", "4"))); + compare.emplace(std::make_pair(2, D3("2", "3", "4"))); + + CHECK_EQUAL(compare.size(), data.size()); + + bool isEqual = Check_Equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_value4) + { + Compare4 compare; + Data4 data; + + data.emplace(0, "0", "1", "2", "3"); + compare.emplace(0, D4("0", "1", "2", "3")); + + data.emplace(1, D4("1", "2", "3", "4")); + compare.emplace(1, D4("1", "2", "3", "4")); + + data.emplace(std::make_pair(2, D4("2", "3", "4", "5"))); + compare.emplace(std::make_pair(2, D4("2", "3", "4", "5"))); + + // Do it again. + data.emplace(0, "0", "1", "2", "3"); + compare.emplace(0, D4("0", "1", "2", "3")); + + data.emplace(1, D4("1", "2", "3", "4")); + compare.emplace(1, D4("1", "2", "3", "4")); + + data.emplace(std::make_pair(2, D4("2", "3", "4", "5"))); + compare.emplace(std::make_pair(2, D4("2", "3", "4", "5"))); + + CHECK_EQUAL(compare.size(), data.size()); + + bool isEqual = Check_Equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_key) { diff --git a/test/test_flat_multiset.cpp b/test/test_flat_multiset.cpp index fb775560..447de187 100644 --- a/test/test_flat_multiset.cpp +++ b/test/test_flat_multiset.cpp @@ -56,6 +56,109 @@ namespace typedef std::multiset Compare_DataDC; typedef std::multiset Compare_DataNDC; + struct D1 + { + D1(const std::string& a_) + : a(a_) + { + } + + std::string a; + }; + + struct D2 + { + D2(const std::string& a_, const std::string& b_) + : a(a_), + b(b_) + { + } + + std::string a; + std::string b; + }; + + struct D3 + { + D3(const std::string& a_, const std::string& b_, const std::string& c_) + : a(a_), + b(b_), + c(c_) + { + } + + std::string a; + std::string b; + std::string c; + }; + + struct D4 + { + D4(const std::string& a_, const std::string& b_, const std::string& c_, const std::string& d_) + : a(a_), + b(b_), + c(c_), + d(d_) + { + } + + std::string a; + std::string b; + std::string c; + std::string d; + }; + + bool operator == (const D1& lhs, const D1& rhs) + { + return (lhs.a == rhs.a); + } + + bool operator == (const D2& lhs, const D2& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b); + } + + bool operator == (const D3& lhs, const D3& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c); + } + + bool operator == (const D4& lhs, const D4& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c) && (lhs.d == rhs.d); + } + + bool operator < (const D1& lhs, const D1& rhs) + { + return (lhs.a < rhs.a); + } + + bool operator < (const D2& lhs, const D2& rhs) + { + return (lhs.a < rhs.a) && (lhs.b < rhs.b); + } + + bool operator < (const D3& lhs, const D3& rhs) + { + return (lhs.a < rhs.a) && (lhs.b < rhs.b) && (lhs.c < rhs.c); + } + + bool operator < (const D4& lhs, const D4& rhs) + { + return (lhs.a < rhs.a) && (lhs.b < rhs.b) && (lhs.c < rhs.c) && (lhs.d < rhs.d); + } + + typedef etl::flat_multiset Data1; + typedef etl::flat_multiset Data2; + typedef etl::flat_multiset Data3; + typedef etl::flat_multiset Data4; + + typedef std::multiset Compare1; + typedef std::multiset Compare2; + typedef std::multiset Compare3; + typedef std::multiset Compare4; + + //************************************************************************* std::ostream& operator <<(std::ostream& os, DataNDC::iterator itr) { @@ -393,6 +496,142 @@ namespace CHECK(std::is_sorted(data.begin(), data.end())); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_value1) + { + Compare1 compare; + Data1 data; + + data.emplace("0"); + compare.emplace("0"); + + data.emplace("1"); + compare.emplace("1"); + + data.emplace("2"); + compare.emplace("2"); + + // Do it again. + data.emplace("0"); + compare.emplace("0"); + + data.emplace("1"); + compare.emplace("1"); + + data.emplace("2"); + compare.emplace("2"); + + CHECK_EQUAL(compare.size(), data.size()); + + bool isEqual = std::equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_value2) + { + Compare2 compare; + Data2 data; + + data.emplace("0", "1"); + compare.emplace("0", "1"); + + data.emplace("1", "2"); + compare.emplace("1", "2"); + + data.emplace("2", "3"); + compare.emplace("2", "3"); + + // Do it again. + data.emplace("0", "1"); + compare.emplace("0", "1"); + + data.emplace("1", "2"); + compare.emplace("1", "2"); + + data.emplace("2", "3"); + compare.emplace("2", "3"); + + CHECK_EQUAL(compare.size(), data.size()); + + bool isEqual = std::equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_value3) + { + Compare3 compare; + Data3 data; + + data.emplace("0", "1", "2"); + compare.emplace("0", "1", "2"); + + data.emplace("1", "2", "3"); + compare.emplace("1", "2", "3"); + + data.emplace("2", "3", "4"); + compare.emplace("2", "3", "4"); + + // Do it again. + data.emplace("0", "1", "2"); + compare.emplace("0", "1", "2"); + + data.emplace("1", "2", "3"); + compare.emplace("1", "2", "3"); + + data.emplace("2", "3", "4"); + compare.emplace("2", "3", "4"); + + CHECK_EQUAL(compare.size(), data.size()); + + bool isEqual = std::equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_value4) + { + Compare4 compare; + Data4 data; + + data.emplace("0", "1", "2", "3"); + compare.emplace("0", "1", "2", "3"); + + data.emplace("1", "2", "3", "4"); + compare.emplace("1", "2", "3", "4"); + + data.emplace("2", "3", "4", "5"); + compare.emplace("2", "3", "4", "5"); + + // Do it again. + data.emplace("0", "1", "2", "3"); + compare.emplace("0", "1", "2", "3"); + + data.emplace("1", "2", "3", "4"); + compare.emplace("1", "2", "3", "4"); + + data.emplace("2", "3", "4", "5"); + compare.emplace("2", "3", "4", "5"); + + CHECK_EQUAL(compare.size(), data.size()); + + bool isEqual = std::equal(data.begin(), + data.end(), + compare.begin()); + + CHECK(isEqual); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_key) { diff --git a/test/test_flat_set.cpp b/test/test_flat_set.cpp index 25ff5cc7..9bcbc73a 100644 --- a/test/test_flat_set.cpp +++ b/test/test_flat_set.cpp @@ -104,6 +104,128 @@ namespace std::vector int_data; + struct D1 + { + D1(const std::string& a_) + : a(a_) + { + } + + std::string a; + }; + + struct D2 + { + D2(const std::string& a_, const std::string& b_) + : a(a_), + b(b_) + { + } + + std::string a; + std::string b; + }; + + struct D3 + { + D3(const std::string& a_, const std::string& b_, const std::string& c_) + : a(a_), + b(b_), + c(c_) + { + } + + std::string a; + std::string b; + std::string c; + }; + + struct D4 + { + D4(const std::string& a_, const std::string& b_, const std::string& c_, const std::string& d_) + : a(a_), + b(b_), + c(c_), + d(d_) + { + } + + std::string a; + std::string b; + std::string c; + std::string d; + }; + + bool operator == (const D1& lhs, const D1& rhs) + { + return (lhs.a == rhs.a); + } + + bool operator == (const D2& lhs, const D2& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b); + } + + bool operator == (const D3& lhs, const D3& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c); + } + + bool operator == (const D4& lhs, const D4& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c) && (lhs.d == rhs.d); + } + + bool operator != (const D1& lhs, const D1& rhs) + { + return !(lhs == rhs); + } + + bool operator != (const D2& lhs, const D2& rhs) + { + return !(lhs == rhs); + } + + bool operator != (const D3& lhs, const D3& rhs) + { + return !(lhs == rhs); + } + + bool operator != (const D4& lhs, const D4& rhs) + { + return !(lhs == rhs); + } + + bool operator < (const D1& lhs, const D1& rhs) + { + return (lhs.a < rhs.a); + } + + bool operator < (const D2& lhs, const D2& rhs) + { + return (lhs.a < rhs.a) && (lhs.b < rhs.b); + } + + bool operator < (const D3& lhs, const D3& rhs) + { + return (lhs.a < rhs.a) && (lhs.b < rhs.b) && (lhs.c < rhs.c); + } + + bool operator < (const D4& lhs, const D4& rhs) + { + return (lhs.a < rhs.a) && (lhs.b < rhs.b) && (lhs.c < rhs.c) && (lhs.d < rhs.d); + } + + typedef etl::flat_set Data1; + typedef etl::flat_set Data2; + typedef etl::flat_set Data3; + typedef etl::flat_set Data4; + + typedef std::set Compare1; + typedef std::set Compare2; + typedef std::set Compare3; + typedef std::set Compare4; + //************************************************************************* struct SetupFixture { @@ -382,6 +504,118 @@ namespace CHECK(std::is_sorted(data.begin(), data.end())); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_value1) + { + Compare1 compare; + Data1 data; + + data.emplace("0"); + compare.emplace("0"); + + data.emplace("1"); + compare.emplace("1"); + + data.emplace("2"); + compare.emplace("2"); + + // Do it again. + data.emplace("0"); + compare.emplace("0"); + + data.emplace("1"); + compare.emplace("1"); + + data.emplace("2"); + compare.emplace("2"); + + CHECK_EQUAL(compare.size(), data.size()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_value2) + { + Compare2 compare; + Data2 data; + + data.emplace("0", "1"); + compare.emplace("0", "1"); + + data.emplace("1", "2"); + compare.emplace("1", "2"); + + data.emplace("2", "3"); + compare.emplace("2", "3"); + + // Do it again. + data.emplace("0", "1"); + compare.emplace("0", "1"); + + data.emplace("1", "2"); + compare.emplace("1", "2"); + + data.emplace("2", "3"); + compare.emplace("2", "3"); + + CHECK_EQUAL(compare.size(), data.size()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_value3) + { + Compare3 compare; + Data3 data; + + data.emplace("0", "1", "2"); + compare.emplace("0", "1", "2"); + + data.emplace("1", "2", "3"); + compare.emplace("1", "2", "3"); + + data.emplace("2", "3", "4"); + compare.emplace("2", "3", "4"); + + // Do it again. + data.emplace("0", "1", "2"); + compare.emplace("0", "1", "2"); + + data.emplace("1", "2", "3"); + compare.emplace("1", "2", "3"); + + data.emplace("2", "3", "4"); + compare.emplace("2", "3", "4"); + + CHECK_EQUAL(compare.size(), data.size()); + } + + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_value4) + { + Compare4 compare; + Data4 data; + + data.emplace("0", "1", "2", "3"); + compare.emplace("0", "1", "2", "3"); + + data.emplace("1", "2", "3", "4"); + compare.emplace("1", "2", "3", "4"); + + data.emplace("2", "3", "4", "5"); + compare.emplace("2", "3", "4", "5"); + + // Do it again. + data.emplace("0", "1", "2", "3"); + compare.emplace("0", "1", "2", "3"); + + data.emplace("1", "2", "3", "4"); + compare.emplace("1", "2", "3", "4"); + + data.emplace("2", "3", "4", "5"); + compare.emplace("2", "3", "4", "5"); + + CHECK_EQUAL(compare.size(), data.size()); + } + //************************************************************************* TEST_FIXTURE(SetupFixture, test_erase_key) { diff --git a/test/test_set.cpp b/test/test_set.cpp index 06b5607a..98422f6f 100644 --- a/test/test_set.cpp +++ b/test/test_set.cpp @@ -461,6 +461,49 @@ namespace CHECK_THROW(data.insert(excess_data.begin(), excess_data.end()), etl::set_full); } + //************************************************************************* + TEST_FIXTURE(SetupFixture, test_emplace_value) + { + //Compare_Data compare_data; + //Data data; + + //std::pair data_result = data.emplace(0); + //std::pair compare_result = compare_data.emplace(0); + + //// Check that both return successful return results + //CHECK_EQUAL(*data_result.first, *compare_result.first); + + //// Try adding a duplicate (should return iterator pointing to duplicate) + //data_result = data.insert(0); + //compare_result = compare_data.insert(0); + + //// Check that both return successful return results + //CHECK_EQUAL(*data_result.first, *compare_result.first); + + //// Check that elements in set are the same + //bool isEqual = Check_Equal(data.begin(), + // data.end(), + // compare_data.begin()); + //CHECK(isEqual); + + //data.insert(2); + //compare_data.insert(2); + + //isEqual = Check_Equal(data.begin(), + // data.end(), + // compare_data.begin()); + + //CHECK(isEqual); + + //data.insert(1); + //compare_data.insert(1); + + //isEqual = Check_Equal(data.begin(), + // data.end(), + // compare_data.begin()); + + //CHECK(isEqual); + } //************************************************************************* TEST_FIXTURE(SetupFixture, test_equal_range) From c43adc7df31ee45d7553bc6aefbb0fb1e978304c Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 4 Feb 2018 14:52:31 +0000 Subject: [PATCH 27/50] Improved performance of emplace for value_type parameters --- library.properties | 2 +- src/flat_map.h | 27 +++------------------------ src/flat_multimap.h | 13 +++---------- src/flat_multiset.h | 11 +---------- src/flat_set.h | 26 +------------------------- support/Release notes.txt | 4 ++++ 6 files changed, 13 insertions(+), 70 deletions(-) diff --git a/library.properties b/library.properties index 69ddf058..b2176433 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=10.16.0 +version=10.16.1 author= John Wellbelove maintainer=John Wellbelove sentence=A C++ template library tailored for embedded systems. diff --git a/src/flat_map.h b/src/flat_map.h index c257ec7d..e9b799cd 100644 --- a/src/flat_map.h +++ b/src/flat_map.h @@ -341,29 +341,7 @@ namespace etl //************************************************************************* std::pair emplace(const value_type& value) { - ETL_ASSERT(!full(), ETL_ERROR(flat_map_full)); - - // Create it. - value_type* pvalue = storage.allocate(); - ::new (pvalue) value_type(value); - - iterator i_element = lower_bound(value.first); - - std::pair result(i_element, false); - - // Doesn't already exist? - if ((i_element == end() || (i_element->first != value.first))) - { - ++construct_count; - result = refmap_t::insert_at(i_element, *pvalue); - } - else - { - pvalue->~value_type(); - storage.release(pvalue); - } - - return result; + return insert(value); } //************************************************************************* @@ -375,7 +353,8 @@ namespace etl // Create it. value_type* pvalue = storage.allocate(); - ::new (pvalue) value_type(key, value); + ::new ((void*)etl::addressof(pvalue->first)) key_type(key); + ::new ((void*)etl::addressof(pvalue->second)) mapped_type(value); iterator i_element = lower_bound(key); diff --git a/src/flat_multimap.h b/src/flat_multimap.h index b8fecd82..4ef7901e 100644 --- a/src/flat_multimap.h +++ b/src/flat_multimap.h @@ -294,15 +294,7 @@ namespace etl //************************************************************************* std::pair emplace(const value_type& value) { - ETL_ASSERT(!full(), ETL_ERROR(flat_multimap_full)); - - // Create it. - value_type* pvalue = storage.allocate(); - ::new (pvalue) value_type(value); - iterator i_element = lower_bound(value.first); - ++construct_count; - - return refmap_t::insert_at(i_element, *pvalue); + return insert(value); } //************************************************************************* @@ -314,7 +306,8 @@ namespace etl // Create it. value_type* pvalue = storage.allocate(); - ::new (pvalue) value_type(key, value); + ::new ((void*)etl::addressof(pvalue->first)) key_type(key); + ::new ((void*)etl::addressof(pvalue->second)) mapped_type(value); iterator i_element = lower_bound(key); ++construct_count; diff --git a/src/flat_multiset.h b/src/flat_multiset.h index 63d44b02..2ec645a1 100644 --- a/src/flat_multiset.h +++ b/src/flat_multiset.h @@ -271,16 +271,7 @@ namespace etl template std::pair emplace(parameter_t value) { - ETL_ASSERT(!full(), ETL_ERROR(flat_multiset_full)); - - // Create it. - value_type* pvalue = storage.allocate(); - ::new (pvalue) value_type(value); - - iterator i_element = lower_bound(*pvalue); - - ++construct_count; - return std::pair(refset_t::insert_at(i_element, *pvalue)); + return insert(value); } //************************************************************************* diff --git a/src/flat_set.h b/src/flat_set.h index 29d16801..49e8b12f 100644 --- a/src/flat_set.h +++ b/src/flat_set.h @@ -274,31 +274,7 @@ namespace etl //************************************************************************* std::pair emplace(parameter_t value) { - ETL_ASSERT(!full(), ETL_ERROR(flat_set_full)); - - std::pair result; - - // Create it. - value_type* pvalue = storage.allocate(); - ::new (pvalue) value_type(value); - - iterator i_element = lower_bound(*pvalue); - - // Doesn't already exist? - if ((i_element == end() || (*i_element != *pvalue))) - { - ++construct_count; - result = refset_t::insert_at(i_element, *pvalue); - } - else - { - // Destroy it. - pvalue->~value_type(); - storage.release(pvalue); - result = std::pair(end(), false); - } - - return result; + return insert(value); } //************************************************************************* diff --git a/support/Release notes.txt b/support/Release notes.txt index f1f865aa..5e1cd96c 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,7 @@ +=============================================================================== +10.16.1 +Improved performance of emplace for value_type parameters. + =============================================================================== 10.16.0 Added emplace member functions to flat_map, flat_multimap, flat_set and flat_multiset From 1dd1ffc4e4df5213af71bb30db4ec2fce849618b Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 4 Feb 2018 17:34:51 +0000 Subject: [PATCH 28/50] Added emplace functions to etl::variant --- library.properties | 2 +- src/variant.h | 108 +++++++++++++++++++++++++--- support/Release notes.txt | 4 ++ test/test_variant.cpp | 145 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 248 insertions(+), 11 deletions(-) diff --git a/library.properties b/library.properties index b2176433..b0890a1f 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=10.16.1 +version=10.17.0 author= John Wellbelove maintainer=John Wellbelove sentence=A C++ template library tailored for embedded systems. diff --git a/src/variant.h b/src/variant.h index 4bf3d5b9..61d8c892 100644 --- a/src/variant.h +++ b/src/variant.h @@ -112,6 +112,18 @@ namespace etl typename T8 = __private_variant__::no_type<8> > class variant { + public: + + //*************************************************************************** + /// The type used for ids. + //*************************************************************************** + typedef uint_least8_t type_id_t; + + //*************************************************************************** + /// The id a unsupported types. + //*************************************************************************** + static const type_id_t UNSUPPORTED_TYPE_ID = integral_limits::max; + private: // All types of variant are friends. @@ -133,16 +145,6 @@ namespace etl //*************************************************************************** static const size_t ALIGNMENT = etl::largest_alignment::value; - //*************************************************************************** - /// The type used for ids. - //*************************************************************************** - typedef uint_least8_t type_id_t; - - //*************************************************************************** - /// The id a unsupported types. - //*************************************************************************** - static const type_id_t UNSUPPORTED_TYPE_ID = integral_limits::max; - //*************************************************************************** /// Short form of no_type placeholders. //*************************************************************************** @@ -701,6 +703,84 @@ namespace etl type_id = other.type_id; } +#if !ETL_CPP11_SUPPORTED + //*************************************************************************** + /// Emplace with one constructor parameter. + //*************************************************************************** + template + T& emplace(const TP1& value1) + { + STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + + destruct_current(); + ::new (static_cast(data)) T(value1); + type_id = Type_Id_Lookup::type_id; + + return *static_cast(data); + } + + //*************************************************************************** + /// Emplace with two constructor parameters. + //*************************************************************************** + template + T& emplace(const TP1& value1, const TP2& value2) + { + STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + + destruct_current(); + ::new (static_cast(data)) T(value1, value2); + type_id = Type_Id_Lookup::type_id; + + return *static_cast(data); + } + + //*************************************************************************** + /// Emplace with three constructor parameters. + //*************************************************************************** + template + T& emplace(const TP1& value1, const TP2& value2, const TP3& value3) + { + STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + + destruct_current(); + ::new (static_cast(data)) T(value1, value2, value3); + type_id = Type_Id_Lookup::type_id; + + return *static_cast(data); + } + + //*************************************************************************** + /// Emplace with four constructor parameters. + //*************************************************************************** + template + T& emplace(const TP1& value1, const TP2& value2, const TP3& value3, const TP4& value4) + { + STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + + destruct_current(); + ::new (static_cast(data)) T(value1, value2, value3, value4); + type_id = Type_Id_Lookup::type_id; + + return *static_cast(data); + } + +#else + //************************************************************************* + /// Emplace with variadic constructor parameters. + //************************************************************************* + template + T& emplace(Args&&... args) + { + STATIC_ASSERT(Type_Is_Supported::value, "Unsupported type"); + + destruct_current(); + ::new (static_cast(data)) T(std::forward(args)...); + type_id = Type_Id_Lookup::type_id; + + return *static_cast(data); + } +#endif + //*************************************************************************** /// Assignment operator for T1 type. ///\param value The value to assign. @@ -821,6 +901,14 @@ namespace etl return type_id == Type_Id_Lookup::type_id; } + //*************************************************************************** + /// Gets the index of the type currently stored or UNSUPPORTED_TYPE_ID + //*************************************************************************** + ETL_CONSTEXPR size_t index() const + { + return type_id; + } + //*************************************************************************** /// Clears the value to 'no valid stored value'. //*************************************************************************** diff --git a/support/Release notes.txt b/support/Release notes.txt index 5e1cd96c..a02a8180 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,7 @@ +=============================================================================== +10.17.0 +Added emplace functions to etl::variant. + =============================================================================== 10.16.1 Improved performance of emplace for value_type parameters. diff --git a/test/test_variant.cpp b/test/test_variant.cpp index 5b3324e9..353a3c5b 100644 --- a/test/test_variant.cpp +++ b/test/test_variant.cpp @@ -34,6 +34,7 @@ SOFTWARE. #include #include #include +#include namespace { @@ -99,6 +100,128 @@ namespace // This line should compile with no errors. test_variant_max_types variant_max; + struct D1 + { + D1(const std::string& a_) + : a(a_) + { + } + + std::string a; + }; + + struct D2 + { + D2(const std::string& a_, const std::string& b_) + : a(a_), + b(b_) + { + } + + std::string a; + std::string b; + }; + + struct D3 + { + D3(const std::string& a_, const std::string& b_, const std::string& c_) + : a(a_), + b(b_), + c(c_) + { + } + + std::string a; + std::string b; + std::string c; + }; + + struct D4 + { + D4(const std::string& a_, const std::string& b_, const std::string& c_, const std::string& d_) + : a(a_), + b(b_), + c(c_), + d(d_) + { + } + + std::string a; + std::string b; + std::string c; + std::string d; + }; + + bool operator == (const D1& lhs, const D1& rhs) + { + return (lhs.a == rhs.a); + } + + bool operator == (const D2& lhs, const D2& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b); + } + + bool operator == (const D3& lhs, const D3& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c); + } + + bool operator == (const D4& lhs, const D4& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c) && (lhs.d == rhs.d); + } + + bool operator != (const D1& lhs, const D1& rhs) + { + return !(lhs == rhs); + } + + bool operator != (const D2& lhs, const D2& rhs) + { + return !(lhs == rhs); + } + + bool operator != (const D3& lhs, const D3& rhs) + { + return !(lhs == rhs); + } + + bool operator != (const D4& lhs, const D4& rhs) + { + return !(lhs == rhs); + } + + std::ostream& operator <<(std::ostream& os, const D1& d1) + { + os << d1.a; + + return os; + } + + std::ostream& operator <<(std::ostream& os, const D2& d2) + { + os << d2.a << " " << d2.b; + + return os; + } + + std::ostream& operator <<(std::ostream& os, const D3& d3) + { + os << d3.a << " " << d3.b << " " << d3.c; + + return os; + } + + std::ostream& operator <<(std::ostream& os, const D4& d4) + { + os << d4.a << " " << d4.b << " " << d4.c << " " << d4.d; + + return os; + } + + typedef etl::variant test_variant_emplace; + SUITE(test_variant) { TEST(test_alignment) @@ -666,5 +789,27 @@ namespace variant.upcast().set(); CHECK_EQUAL(2, variant.get().value); } + + //************************************************************************* + TEST(TestEmplace) + { + test_variant_emplace variant; + + variant.emplace("1"); + CHECK(variant.is_type()); + CHECK_EQUAL(D1("1"), variant.get()); + + variant.emplace("1", "2"); + CHECK(variant.is_type()); + CHECK_EQUAL(D2("1", "2"), variant.get()); + + variant.emplace("1", "2", "3"); + CHECK(variant.is_type()); + CHECK_EQUAL(D3("1", "2", "3"), variant.get()); + + variant.emplace("1", "2", "3", "4"); + CHECK(variant.is_type()); + CHECK_EQUAL(D4("1", "2", "3", "4"), variant.get()); + } }; } From 4b1eeee511f0ae655ce801771b855e77628faf81 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 4 Feb 2018 17:42:34 +0000 Subject: [PATCH 29/50] Added emplace functions to etl::variant --- test/test_variant.cpp | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/test/test_variant.cpp b/test/test_variant.cpp index 353a3c5b..07a96cdb 100644 --- a/test/test_variant.cpp +++ b/test/test_variant.cpp @@ -172,26 +172,6 @@ namespace return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c) && (lhs.d == rhs.d); } - bool operator != (const D1& lhs, const D1& rhs) - { - return !(lhs == rhs); - } - - bool operator != (const D2& lhs, const D2& rhs) - { - return !(lhs == rhs); - } - - bool operator != (const D3& lhs, const D3& rhs) - { - return !(lhs == rhs); - } - - bool operator != (const D4& lhs, const D4& rhs) - { - return !(lhs == rhs); - } - std::ostream& operator <<(std::ostream& os, const D1& d1) { os << d1.a; @@ -802,7 +782,7 @@ namespace variant.emplace("1", "2"); CHECK(variant.is_type()); CHECK_EQUAL(D2("1", "2"), variant.get()); - + variant.emplace("1", "2", "3"); CHECK(variant.is_type()); CHECK_EQUAL(D3("1", "2", "3"), variant.get()); From 879fb1f6265271bfd31ab1a906b8a33a42eab30b Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 5 Feb 2018 21:16:43 +0000 Subject: [PATCH 30/50] Improvements to message and callback timer frameworks. Reduced disable/enable time dur function calls. Added the option to use either atomic semaphores or interrupt enables to control access. --- library.properties | 2 +- src/c/ecl_timer.c | 28 +- src/callback_timer.h | 78 ++- src/message_timer.h | 75 ++- support/Release notes.txt | 6 + test/codeblocks/ETL.layout | 1051 +++++++++++++++---------------- test/ecl_user.h | 16 +- test/etl_profile.h | 3 + test/test_c_timer_framework.cpp | 2 + 9 files changed, 645 insertions(+), 616 deletions(-) diff --git a/library.properties b/library.properties index b0890a1f..bfa833f7 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=10.17.0 +version=10.18.0 author= John Wellbelove maintainer=John Wellbelove sentence=A C++ template library tailored for embedded systems. diff --git a/src/c/ecl_timer.c b/src/c/ecl_timer.c index 2b6e3e77..3fb41b74 100644 --- a/src/c/ecl_timer.c +++ b/src/c/ecl_timer.c @@ -261,7 +261,6 @@ struct ecl_time_config struct ecl_timer_config* ptimers; uint_least8_t max_timers; volatile ecl_timer_enable_t enabled; - ECL_TIMER_TIMER_SEMAPHORE process_semaphore; volatile uint_least8_t registered_timers; }; @@ -274,7 +273,6 @@ void ecl_timer_init(struct ecl_timer_config* ptimers_, uint_least8_t max_timers_ ecl.ptimers = ptimers_; ecl.max_timers = max_timers_; ecl.enabled = 0; - ecl.process_semaphore = 0; ecl.registered_timers = 0; int i; @@ -298,7 +296,7 @@ ecl_timer_id_t ecl_timer_register(void (*pcallback_)(), ecl_timer_id_t id = ECL_TIMER_NO_TIMER; - ECL_TIMER_DISABLE_PROCESSING(ecl.process_semaphore); + ECL_TIMER_DISABLE_PROCESSING; int is_space = (ecl.registered_timers < ecl.max_timers); @@ -321,7 +319,7 @@ ecl_timer_id_t ecl_timer_register(void (*pcallback_)(), } } - ECL_TIMER_ENABLE_PROCESSING(ecl.process_semaphore); + ECL_TIMER_ENABLE_PROCESSING; return id; } @@ -337,7 +335,7 @@ ecl_timer_result_t ecl_timer_unregister(ecl_timer_id_t id_) if (id_ != ECL_TIMER_NO_TIMER) { - ECL_TIMER_DISABLE_PROCESSING(ecl.process_semaphore); + ECL_TIMER_DISABLE_PROCESSING; struct ecl_timer_config* ptimer = &ecl.ptimers[id_]; @@ -355,7 +353,7 @@ ecl_timer_result_t ecl_timer_unregister(ecl_timer_id_t id_) } } - ECL_TIMER_ENABLE_PROCESSING(ecl.process_semaphore); + ECL_TIMER_ENABLE_PROCESSING; } return result; @@ -385,7 +383,7 @@ ecl_timer_result_t ecl_timer_is_running() //******************************************* void ecl_timer_clear() { - ECL_TIMER_DISABLE_PROCESSING(ecl.process_semaphore); + ECL_TIMER_DISABLE_PROCESSING; ecl_timer_list_clear(); @@ -397,7 +395,7 @@ void ecl_timer_clear() ecl.registered_timers = 0; - ECL_TIMER_ENABLE_PROCESSING(ecl.process_semaphore); + ECL_TIMER_ENABLE_PROCESSING; } //******************************************* @@ -411,7 +409,7 @@ ecl_timer_result_t ecl_timer_tick(uint32_t count) if (ecl.enabled) { - if (ECL_TIMER_PROCESSING_ENABLED(ecl.process_semaphore)) + if (ECL_TIMER_PROCESSING_ENABLED) { // We have something to do? int has_active = !ecl_timer_list_empty(); @@ -463,8 +461,6 @@ ecl_timer_result_t ecl_timer_start(ecl_timer_id_t id_, ecl_timer_start_t immedia { assert(ecl.ptimers != 0); - ECL_TIMER_DISABLE_PROCESSING(ecl.process_semaphore); - ecl_timer_result_t result = ECL_TIMER_FAIL; // Valid timer id? @@ -478,6 +474,7 @@ ecl_timer_result_t ecl_timer_start(ecl_timer_id_t id_, ecl_timer_start_t immedia // Has a valid period. if (ptimer->period != ECL_TIMER_INACTIVE) { + ECL_TIMER_DISABLE_PROCESSING; if (ecl_timer_is_active(ptimer)) { ecl_timer_list_remove(ptimer->id, 0); @@ -485,14 +482,13 @@ ecl_timer_result_t ecl_timer_start(ecl_timer_id_t id_, ecl_timer_start_t immedia ptimer->delta = immediate_ ? 0 : ptimer->period; ecl_timer_list_insert(ptimer->id); + ECL_TIMER_ENABLE_PROCESSING; result = ECL_TIMER_PASS; } } } - ECL_TIMER_ENABLE_PROCESSING(ecl.process_semaphore); - return result; } @@ -503,8 +499,6 @@ ecl_timer_result_t ecl_timer_stop(ecl_timer_id_t id_) { assert(ecl.ptimers != 0); - ECL_TIMER_DISABLE_PROCESSING(ecl.process_semaphore); - ecl_timer_result_t result = ECL_TIMER_FAIL; // Valid timer id? @@ -517,14 +511,14 @@ ecl_timer_result_t ecl_timer_stop(ecl_timer_id_t id_) { if (ecl_timer_is_active(ptimer)) { + ECL_TIMER_DISABLE_PROCESSING; ecl_timer_list_remove(ptimer->id, 0); + ECL_TIMER_ENABLE_PROCESSING; result = ECL_TIMER_PASS; } } } - ECL_TIMER_ENABLE_PROCESSING(ecl.process_semaphore); - return result; } diff --git a/src/callback_timer.h b/src/callback_timer.h index d8e5124c..8ed39417 100644 --- a/src/callback_timer.h +++ b/src/callback_timer.h @@ -42,6 +42,30 @@ SOFTWARE. #undef ETL_FILE #define ETL_FILE "42" +#if !defined(ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK) && !defined(ETL_CALLBACK_TIMER_USE_INTERRUPT_LOCK) + #error ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK or ETL_CALLBACK_TIMER_USE_INTERRUPT_LOCK not defined +#endif + +#if defined(ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK) && defined(ETL_CALLBACK_TIMER_USE_INTERRUPT_LOCK) + #error Only define one of ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK or ETL_CALLBACK_TIMER_USE_INTERRUPT_LOCK +#endif + +#if defined(ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK) + #define ETL_DISABLE_TIMER_UPDATES (++process_semaphore) + #define ETL_ENABLE_TIMER_UPDATES (--process_semaphore) + #define ETL_TIMER_UPDATES_ENABLED (process_semaphore.load() == 0) +#endif + +#if defined(ETL_CALLBACK_TIMER_USE_INTERRUPT_LOCK) + #if !defined(ETL_CALLBACK_TIMER_DISABLE_INTERRUPTS) || !defined(ETL_CALLBACK_TIMER_ENABLE_INTERRUPTS) + #error ETL_CALLBACK_TIMER_DISABLE_INTERRUPTS and/or ETL_CALLBACK_TIMER_ENABLE_INTERRUPTS not defined + #endif + + #define ETL_DISABLE_TIMER_UPDATES (ETL_CALLBACK_TIMER_DISABLE_INTERRUPTS) + #define ETL_ENABLE_TIMER_UPDATES (ETL_CALLBACK_TIMER_ENABLE_INTERRUPTS) + #define ETL_TIMER_UPDATES_ENABLED true +#endif + namespace etl { //************************************************************************* @@ -326,7 +350,7 @@ namespace etl { etl::timer::id::type id = etl::timer::id::NO_TIMER; - disable_timer_updates(); + ETL_DISABLE_TIMER_UPDATES; bool is_space = (registered_timers < MAX_TIMERS); @@ -348,7 +372,7 @@ namespace etl } } - enable_timer_updates(); + ETL_ENABLE_TIMER_UPDATES; return id; } @@ -362,7 +386,7 @@ namespace etl { etl::timer::id::type id = etl::timer::id::NO_TIMER; - disable_timer_updates(); + ETL_DISABLE_TIMER_UPDATES; bool is_space = (registered_timers < MAX_TIMERS); @@ -384,7 +408,7 @@ namespace etl } } - enable_timer_updates(); + ETL_ENABLE_TIMER_UPDATES; return id; } @@ -398,7 +422,7 @@ namespace etl if (id_ != etl::timer::id::NO_TIMER) { - disable_timer_updates(); + ETL_DISABLE_TIMER_UPDATES; etl::callback_timer_data& timer = timer_array[id_]; @@ -416,7 +440,7 @@ namespace etl } } - enable_timer_updates(); + ETL_ENABLE_TIMER_UPDATES; } return result; @@ -443,7 +467,7 @@ namespace etl //******************************************* void clear() { - disable_timer_updates(); + ETL_DISABLE_TIMER_UPDATES; active_list.clear(); @@ -454,7 +478,7 @@ namespace etl registered_timers = 0; - enable_timer_updates(); + ETL_ENABLE_TIMER_UPDATES; } //******************************************* @@ -467,7 +491,7 @@ namespace etl { if (enabled) { - if (process_semaphore.load() == 0) + if (ETL_TIMER_UPDATES_ENABLED) { // We have something to do? bool has_active = !active_list.empty(); @@ -525,8 +549,6 @@ namespace etl //******************************************* bool start(etl::timer::id::type id_, bool immediate_ = false) { - disable_timer_updates(); - bool result = false; // Valid timer id? @@ -540,6 +562,7 @@ namespace etl // Has a valid period. if (timer.period != etl::timer::state::INACTIVE) { + ETL_DISABLE_TIMER_UPDATES; if (timer.is_active()) { active_list.remove(timer.id, false); @@ -547,14 +570,13 @@ namespace etl timer.delta = immediate_ ? 0 : timer.period; active_list.insert(timer.id); + ETL_ENABLE_TIMER_UPDATES; result = true; } } } - enable_timer_updates(); - return result; } @@ -563,8 +585,6 @@ namespace etl //******************************************* bool stop(etl::timer::id::type id_) { - disable_timer_updates(); - bool result = false; // Valid timer id? @@ -577,14 +597,14 @@ namespace etl { if (timer.is_active()) { + ETL_DISABLE_TIMER_UPDATES; active_list.remove(timer.id, false); + ETL_ENABLE_TIMER_UPDATES; result = true; } } } - enable_timer_updates(); - return result; } @@ -625,7 +645,9 @@ namespace etl : timer_array(timer_array_), active_list(timer_array_), enabled(false), +#if defined(ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK) process_semaphore(0), +#endif registered_timers(0), MAX_TIMERS(MAX_TIMERS_) { @@ -633,22 +655,6 @@ namespace etl private: - //******************************************* - /// Enable timer callback events. - //******************************************* - void enable_timer_updates() - { - --process_semaphore; - } - - //******************************************* - /// Disable timer callback events. - //******************************************* - void disable_timer_updates() - { - ++process_semaphore; - } - // The array of timer data structures. callback_timer_data* const timer_array; @@ -656,7 +662,9 @@ namespace etl __private_callback_timer__::list active_list; volatile bool enabled; +#if defined(ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK) volatile etl::timer_semaphore_t process_semaphore; +#endif volatile uint_least8_t registered_timers; public: @@ -688,6 +696,10 @@ namespace etl }; } +#undef ETL_DISABLE_TIMER_UPDATES +#undef ETL_ENABLE_TIMER_UPDATES +#undef ETL_TIMER_UPDATES_ENABLED + #undef ETL_FILE #endif diff --git a/src/message_timer.h b/src/message_timer.h index 03a6a19c..d76bb94d 100644 --- a/src/message_timer.h +++ b/src/message_timer.h @@ -45,6 +45,30 @@ SOFTWARE. #undef ETL_FILE #define ETL_FILE "41" +#if !defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK) && !defined(ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK) + #error ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK or ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK not defined +#endif + +#if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK) && defined(ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK) + #error Only define one of ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK or ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK +#endif + +#if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK) + #define ETL_DISABLE_TIMER_UPDATES (++process_semaphore) + #define ETL_ENABLE_TIMER_UPDATES (--process_semaphore) + #define ETL_TIMER_UPDATES_ENABLED (process_semaphore.load() == 0) +#endif + +#if defined(ETL_MESSAGE_TIMER_USE_INTERRUPT_LOCK) + #if !defined(ETL_MESSAGE_TIMER_DISABLE_INTERRUPTS) || !defined(ETL_MESSAGE_TIMER_ENABLE_INTERRUPTS) + #error ETL_MESSAGE_TIMER_DISABLE_INTERRUPTS and/or ETL_MESSAGE_TIMER_ENABLE_INTERRUPTS not defined + #endif + + #define ETL_DISABLE_TIMER_UPDATES (ETL_MESSAGE_TIMER_DISABLE_INTERRUPTS) + #define ETL_ENABLE_TIMER_UPDATES (ETL_MESSAGE_TIMER_ENABLE_INTERRUPTS) + #define ETL_TIMER_UPDATES_ENABLED true +#endif + namespace etl { //************************************************************************* @@ -323,7 +347,7 @@ namespace etl { etl::timer::id::type id = etl::timer::id::NO_TIMER; - disable_timer_updates(); + ETL_DISABLE_TIMER_UPDATES; bool is_space = (registered_timers < MAX_TIMERS); @@ -349,7 +373,7 @@ namespace etl } } - enable_timer_updates(); + ETL_ENABLE_TIMER_UPDATES; return id; } @@ -363,7 +387,7 @@ namespace etl if (id_ != etl::timer::id::NO_TIMER) { - disable_timer_updates(); + ETL_DISABLE_TIMER_UPDATES; etl::message_timer_data& timer = timer_array[id_]; @@ -381,7 +405,7 @@ namespace etl } } - enable_timer_updates(); + ETL_ENABLE_TIMER_UPDATES; } return result; @@ -408,7 +432,7 @@ namespace etl //******************************************* void clear() { - disable_timer_updates(); + ETL_DISABLE_TIMER_UPDATES; active_list.clear(); @@ -419,7 +443,7 @@ namespace etl registered_timers = 0; - enable_timer_updates(); + ETL_ENABLE_TIMER_UPDATES; } //******************************************* @@ -432,7 +456,7 @@ namespace etl { if (enabled) { - if (process_semaphore.load() == 0) + if ETL_IF_CONSTEXPR(ETL_TIMER_UPDATES_ENABLED) { // We have something to do? bool has_active = !active_list.empty(); @@ -492,8 +516,6 @@ namespace etl { bool result = false; - disable_timer_updates(); - // Valid timer id? if (id_ != etl::timer::id::NO_TIMER) { @@ -505,6 +527,7 @@ namespace etl // Has a valid period. if (timer.period != etl::timer::state::INACTIVE) { + ETL_DISABLE_TIMER_UPDATES; if (timer.is_active()) { active_list.remove(timer.id, false); @@ -512,14 +535,13 @@ namespace etl timer.delta = immediate_ ? 0 : timer.period; active_list.insert(timer.id); + ETL_ENABLE_TIMER_UPDATES; result = true; } } } - enable_timer_updates(); - return result; } @@ -530,8 +552,6 @@ namespace etl { bool result = false; - disable_timer_updates(); - // Valid timer id? if (id_ != etl::timer::id::NO_TIMER) { @@ -542,14 +562,14 @@ namespace etl { if (timer.is_active()) { + ETL_DISABLE_TIMER_UPDATES; active_list.remove(timer.id, false); + ETL_ENABLE_TIMER_UPDATES; result = true; } } } - enable_timer_updates(); - return result; } @@ -590,7 +610,9 @@ namespace etl : timer_array(timer_array_), active_list(timer_array_), enabled(false), +#if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK) process_semaphore(0), +#endif registered_timers(0), MAX_TIMERS(MAX_TIMERS_) { @@ -605,22 +627,6 @@ namespace etl private: - //******************************************* - /// Enable timer callback events. - //******************************************* - void enable_timer_updates() - { - --process_semaphore; - } - - //******************************************* - /// Disable timer callback events. - //******************************************* - void disable_timer_updates() - { - ++process_semaphore; - } - // The array of timer data structures. message_timer_data* const timer_array; @@ -628,7 +634,10 @@ namespace etl __private_message_timer__::list active_list; volatile bool enabled; + +#if defined(ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK) volatile etl::timer_semaphore_t process_semaphore; +#endif volatile uint_least8_t registered_timers; public: @@ -660,6 +669,10 @@ namespace etl }; } +#undef ETL_DISABLE_TIMER_UPDATES +#undef ETL_ENABLE_TIMER_UPDATES +#undef ETL_TIMER_UPDATES_ENABLED + #undef ETL_FILE #endif diff --git a/support/Release notes.txt b/support/Release notes.txt index a02a8180..11310d97 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,9 @@ +=============================================================================== +10.18.0 +Improvements to message and callback timer frameworks. +Reduced disable/enable time dur function calls. +Added the option to use either atomic semaphores or interrupt enables to control access. + =============================================================================== 10.17.0 Added emplace functions to etl::variant. diff --git a/test/codeblocks/ETL.layout b/test/codeblocks/ETL.layout index 7fb40ace..1306d367 100644 --- a/test/codeblocks/ETL.layout +++ b/test/codeblocks/ETL.layout @@ -1,585 +1,584 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/test/ecl_user.h b/test/ecl_user.h index 26eb1ab4..418bdee9 100644 --- a/test/ecl_user.h +++ b/test/ecl_user.h @@ -31,18 +31,18 @@ SOFTWARE. #include +extern uint32_t timer_semaphore; + #if defined(_MSC_VER) #include - #define ECL_TIMER_TIMER_SEMAPHORE uint32_t - #define ECL_TIMER_DISABLE_PROCESSING(x) InterlockedIncrement((volatile long*)&x) - #define ECL_TIMER_ENABLE_PROCESSING(x) InterlockedDecrement((volatile long*)&x) - #define ECL_TIMER_PROCESSING_ENABLED(x) (InterlockedAdd((volatile long*)&x, 0) == 0) + #define ECL_TIMER_DISABLE_PROCESSING InterlockedIncrement((volatile long*)&timer_semaphore) + #define ECL_TIMER_ENABLE_PROCESSING InterlockedDecrement((volatile long*)&timer_semaphore) + #define ECL_TIMER_PROCESSING_ENABLED (InterlockedAdd((volatile long*)&timer_semaphore, 0) == 0) #else - #define ECL_TIMER_TIMER_SEMAPHORE uint32_t - #define ECL_TIMER_DISABLE_PROCESSING(x) __sync_fetch_and_add(&x, 1) - #define ECL_TIMER_ENABLE_PROCESSING(x) __sync_fetch_and_sub(&x, 1) - #define ECL_TIMER_PROCESSING_ENABLED(x) (__sync_fetch_and_add(&x, 0) == 0) + #define ECL_TIMER_DISABLE_PROCESSING __sync_fetch_and_add(&timer_semaphore, 1) + #define ECL_TIMER_ENABLE_PROCESSING __sync_fetch_and_sub(&timer_semaphore, 1) + #define ECL_TIMER_PROCESSING_ENABLED (__sync_fetch_and_add(&timer_semaphore, 0) == 0) #endif #endif diff --git a/test/etl_profile.h b/test/etl_profile.h index ab9df17e..d2f02616 100644 --- a/test/etl_profile.h +++ b/test/etl_profile.h @@ -39,6 +39,9 @@ SOFTWARE. #define ETL_IDEQUE_REPAIR_ENABLE #define ETL_IN_UNIT_TEST +#define ETL_MESSAGE_TIMER_USE_ATOMIC_LOCK +#define ETL_CALLBACK_TIMER_USE_ATOMIC_LOCK + #define ETL_POLYMORPHIC_BITSET #define ETL_POLYMORPHIC_DEQUE #define ETL_POLYMORPHIC_FLAT_MAP diff --git a/test/test_c_timer_framework.cpp b/test/test_c_timer_framework.cpp index c96a712b..3868fcc3 100644 --- a/test/test_c_timer_framework.cpp +++ b/test/test_c_timer_framework.cpp @@ -33,6 +33,8 @@ SOFTWARE. extern "C" { + uint32_t timer_semaphore; + #include "ecl_timer.h" } From 52fa62585a6b8d00215054cba5c53d4812e32b6d Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 6 Feb 2018 21:11:07 +0000 Subject: [PATCH 31/50] Reduced disable/enable time during function calls. --- library.properties | 2 +- src/callback_timer.h | 18 +++--------------- src/message_timer.h | 14 +++----------- support/Release notes.txt | 6 +++++- 4 files changed, 12 insertions(+), 28 deletions(-) diff --git a/library.properties b/library.properties index bfa833f7..c97b8bf2 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=10.18.0 +version=10.18.1 author= John Wellbelove maintainer=John Wellbelove sentence=A C++ template library tailored for embedded systems. diff --git a/src/callback_timer.h b/src/callback_timer.h index 8ed39417..42410566 100644 --- a/src/callback_timer.h +++ b/src/callback_timer.h @@ -350,8 +350,6 @@ namespace etl { etl::timer::id::type id = etl::timer::id::NO_TIMER; - ETL_DISABLE_TIMER_UPDATES; - bool is_space = (registered_timers < MAX_TIMERS); if (is_space) @@ -372,8 +370,6 @@ namespace etl } } - ETL_ENABLE_TIMER_UPDATES; - return id; } @@ -386,8 +382,6 @@ namespace etl { etl::timer::id::type id = etl::timer::id::NO_TIMER; - ETL_DISABLE_TIMER_UPDATES; - bool is_space = (registered_timers < MAX_TIMERS); if (is_space) @@ -408,8 +402,6 @@ namespace etl } } - ETL_ENABLE_TIMER_UPDATES; - return id; } @@ -422,15 +414,15 @@ namespace etl if (id_ != etl::timer::id::NO_TIMER) { - ETL_DISABLE_TIMER_UPDATES; - etl::callback_timer_data& timer = timer_array[id_]; if (timer.id != etl::timer::id::NO_TIMER) { if (timer.is_active()) { + ETL_DISABLE_TIMER_UPDATES; active_list.remove(timer.id, false); + ETL_ENABLE_TIMER_UPDATES; // Reset in-place. new (&timer) callback_timer_data(); @@ -439,8 +431,6 @@ namespace etl result = true; } } - - ETL_ENABLE_TIMER_UPDATES; } return result; @@ -468,8 +458,8 @@ namespace etl void clear() { ETL_DISABLE_TIMER_UPDATES; - active_list.clear(); + ETL_ENABLE_TIMER_UPDATES; for (int i = 0; i < MAX_TIMERS; ++i) { @@ -477,8 +467,6 @@ namespace etl } registered_timers = 0; - - ETL_ENABLE_TIMER_UPDATES; } //******************************************* diff --git a/src/message_timer.h b/src/message_timer.h index d76bb94d..64d41f7d 100644 --- a/src/message_timer.h +++ b/src/message_timer.h @@ -347,8 +347,6 @@ namespace etl { etl::timer::id::type id = etl::timer::id::NO_TIMER; - ETL_DISABLE_TIMER_UPDATES; - bool is_space = (registered_timers < MAX_TIMERS); if (is_space) @@ -373,8 +371,6 @@ namespace etl } } - ETL_ENABLE_TIMER_UPDATES; - return id; } @@ -387,15 +383,15 @@ namespace etl if (id_ != etl::timer::id::NO_TIMER) { - ETL_DISABLE_TIMER_UPDATES; - etl::message_timer_data& timer = timer_array[id_]; if (timer.id != etl::timer::id::NO_TIMER) { if (timer.is_active()) { + ETL_DISABLE_TIMER_UPDATES; active_list.remove(timer.id, true); + ETL_ENABLE_TIMER_UPDATES; // Reset in-place. new (&timer) message_timer_data(); @@ -404,8 +400,6 @@ namespace etl result = true; } } - - ETL_ENABLE_TIMER_UPDATES; } return result; @@ -433,8 +427,8 @@ namespace etl void clear() { ETL_DISABLE_TIMER_UPDATES; - active_list.clear(); + ETL_ENABLE_TIMER_UPDATES; for (int i = 0; i < MAX_TIMERS; ++i) { @@ -442,8 +436,6 @@ namespace etl } registered_timers = 0; - - ETL_ENABLE_TIMER_UPDATES; } //******************************************* diff --git a/support/Release notes.txt b/support/Release notes.txt index 11310d97..00170cfc 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,7 +1,11 @@ +=============================================================================== +10.18.1 +Reduced disable/enable time during function calls. + =============================================================================== 10.18.0 Improvements to message and callback timer frameworks. -Reduced disable/enable time dur function calls. +Reduced disable/enable time during function calls. Added the option to use either atomic semaphores or interrupt enables to control access. =============================================================================== From 58e155658e02499b0bf7e4745b6a5e029cf4e8ff Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 8 Feb 2018 16:00:05 +0000 Subject: [PATCH 32/50] Alignment tests for conversion operators --- test/test_alignment.cpp | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/test/test_alignment.cpp b/test/test_alignment.cpp index 4f55c829..ba0b25ab 100644 --- a/test/test_alignment.cpp +++ b/test/test_alignment.cpp @@ -67,6 +67,35 @@ namespace f(static_cast(data9)); } + //************************************************************************* + TEST(test_aligned_storage_conversion_operators) + { + typedef etl::aligned_storage::value>::type storage32_t; + static storage32_t data; + + void* pdata = &data.data; + + uint32_t& ref = data; + const uint32_t& cref = data; + CHECK(&ref == pdata); + CHECK(&cref == pdata); + + uint32_t* ptr = data; + const uint32_t* cptr = data; + CHECK(ptr == pdata); + CHECK(cptr == pdata); + + uint32_t& ref2 = data.get_reference(); + const uint32_t& cref2 = data.get_reference(); + CHECK(&ref2 == pdata); + CHECK(&cref2 == pdata); + + uint32_t* ptr2 = data.get_address(); + const uint32_t* cptr2 = data.get_address(); + CHECK(ptr2 == pdata); + CHECK(cptr2 == pdata); + } + //************************************************************************* TEST(test_aligned_storage_as) { From 1c4f0596a93c4f6ce790d603cd8753230f1c5ea8 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 11 Feb 2018 17:25:40 +0000 Subject: [PATCH 33/50] Added 'create' and 'destroy' functions --- src/pool.h | 423 ++++++++++++++++++++++++++++++++++++++------- test/test_pool.cpp | 172 ++++++++++++++++++ 2 files changed, 536 insertions(+), 59 deletions(-) diff --git a/src/pool.h b/src/pool.h index 01ff1a13..36bf99b6 100644 --- a/src/pool.h +++ b/src/pool.h @@ -32,13 +32,13 @@ SOFTWARE. #define __ETL_POOL__ #include "platform.h" +#include "error_handler.h" #include "alignment.h" #include "array.h" #include "container.h" #include "integral_limits.h" #include "nullptr.h" #include "alignment.h" -#include "error_handler.h" #include "static_assert.h" #include @@ -47,6 +47,8 @@ SOFTWARE. #undef ETL_FILE #define ETL_FILE "11" +#define ETL_POOL_CPP03_CODE 0 + //***************************************************************************** ///\defgroup pool pool /// A fixed capacity pool. @@ -117,8 +119,7 @@ namespace etl typedef size_t size_type; //************************************************************************* - /// Allocate an object from the pool. - /// Uses the default constructor. + /// Allocate storage for an object from the pool. /// If asserts or exceptions are enabled and there are no more free items an /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. //************************************************************************* @@ -133,13 +134,138 @@ namespace etl return reinterpret_cast(allocate_item()); } +#if !ETL_CPP11_SUPPORTED || ETL_POOL_CPP03_CODE + //************************************************************************* + /// Allocate storage for an object from the pool and create default. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. + //************************************************************************* + template + T* create() + { + T* p = allocate(); + + if (p) + { + ::new (p) T(); + } + + return p; + } + + //************************************************************************* + /// Allocate storage for an object from the pool and create with 1 parameter. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. + //************************************************************************* + template + T* create(const T1& value1) + { + T* p = allocate(); + + if (p) + { + ::new (p) T(value1); + } + + return p; + } + + //************************************************************************* + /// Allocate storage for an object from the pool and create with 2 parameters. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. + //************************************************************************* + template + T* create(const T1& value1, const T2& value2) + { + T* p = allocate(); + + if (p) + { + ::new (p) T(value1, value2); + } + + return p; + } + + //************************************************************************* + /// Allocate storage for an object from the pool and create with 3 parameters. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. + //************************************************************************* + template + T* create(const T1& value1, const T2& value2, const T3& value3) + { + T* p = allocate(); + + if (p) + { + ::new (p) T(value1, value2, value3); + } + + return p; + } + + //************************************************************************* + /// Allocate storage for an object from the pool and create with 4 parameters. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. + //************************************************************************* + template + T* create(const T1& value1, const T2& value2, const T3& value3, const T4& value4) + { + T* p = allocate(); + + if (p) + { + ::new (p) T(value1, value2, value3, value4); + } + + return p; + } +#else + //************************************************************************* + /// Emplace with variadic constructor parameters. + //************************************************************************* + template + T* create(Args&&... args) + { + T* p = allocate(); + + if (p) + { + ::new (p) T(std::forward(args)...); + } + + return p; + } +#endif + + //************************************************************************* + /// Destroys the object. + /// Undefined behaviour if the pool does not contain a 'T'. + /// \param p_object A pointer to the object to be destroyed. + //************************************************************************* + template + void destroy(const void* const p_object) + { + if (sizeof(T) > ITEM_SIZE) + { + ETL_ASSERT(false, ETL_ERROR(etl::pool_element_size)); + } + + reinterpret_cast((const_cast(p_object)))->~T(); + release(p_object); + } + //************************************************************************* /// Release an object in the pool. /// If asserts or exceptions are enabled and the object does not belong to this /// pool then an etl::pool_object_not_in_pool is thrown. /// \param p_object A pointer to the object to be released. //************************************************************************* - void release(const void* p_object) + void release(const void* const p_object) { release_item((char*)p_object); } @@ -259,7 +385,7 @@ namespace etl } else { - ETL_ASSERT(false, ETL_ERROR(etl::pool_no_allocation)); + ETL_ASSERT(false, ETL_ERROR(pool_no_allocation)); } return p_value; @@ -338,59 +464,6 @@ namespace etl #endif }; - //************************************************************************* - /// A templated pool implementation that uses a fixed size pool. - ///\ingroup pool - //************************************************************************* - template - class pool : public etl::ipool - { - public: - - static const size_t SIZE = SIZE_; - - //************************************************************************* - /// Constructor - //************************************************************************* - pool() - : etl::ipool(reinterpret_cast(&buffer[0]), ELEMENT_SIZE, SIZE) - { - } - - //************************************************************************* - /// Allocate an object from the pool. - /// Uses the default constructor. - /// If asserts or exceptions are enabled and there are no more free items an - /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. - /// Static asserts if the specified type is too large for the pool. - //************************************************************************* - template - U* allocate() - { - STATIC_ASSERT(sizeof(U) <= ELEMENT_SIZE, "Type too large for pool"); - return ipool::allocate(); - } - - private: - - // The pool element. - union Element - { - uintptr_t next; ///< Pointer to the next free element. - char value[sizeof(T)]; ///< Storage for value type. - typename etl::type_with_alignment::value>::type dummy; ///< Dummy item to get correct alignment. - }; - - ///< The memory for the pool of objects. - typename etl::aligned_storage::value>::type buffer[SIZE]; - - static const uint32_t ELEMENT_SIZE = sizeof(Element); - - // Should not be copied. - pool(const pool&); - pool& operator =(const pool&); - }; - //************************************************************************* /// A templated abstract pool implementation that uses a fixed size pool. ///\ingroup pool @@ -422,10 +495,102 @@ namespace etl U* allocate() { STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); - STATIC_ASSERT(sizeof(U) <= ELEMENT_SIZE, "Type too large for pool"); + STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); return ipool::allocate(); } +#if !ETL_CPP11_SUPPORTED || ETL_POOL_CPP03_CODE + //************************************************************************* + /// Allocate storage for an object from the pool and create with default. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. + //************************************************************************* + template + U* create() + { + STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); + STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return ipool::create(); + } + + //************************************************************************* + /// Allocate storage for an object from the pool and create with 1 parameter. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. + //************************************************************************* + template + U* create(const T1& value1) + { + STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); + STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return ipool::create(value1); + } + + //************************************************************************* + /// Allocate storage for an object from the pool and create with 2 parameters. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. + //************************************************************************* + template + U* create(const T1& value1, const T2& value2) + { + STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); + STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return ipool::create(value1, value2); + } + + //************************************************************************* + /// Allocate storage for an object from the pool and create with 3 parameters. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. + //************************************************************************* + template + U* create(const T1& value1, const T2& value2, const T3& value3) + { + STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); + STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return ipool::create(value1, value2, value3); + } + + //************************************************************************* + /// Allocate storage for an object from the pool and create with 4 parameters. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. + //************************************************************************* + template + U* create(const T1& value1, const T2& value2, const T3& value3, const T4& value4) + { + STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); + STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return ipool::create(value1, value2, value3, value4); + } +#else + //************************************************************************* + /// Emplace with variadic constructor parameters. + //************************************************************************* + template + U* create(Args&&... args) + { + STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); + STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return ipool::create(std::forward(args)...); + } +#endif + + //************************************************************************* + /// Destroys the object. + /// Undefined behaviour if the pool does not contain a 'U'. + /// \param p_object A pointer to the object to be destroyed. + //************************************************************************* + template + void destroy(const void* const p_object) + { + STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT_, "Type has incompatible alignment"); + STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + reinterpret_cast((const_cast(p_object)))->~U(); + ipool::release(p_object); + } + private: // The pool element. @@ -445,6 +610,146 @@ namespace etl generic_pool(const generic_pool&); generic_pool& operator =(const generic_pool&); }; + + //************************************************************************* + /// A templated pool implementation that uses a fixed size pool. + ///\ingroup pool + //************************************************************************* + template + class pool : public etl::generic_pool::value, SIZE_> + { + private: + + typedef etl::generic_pool::value, SIZE_> base_t; + + public: + + static const size_t SIZE = base_t::SIZE; + static const size_t ALIGNMENT = base_t::ALIGNMENT; + static const size_t TYPE_SIZE = base_t::TYPE_SIZE; + + //************************************************************************* + /// Constructor + //************************************************************************* + pool() + { + } + + //************************************************************************* + /// Allocate an object from the pool. + /// Uses the default constructor. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. + /// Static asserts if the specified type is too large for the pool. + //************************************************************************* + template + U* allocate() + { + STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT, "Type has incompatible alignment"); + STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return base_t::template allocate(); + } + +#if !ETL_CPP11_SUPPORTED || ETL_POOL_CPP03_CODE + //************************************************************************* + /// Allocate storage for an object from the pool and create with default. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. + //************************************************************************* + template + U* create() + { + STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT, "Type has incompatible alignment"); + STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return base_t::template create(); + } + + //************************************************************************* + /// Allocate storage for an object from the pool and create with 1 parameter. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. + //************************************************************************* + template + U* create(const T1& value1) + { + STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT, "Type has incompatible alignment"); + STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return base_t::template create(value1); + } + + //************************************************************************* + /// Allocate storage for an object from the pool and create with 2 parameters. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. + //************************************************************************* + template + U* create(const T1& value1, const T2& value2) + { + STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT, "Type has incompatible alignment"); + STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return base_t::template create(value1, value2); + } + + //************************************************************************* + /// Allocate storage for an object from the pool and create with 3 parameters. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. + //************************************************************************* + template + U* create(const T1& value1, const T2& value2, const T3& value3) + { + STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT, "Type has incompatible alignment"); + STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return base_t::template create(value1, value2, value3); + } + + //************************************************************************* + /// Allocate storage for an object from the pool and create with 4 parameters. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. + //************************************************************************* + template + U* create(const T1& value1, const T2& value2, const T3& value3, const T4& value4) + { + STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT, "Type has incompatible alignment"); + STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return base_t::template create(value1, value2, value3, value4); + } +#else + //************************************************************************* + /// Allocate storage for an object from the pool and create with variadic parameters. + /// If asserts or exceptions are enabled and there are no more free items an + /// etl::pool_no_allocation if thrown, otherwise a nullptr is returned. + //************************************************************************* + template + U* create(Args&&... args) + { + STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT, "Type has incompatible alignment"); + STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + return base_t::template create(std::forward(args)...); + } +#endif + + //************************************************************************* + /// Destroys the object. + /// Undefined behaviour if the pool does not contain a 'U'. + /// \param p_object A pointer to the object to be destroyed. + //************************************************************************* + template + void destroy(const void* const p_object) + { + STATIC_ASSERT(etl::alignment_of::value <= ALIGNMENT, "Type has incompatible alignment"); + STATIC_ASSERT(sizeof(U) <= TYPE_SIZE, "Type too large for pool"); + reinterpret_cast((const_cast(p_object)))->~U(); + base_t::release(p_object); + } + + private: + + // Should not be copied. + pool(const pool&); + pool& operator =(const pool&); + }; } #undef ETL_FILE diff --git a/test/test_pool.cpp b/test/test_pool.cpp index ecb15282..d4fd49e5 100644 --- a/test/test_pool.cpp +++ b/test/test_pool.cpp @@ -33,6 +33,7 @@ SOFTWARE. #include #include +#include #include "pool.h" #include "largest.h" @@ -47,6 +48,119 @@ typedef TestDataNDC Test_Data2; namespace { + struct D0 + { + D0() + { + } + }; + + struct D1 + { + D1(const std::string& a_) + : a(a_) + { + } + + std::string a; + }; + + struct D2 + { + D2(const std::string& a_, const std::string& b_) + : a(a_), + b(b_) + { + } + + std::string a; + std::string b; + }; + + struct D3 + { + D3(const std::string& a_, const std::string& b_, const std::string& c_) + : a(a_), + b(b_), + c(c_) + { + } + + std::string a; + std::string b; + std::string c; + }; + + struct D4 + { + D4(const std::string& a_, const std::string& b_, const std::string& c_, const std::string& d_) + : a(a_), + b(b_), + c(c_), + d(d_) + { + } + + std::string a; + std::string b; + std::string c; + std::string d; + }; + + bool operator == (const D0& lhs, const D0& rhs) + { + return true; + } + + bool operator == (const D1& lhs, const D1& rhs) + { + return (lhs.a == rhs.a); + } + + bool operator == (const D2& lhs, const D2& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b); + } + + bool operator == (const D3& lhs, const D3& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c); + } + + bool operator == (const D4& lhs, const D4& rhs) + { + return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c) && (lhs.d == rhs.d); + } + + std::ostream& operator <<(std::ostream& os, const D0& d) + { + return os; + } + + std::ostream& operator <<(std::ostream& os, const D1& d) + { + os << d.a; + return os; + } + + std::ostream& operator <<(std::ostream& os, const D2& d) + { + os << d.a << " " << d.b; + return os; + } + + std::ostream& operator <<(std::ostream& os, const D3& d) + { + os << d.a << " " << d.b << " " << d.c; + return os; + } + + std::ostream& operator <<(std::ostream& os, const D4& d) + { + os << d.a << " " << d.b << " " << d.c << " " << d.d; + return os; + } + SUITE(test_pool) { //************************************************************************* @@ -294,6 +408,64 @@ namespace CHECK_NO_THROW(p4 = pool.allocate()); } }; + + //************************************************************************* + TEST(test_create_destroy) + { + etl::pool pool0; + etl::pool pool1; + etl::pool pool2; + etl::pool pool3; + etl::pool pool4; + + D0* p0 = pool0.create(); + D1* p1 = pool1.create("1"); + D2* p2 = pool2.create("1", "2"); + D3* p3 = pool3.create("1", "2", "3"); + D4* p4 = pool4.create("1", "2", "3", "4"); + + CHECK_EQUAL(pool0.max_size() - 1, pool0.available()); + CHECK_EQUAL(1, pool0.size()); + + CHECK_EQUAL(pool1.max_size() - 1, pool1.available()); + CHECK_EQUAL(1, pool1.size()); + + CHECK_EQUAL(pool2.max_size() - 1, pool2.available()); + CHECK_EQUAL(1, pool2.size()); + + CHECK_EQUAL(pool3.max_size() - 1, pool3.available()); + CHECK_EQUAL(1, pool3.size()); + + CHECK_EQUAL(pool4.max_size() - 1, pool4.available()); + CHECK_EQUAL(1, pool4.size()); + + CHECK_EQUAL(D0(), *p0); + CHECK_EQUAL(D1("1"), *p1); + CHECK_EQUAL(D2("1", "2"), *p2); + CHECK_EQUAL(D3("1", "2", "3"), *p3); + CHECK_EQUAL(D4("1", "2", "3", "4"), *p4); + + pool0.destroy(p0); + pool1.destroy(p1); + pool2.destroy(p2); + pool3.destroy(p3); + pool4.destroy(p4); + + CHECK_EQUAL(pool0.max_size(), pool0.available()); + CHECK_EQUAL(0, pool0.size()); + + CHECK_EQUAL(pool1.max_size(), pool1.available()); + CHECK_EQUAL(0, pool1.size()); + + CHECK_EQUAL(pool2.max_size(), pool2.available()); + CHECK_EQUAL(0, pool2.size()); + + CHECK_EQUAL(pool3.max_size(), pool3.available()); + CHECK_EQUAL(0, pool3.size()); + + CHECK_EQUAL(pool4.max_size(), pool4.available()); + CHECK_EQUAL(0, pool4.size()); + } } #if defined(ETL_COMPILER_GCC) From feb59e0f2f88d830fb4c80d903b48884114d3182 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 11 Feb 2018 17:30:32 +0000 Subject: [PATCH 34/50] Added 'create' and 'destroy' functions --- library.properties | 2 +- support/Release notes.txt | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/library.properties b/library.properties index c97b8bf2..9d6827e0 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=10.18.1 +version=10.19.0 author= John Wellbelove maintainer=John Wellbelove sentence=A C++ template library tailored for embedded systems. diff --git a/support/Release notes.txt b/support/Release notes.txt index 00170cfc..7cea807c 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,10 @@ +=============================================================================== +10.19.0 +Added 'create' and 'destroy' functions to pools. +Modified class heirarchy. +etl::generic_pool is derived from on etl::ipool. +etl::pool is derived from etl::generic_pool. + =============================================================================== 10.18.1 Reduced disable/enable time during function calls. From b4bf215675697987d9929fc8407268ad4c15f5fe Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 11 Feb 2018 18:45:10 +0000 Subject: [PATCH 35/50] Removed unused variables --- test/test_forward_list.cpp | 2 +- test/test_functional.cpp | 4 ++-- test/test_intrusive_forward_list.cpp | 2 +- test/test_intrusive_list.cpp | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/test_forward_list.cpp b/test/test_forward_list.cpp index 524150a7..c6e81f6c 100644 --- a/test/test_forward_list.cpp +++ b/test/test_forward_list.cpp @@ -753,7 +753,7 @@ namespace CompareDataNDC::iterator i_compare_data = compare_data.begin(); std::advance(i_compare_data, 4); - CompareDataNDC::iterator i_compare_result = compare_data.erase_after(i_compare_data, compare_data.end()); + compare_data.erase_after(i_compare_data, compare_data.end()); DataNDC::iterator i_result = data.erase_after(i_data, data.end()); diff --git a/test/test_functional.cpp b/test/test_functional.cpp index ef3604c0..8a3ce993 100644 --- a/test/test_functional.cpp +++ b/test/test_functional.cpp @@ -88,7 +88,7 @@ namespace std::list::const_iterator itest = test.begin(); std::list::const_iterator icompare = compare.begin(); - std::vector>::const_iterator ivector = test_ref.begin(); + //std::vector>::const_iterator ivector = test_ref.begin(); while (icompare != compare.end()) { @@ -120,4 +120,4 @@ namespace CHECK_EQUAL(1, ra); } }; -} \ No newline at end of file +} diff --git a/test/test_intrusive_forward_list.cpp b/test/test_intrusive_forward_list.cpp index 0ec1a5d7..982e6e74 100644 --- a/test/test_intrusive_forward_list.cpp +++ b/test/test_intrusive_forward_list.cpp @@ -612,7 +612,7 @@ namespace std::forward_list::iterator i_compare_data = compare_data.begin(); std::advance(i_compare_data, 4); - std::forward_list::iterator i_compare_result = compare_data.erase_after(i_compare_data, compare_data.end()); + compare_data.erase_after(i_compare_data, compare_data.end()); DataNDC0::iterator i_result = data0.erase_after(i_data, data0.end()); diff --git a/test/test_intrusive_list.cpp b/test/test_intrusive_list.cpp index 4666298e..4d85c00a 100644 --- a/test/test_intrusive_list.cpp +++ b/test/test_intrusive_list.cpp @@ -644,7 +644,7 @@ namespace std::vector::iterator i_compare_data = compare_data.begin(); std::advance(i_compare_data, 5); - std::vector::iterator i_compare_result = compare_data.erase(i_compare_data, compare_data.end()); + compare_data.erase(i_compare_data, compare_data.end()); DataNDC0::iterator i_result = data0.erase(i_data, data0.end()); From 9404af807441be4f6d03306f36ab9c72b6daa941 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 11 Feb 2018 18:45:42 +0000 Subject: [PATCH 36/50] Codeblocks projects changes --- test/codeblocks/ETL.cbp | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/codeblocks/ETL.cbp b/test/codeblocks/ETL.cbp index 39a2bd7f..279a97cf 100644 --- a/test/codeblocks/ETL.cbp +++ b/test/codeblocks/ETL.cbp @@ -48,9 +48,7 @@ - - From ff79fd858383c4b819b1a705f6d32b415e5a42b5 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 11 Feb 2018 18:50:00 +0000 Subject: [PATCH 37/50] Fixed strict aliasing warnings for aligned storage --- library.properties | 2 +- src/alignment.h | 12 ++++++++---- support/Release notes.txt | 4 ++++ 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/library.properties b/library.properties index 9d6827e0..1583ca79 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=10.19.0 +version=10.19.1 author= John Wellbelove maintainer=John Wellbelove sentence=A C++ template library tailored for embedded systems. diff --git a/src/alignment.h b/src/alignment.h index f54ee145..39565c3a 100644 --- a/src/alignment.h +++ b/src/alignment.h @@ -117,7 +117,8 @@ namespace etl operator T& () { STATIC_ASSERT((etl::is_same:: value || ((ALIGNMENT % etl::alignment_of::value) == 0)), "Incompatible alignment"); - return reinterpret_cast(*data); + T* t = *this; + return *t; } /// Convert to const T reference. @@ -125,7 +126,8 @@ namespace etl operator const T& () const { STATIC_ASSERT((etl::is_same:: value || ((ALIGNMENT % etl::alignment_of::value) == 0)), "Incompatible alignment"); - return reinterpret_cast(*data); + const T* t = *this; + return *t; } /// Convert to T pointer. @@ -149,7 +151,8 @@ namespace etl T& get_reference() { STATIC_ASSERT((etl::is_same:: value || ((ALIGNMENT % etl::alignment_of::value) == 0)), "Incompatible alignment"); - return reinterpret_cast(*data); + T* t = *this; + return *t; } /// Get address as const T reference. @@ -157,7 +160,8 @@ namespace etl const T& get_reference() const { STATIC_ASSERT((etl::is_same:: value || ((ALIGNMENT % etl::alignment_of::value) == 0)), "Incompatible alignment"); - return reinterpret_cast(*data); + const T* t = *this; + return *t; } /// Get address as T pointer. diff --git a/support/Release notes.txt b/support/Release notes.txt index 7cea807c..5b7357c6 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,7 @@ +=============================================================================== +10.19.1 +Fixed strict aliasing warnings for aligned storage. + =============================================================================== 10.19.0 Added 'create' and 'destroy' functions to pools. From 070e8fe6b634e08974f0ec6a8d1e66ef58c9a8a3 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 16 Feb 2018 10:11:19 +0000 Subject: [PATCH 38/50] Improved etl::endianness. Added static functions. --- src/endianness.h | 28 +++++++++++++++++++++------- test/test_endian.cpp | 3 +++ 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/src/endianness.h b/src/endianness.h index ec8ff167..5dd3dcfc 100644 --- a/src/endianness.h +++ b/src/endianness.h @@ -68,24 +68,38 @@ namespace etl //*************************************************************************** struct endianness { - endianness() - : ETL_ENDIAN_TEST(0x0011223344556677) + etl::endian operator ()() const { + return etl::endian(*this); } - endian operator ()() const + operator etl::endian() const { - return endian(*this); + return get(); } - operator endian() const + static etl::endian value() { - return (*reinterpret_cast(&ETL_ENDIAN_TEST) == 0x44556677) ? endian::little : endian::big; + return get(); } private: - const uint64_t ETL_ENDIAN_TEST; + static etl::endian get() + { + static const union U + { + U() + : ui32(0x12345678) + { + } + + uint32_t ui32; + uint16_t ui16[2]; + } u; + + return (u.ui16[0] == 0x5678) ? etl::endian::little : etl::endian::big; + } }; } diff --git a/test/test_endian.cpp b/test/test_endian.cpp index 65730c1f..4028eb3e 100644 --- a/test/test_endian.cpp +++ b/test/test_endian.cpp @@ -41,6 +41,9 @@ namespace // Intel platform is little endian. CHECK(etl::endianness()() == etl::endian::little); CHECK(etl::endianness()() != etl::endian::big); + + CHECK(etl::endianness::value() == etl::endian::little); + CHECK(etl::endianness::value() != etl::endian::big); } }; } From 3a7e63a49712f2ed394ab04fc42821b668bfd4ec Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 16 Feb 2018 10:11:49 +0000 Subject: [PATCH 39/50] Modified interrupt locks to match C++ versions. --- src/c/ecl_timer.c | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/src/c/ecl_timer.c b/src/c/ecl_timer.c index 3fb41b74..6f648f88 100644 --- a/src/c/ecl_timer.c +++ b/src/c/ecl_timer.c @@ -296,8 +296,6 @@ ecl_timer_id_t ecl_timer_register(void (*pcallback_)(), ecl_timer_id_t id = ECL_TIMER_NO_TIMER; - ECL_TIMER_DISABLE_PROCESSING; - int is_space = (ecl.registered_timers < ecl.max_timers); if (is_space) @@ -319,8 +317,6 @@ ecl_timer_id_t ecl_timer_register(void (*pcallback_)(), } } - ECL_TIMER_ENABLE_PROCESSING; - return id; } @@ -335,15 +331,15 @@ ecl_timer_result_t ecl_timer_unregister(ecl_timer_id_t id_) if (id_ != ECL_TIMER_NO_TIMER) { - ECL_TIMER_DISABLE_PROCESSING; - struct ecl_timer_config* ptimer = &ecl.ptimers[id_]; if (ptimer->id != ECL_TIMER_NO_TIMER) { if (ecl_timer_is_active(ptimer)) { + ECL_TIMER_DISABLE_PROCESSING; ecl_timer_list_remove(ptimer->id, 0); + ECL_TIMER_ENABLE_PROCESSING; // Reset in-place. ecl_timer_data_init_default(ptimer); @@ -352,8 +348,6 @@ ecl_timer_result_t ecl_timer_unregister(ecl_timer_id_t id_) result = ECL_TIMER_PASS; } } - - ECL_TIMER_ENABLE_PROCESSING; } return result; @@ -383,19 +377,17 @@ ecl_timer_result_t ecl_timer_is_running() //******************************************* void ecl_timer_clear() { - ECL_TIMER_DISABLE_PROCESSING; - ecl_timer_list_clear(); int i; for (i = 0; i < ecl.max_timers; ++i) { + ECL_TIMER_DISABLE_PROCESSING; ecl_timer_data_init_default(&ecl.ptimers[i]); + ECL_TIMER_ENABLE_PROCESSING; } ecl.registered_timers = 0; - - ECL_TIMER_ENABLE_PROCESSING; } //******************************************* From a53768cc289db1f1c8178f7818d0bb56cc875802 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 17 Feb 2018 21:32:31 +0000 Subject: [PATCH 40/50] Re-write of debounce to improve base code reuse. --- src/debounce.h | 637 +++++++++++++++++++++++------------------ test/test_debounce.cpp | 30 +- 2 files changed, 390 insertions(+), 277 deletions(-) diff --git a/src/debounce.h b/src/debounce.h index 3d3d78b3..bb0db44a 100644 --- a/src/debounce.h +++ b/src/debounce.h @@ -44,15 +44,24 @@ namespace etl { public: - void add(bool sample) - { - state &= ~CHANGED; + typedef uint_least8_t flags_t; + typedef uint16_t count_t; + //************************************************************************* + /// Adds the new sample and clears the state change flag. + /// If the sample has changed then the counter is reset. + /// The last sample state is stored as a bit in the flags. + //************************************************************************* + void add_sample(bool sample) + { // Changed from last time? - if (sample != bool((state & LAST) != 0)) + if (sample != bool((flags & SAMPLE) != 0)) { - count = START_COUNT; + count = 0; + flags = (flags & ~SAMPLE) | (sample ? SAMPLE : 0); } + + flags &= ~CHANGE; } //************************************************************************* @@ -61,7 +70,7 @@ namespace etl //************************************************************************* bool has_changed() const { - return (state & CHANGED) != 0; + return (flags & CHANGE) != 0; } //************************************************************************* @@ -70,7 +79,7 @@ namespace etl //************************************************************************* bool is_set() const { - return (state & CURRENT) != 0; + return ((flags & STATE) > OFF); } //************************************************************************* @@ -79,7 +88,7 @@ namespace etl //************************************************************************* bool is_held() const { - return (state & HELD) != 0; + return (flags & STATE) > ON; } //************************************************************************* @@ -88,18 +97,28 @@ namespace etl //************************************************************************* bool is_repeating() const { - return (state & REPEATING) != 0; + return ((flags & STATE) == REPEATING); } + enum states + { + OFF = 0, + ON = 1, + HELD = 2, + REPEATING = 3, + STATE = 0x03, + SAMPLE = 4, + CHANGE = 8 + }; + protected: //************************************************************************* /// Constructor. - ///\param initial_state The initial state. Default = false. //************************************************************************* - debounce_base(bool initial_state = false) - : state(initial_state ? (CURRENT | LAST) : 0), - count(START_COUNT) + debounce_base(bool initial_state) + : flags(initial_state ? ON : OFF), + count(0) { } @@ -110,142 +129,346 @@ namespace etl { } - enum + //************************************************************************* + /// Gets the next state based on the inputs. + //************************************************************************* + void get_next(bool sample, bool condition_set, bool condition_clear, uint_least8_t state_table[][2]) { - START_COUNT = 0 - }; + int index1 = ((flags & STATE) * 2) + (sample ? 1 : 0); + int index2 = (sample ? (condition_set ? 0 : 1) : (condition_clear ? 0 : 1)); - enum + flags_t next = flags; + + next &= ~STATE; + next |= state_table[index1][index2]; + + if (next != flags) + { + next |= CHANGE; + } + else + { + next &= ~CHANGE; + } + + flags = next; + } + + flags_t flags; + count_t count; + }; + + //*************************************************************************** + /// State change logic for 2 state debounce. + //*************************************************************************** + class debounce2 : public debounce_base + { + protected: + + debounce2(bool initial_state) + : debounce_base(initial_state) { - CURRENT = 1, - LAST = 2, - HELD = 4, - CHANGED = 8, - REPEATING = 16 - }; + } - uint_least8_t state; + //************************************************************************* + /// Destructor. + //************************************************************************* + ~debounce2() + { + } - /// The state count. - uint16_t count; + //************************************************************************* + /// + //************************************************************************* + void set_state(bool sample, bool condition_set, bool condition_clear) + { + static uint_least8_t state_table[4][2] = + { + /* OFF 0 */{ debounce_base::OFF, debounce_base::OFF }, + /* OFF 1 */{ debounce_base::ON, debounce_base::OFF }, + /* ON 0 */{ debounce_base::OFF, debounce_base::ON }, + /* ON 1 */{ debounce_base::ON, debounce_base::ON }, + }; + + get_next(sample, condition_set, condition_clear, state_table); + } + + //************************************************************************* + /// + //************************************************************************* + bool process(bool sample, count_t valid_count) + { + add_sample(sample); + + if (count < UINT16_MAX) + { + ++count; + + bool valid = (count == valid_count); + + switch (flags & STATE) + { + case OFF: + { + set_state(sample, valid, valid); + break; + } + + case ON: + { + set_state(sample, valid, valid); + break; + } + + default: + { + break; + } + } + } + + if (flags & CHANGE) + { + count = 0; + } + + return (flags & CHANGE); + } + }; + + //*************************************************************************** + /// State change logic for 3 state debounce. + //*************************************************************************** + class debounce3 : public debounce_base + { + protected: + + debounce3(bool initial_state) + : debounce_base(initial_state) + { + } + + //************************************************************************* + /// Destructor. + //************************************************************************* + ~debounce3() + { + } + + //************************************************************************* + /// + //************************************************************************* + void set_state(bool sample, bool condition_set, bool condition_clear) + { + static uint_least8_t state_table[6][2] = + { + /* OFF 0 */{ debounce_base::OFF, debounce_base::OFF }, + /* OFF 1 */{ debounce_base::ON, debounce_base::OFF }, + /* ON 0 */{ debounce_base::OFF, debounce_base::ON }, + /* ON 1 */{ debounce_base::HELD, debounce_base::ON }, + /* HELD 0 */{ debounce_base::OFF, debounce_base::HELD }, + /* HELD 1 */{ debounce_base::HELD, debounce_base::HELD } + }; + + get_next(sample, condition_set, condition_clear, state_table); + } + + //************************************************************************* + /// + //************************************************************************* + bool process(bool sample, count_t valid_count, count_t hold_count) + { + add_sample(sample); + + if (count < UINT16_MAX) + { + ++count; + + bool valid = (count == valid_count); + bool hold = (count == hold_count); + + switch (flags & STATE) + { + case OFF: + { + set_state(sample, valid, valid); + break; + } + + case ON: + { + set_state(sample, hold, valid); + break; + } + + case HELD: + { + set_state(sample, hold, valid); + break; + } + + default: + { + break; + } + } + } + + if (flags & CHANGE) + { + count = 0; + } + + return (flags & CHANGE); + } + }; + + //*************************************************************************** + /// State change logic for 4 state debounce. + //*************************************************************************** + class debounce4 : public debounce_base + { + protected: + + debounce4(bool initial_state) + : debounce_base(initial_state) + { + } + + //************************************************************************* + /// Destructor. + //************************************************************************* + ~debounce4() + { + } + + //************************************************************************* + /// + //************************************************************************* + void set_state(bool sample, bool condition_set, bool condition_clear) + { + static uint_least8_t state_table[8][2] = + { + /* OFF 0 */{ debounce_base::OFF, debounce_base::OFF }, + /* OFF 1 */{ debounce_base::ON, debounce_base::OFF }, + /* ON 0 */{ debounce_base::OFF, debounce_base::ON }, + /* ON 1 */{ debounce_base::HELD, debounce_base::ON }, + /* HELD 0 */{ debounce_base::OFF, debounce_base::HELD }, + /* HELD 1 */{ debounce_base::REPEATING, debounce_base::HELD }, + /* REPEATING 0 */{ debounce_base::OFF, debounce_base::REPEATING }, + /* REPEATING 1 */{ debounce_base::REPEATING, debounce_base::REPEATING } + }; + + get_next(sample, condition_set, condition_clear, state_table); + } + + //************************************************************************* + /// + //************************************************************************* + bool process(bool sample, count_t valid_count, count_t hold_count, count_t repeat_count) + { + add_sample(sample); + + if (count < UINT16_MAX) + { + ++count; + + bool valid = (count == valid_count); + bool hold = (count == hold_count); + bool repeat = (count == repeat_count); + + switch (flags & STATE) + { + case OFF: + { + set_state(sample, valid, valid); + break; + } + + case ON: + { + set_state(sample, hold, valid); + break; + } + + case HELD: + { + set_state(sample, repeat, valid); + break; + } + + case REPEATING: + { + set_state(sample, repeat, valid); + + if (sample && repeat) + { + count = 0; + flags |= CHANGE; + } + break; + } + + default: + { + break; + } + } + } + + if (flags & CHANGE) + { + count = 0; + } + + return (flags & CHANGE); + } }; } //*************************************************************************** /// A class to debounce signals. - /// The state is decided over N samples, defined by the VALID_COUNT value. - /// If the samples are consistent for VALID_COUNT times then the debouncer state is defined. - /// If the samples change then the debouncer will change state after VALID_COUNT samples. - /// If the samples are true for a count of HOLD_COUNT then the debouncer input is 'held'. - /// The debouncer may be constructed in either state. + /// Fixed Valid/Hold/Repeating values. //*************************************************************************** template - class debounce : public __private_debounce__::debounce_base + class debounce : public __private_debounce__::debounce4 { - private: - - enum - { - VALID_THRESHOLD = VALID_COUNT, - HOLD_THRESHOLD = VALID_THRESHOLD + HOLD_COUNT, - REPEAT_THRESHOLD = HOLD_THRESHOLD + REPEAT_COUNT - }; - - using debounce_base::add; - public: //************************************************************************* /// Constructor. - ///\param initial_state The initial state. Default = false. //************************************************************************* debounce(bool initial_state = false) - : debounce_base(initial_state) + : debounce4(initial_state) { } //************************************************************************* /// Adds a new sample. - /// Returns 'true' if the debouncer changes state from... - /// 1. Clear to Set. - /// 2. Set to Clear. - /// 3. Not Held to Held. - /// 4. Key repeats. + /// Returns 'true' if the debouncer changes state. ///\param sample The new sample. ///\return 'true' if the debouncer changed state. //************************************************************************* bool add(bool sample) { - debounce_base::add(sample); - - if (count < REPEAT_THRESHOLD) - { - ++count; - - if (sample) - { - if (count == VALID_THRESHOLD) - { - // Set. - state |= CHANGED; - state |= CURRENT; - } - else if (count == HOLD_THRESHOLD) - { - // Held. - state |= CHANGED; - state |= HELD; - } - else if (count == REPEAT_THRESHOLD) - { - // Repeat. - state |= CHANGED; - state |= REPEATING; - count = HOLD_THRESHOLD; - } - - state |= LAST; - } - else - { - if (count == VALID_THRESHOLD) - { - // Clear. - state |= CHANGED; - state &= ~CURRENT; - state &= ~HELD; - state &= ~REPEATING; - } - - state &= ~LAST; - } - } - - return (state & CHANGED) != 0; + return process(sample, VALID_COUNT, HOLD_COUNT, REPEAT_COUNT); } }; - + + //*************************************************************************** + /// A class to debounce signals. + /// Fixed Valid/Hold values. + //*************************************************************************** template - class debounce : public __private_debounce__::debounce_base + class debounce : public __private_debounce__::debounce3 { - private: - - enum - { - VALID_THRESHOLD = VALID_COUNT, - HOLD_THRESHOLD = VALID_THRESHOLD + HOLD_COUNT - }; - - using debounce_base::add; - - public: + public: //************************************************************************* /// Constructor. - ///\param initial_state The initial state. Default = false. //************************************************************************* debounce(bool initial_state = false) - : debounce_base(initial_state) + : debounce3(initial_state) { } @@ -260,68 +483,24 @@ namespace etl //************************************************************************* bool add(bool sample) { - debounce_base::add(sample); - - if (count < HOLD_THRESHOLD) - { - ++count; - - if (sample) - { - if (count == VALID_THRESHOLD) - { - // Set. - state |= CHANGED; - state |= CURRENT; - } - else if (count == HOLD_THRESHOLD) - { - // Held. - state |= CHANGED; - state |= HELD; - } - - state |= LAST; - } - else - { - if (count == VALID_THRESHOLD) - { - // Clear. - state |= CHANGED; - state &= ~CURRENT; - state &= ~HELD; - state &= ~REPEATING; - } - - state &= ~LAST; - } - } - - return (state & CHANGED) != 0; + return process(sample, VALID_COUNT, HOLD_COUNT); } }; + //*************************************************************************** + /// A class to debounce signals. + /// Fixed Valid value. + //*************************************************************************** template - class debounce : public __private_debounce__::debounce_base + class debounce : public __private_debounce__::debounce2 { - private: - - enum - { - VALID_THRESHOLD = VALID_COUNT - }; - - using debounce_base::add; - public: //************************************************************************* /// Constructor. - ///\param initial_state The initial state. Default = false. //************************************************************************* debounce(bool initial_state = false) - : debounce_base(initial_state) + : debounce2(initial_state) { } @@ -335,83 +514,51 @@ namespace etl //************************************************************************* bool add(bool sample) { - debounce_base::add(sample); - - if (count < VALID_THRESHOLD) - { - ++count; - - if (sample) - { - if (count == VALID_THRESHOLD) - { - // Set. - state |= CHANGED; - state |= CURRENT; - } - - state |= LAST; - } - else - { - if (count == VALID_THRESHOLD) - { - // Clear. - state |= CHANGED; - state &= ~CURRENT; - state &= ~HELD; - state &= ~REPEATING; - } - - state &= ~LAST; - } - } - - return (state & CHANGED) != 0; + return process(sample, VALID_COUNT); } }; + //*************************************************************************** + /// A class to debounce signals. + /// Variable Valid/Hold/Repeating values. + //*************************************************************************** template <> - class debounce<0, 0, 0> : public __private_debounce__::debounce_base + class debounce<0, 0, 0> : public __private_debounce__::debounce4 { public: - using debounce_base::add; - //************************************************************************* /// Constructor. ///\param initial_state The initial state. Default = false. //************************************************************************* - debounce() - : debounce_base(false), - valid_threshold(1), - hold_threshold(0), - repeat_threshold(0) + debounce(bool initial_state = false) + : debounce4(initial_state), + valid_count(1), + hold_count(0), + repeat_count(0) { } //************************************************************************* /// Constructor. - ///\param initial_state The initial state. - ///\param valid_count The count for a valid state. Default = 1. + ///\param valid_count The count for a valid state.. ///\param hold_count The count after valid_count for a hold state. Default = 0. ///\param repeat_count The count after hold_count for a key repeat. Default = 0. //************************************************************************* - debounce(bool initial_state, uint16_t valid_count = 1, uint16_t hold_count = 0, uint16_t repeat_count = 0) - : debounce_base(initial_state) + debounce(count_t valid, count_t hold = 0, count_t repeat = 0) + : debounce4(false) { - set(valid_count, hold_count, repeat_count); + set(valid, hold, repeat); } //************************************************************************* /// Constructor. - ///\param initial_state The initial state. Default = false. //************************************************************************* - void set(uint16_t valid_count, uint16_t hold_count = 0, uint16_t repeat_count = 0) + void set(count_t valid, count_t hold = 0, count_t repeat = 0) { - valid_threshold = valid_count; - hold_threshold = valid_threshold + hold_count; - repeat_threshold = hold_threshold + repeat_count; + valid_count = valid; + hold_count = hold; + repeat_count = repeat; } //************************************************************************* @@ -426,70 +573,14 @@ namespace etl //************************************************************************* bool add(bool sample) { - debounce_base::add(sample); - - if (count < repeat_threshold) - { - ++count; - - if (sample) - { - if (count == valid_threshold) - { - if (sample) - { - // Set. - state |= CHANGED; - state |= CURRENT; - } - } - - if (hold_threshold != valid_threshold) - { - if ((count == hold_threshold) && sample) - { - // Held. - state |= CHANGED; - state |= HELD; - } - } - - if (repeat_threshold != hold_threshold) - { - if ((count == repeat_threshold) && sample) - { - // Repeat. - state |= CHANGED; - state |= REPEATING; - count = hold_threshold; - } - } - - state |= LAST; - } - else - { - if (count == valid_threshold) - { - // Clear. - state |= CHANGED; - state &= ~CURRENT; - state &= ~HELD; - state &= ~REPEATING; - } - - state &= ~LAST; - } - } - - return (state & CHANGED) != 0; + return process(sample, valid_count, hold_count, repeat_count); } private: - uint16_t valid_threshold; - uint16_t hold_threshold; - uint16_t repeat_threshold; + count_t valid_count; + count_t hold_count; + count_t repeat_count; }; } diff --git a/test/test_debounce.cpp b/test/test_debounce.cpp index 5670acce..bab33073 100644 --- a/test/test_debounce.cpp +++ b/test/test_debounce.cpp @@ -36,7 +36,7 @@ namespace { TEST(test_debounce_default_4_0_0_nonbounce) { - etl::debounce<4, 8, 0> key_state; + etl::debounce<4, 0, 0> key_state; CHECK(!key_state.is_set()); CHECK(!key_state.is_held()); @@ -472,6 +472,28 @@ namespace CHECK(!key_state.is_held()); CHECK(!key_state.is_repeating()); + //******************************* + // No transition to hold or repeat. + CHECK(!key_state.add(true)); + CHECK(key_state.is_set()); + CHECK(!key_state.is_held()); + CHECK(!key_state.is_repeating()); + + CHECK(!key_state.add(true)); + CHECK(key_state.is_set()); + CHECK(!key_state.is_held()); + CHECK(!key_state.is_repeating()); + + CHECK(!key_state.add(true)); + CHECK(key_state.is_set()); + CHECK(!key_state.is_held()); + CHECK(!key_state.is_repeating()); + + CHECK(!key_state.add(true)); + CHECK(key_state.is_set()); + CHECK(!key_state.is_held()); + CHECK(!key_state.is_repeating()); + //******************************* // Transition to clear. CHECK(!key_state.add(false)); @@ -518,13 +540,13 @@ namespace CHECK(!key_state.is_set()); CHECK(!key_state.is_held()); CHECK(!key_state.is_repeating()); - - // Valid set. + CHECK(!key_state.add(true)); CHECK(!key_state.is_set()); CHECK(!key_state.is_held()); CHECK(!key_state.is_repeating()); - + + // Valid set. CHECK(key_state.add(true)); CHECK(key_state.is_set()); CHECK(!key_state.is_held()); From 7d3836f8053a8cd1e58e7f427751074696cee720 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 18 Feb 2018 13:45:19 +0000 Subject: [PATCH 41/50] Updated release files --- library.properties | 2 +- support/Release notes.txt | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/library.properties b/library.properties index 1583ca79..4fe9f709 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=10.19.1 +version=10.20.0 author= John Wellbelove maintainer=John Wellbelove sentence=A C++ template library tailored for embedded systems. diff --git a/support/Release notes.txt b/support/Release notes.txt index 5b7357c6..8a780b79 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,13 @@ +=============================================================================== +10.20.0 +Rewrite of debounce code to factor out commonality. +Made interrupt locks in C timer framework to match that of C++ version. +Improved etl::endianness. Added static functions. + +=============================================================================== +10.19.2 +Fixed strict aliasing warnings for endianess. + =============================================================================== 10.19.1 Fixed strict aliasing warnings for aligned storage. From 703a9e0f4afb97fd0a21aafca454c49725eda768 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 18 Feb 2018 14:18:24 +0000 Subject: [PATCH 42/50] Changes from master --- test/test_flat_set.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_flat_set.cpp b/test/test_flat_set.cpp index 9bcbc73a..b7530a6d 100644 --- a/test/test_flat_set.cpp +++ b/test/test_flat_set.cpp @@ -101,7 +101,7 @@ namespace std::vector initial_data; std::vector excess_data; std::vector different_data; - + std::vector int_data; struct D1 From f296d9eadf2ac71bb08179dd392f088aab59706e Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 18 Feb 2018 14:19:39 +0000 Subject: [PATCH 43/50] Signed/Unsigned warnings --- test/test_pool.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/test_pool.cpp b/test/test_pool.cpp index efde3165..4ae73d68 100644 --- a/test/test_pool.cpp +++ b/test/test_pool.cpp @@ -425,19 +425,19 @@ namespace D4* p4 = pool4.create("1", "2", "3", "4"); CHECK_EQUAL(pool0.max_size() - 1, pool0.available()); - CHECK_EQUAL(1, pool0.size()); + CHECK_EQUAL(1U, pool0.size()); CHECK_EQUAL(pool1.max_size() - 1, pool1.available()); - CHECK_EQUAL(1, pool1.size()); + CHECK_EQUAL(1U, pool1.size()); CHECK_EQUAL(pool2.max_size() - 1, pool2.available()); - CHECK_EQUAL(1, pool2.size()); + CHECK_EQUAL(1U, pool2.size()); CHECK_EQUAL(pool3.max_size() - 1, pool3.available()); - CHECK_EQUAL(1, pool3.size()); + CHECK_EQUAL(1U, pool3.size()); CHECK_EQUAL(pool4.max_size() - 1, pool4.available()); - CHECK_EQUAL(1, pool4.size()); + CHECK_EQUAL(1U, pool4.size()); CHECK_EQUAL(D0(), *p0); CHECK_EQUAL(D1("1"), *p1); @@ -452,19 +452,19 @@ namespace pool4.destroy(p4); CHECK_EQUAL(pool0.max_size(), pool0.available()); - CHECK_EQUAL(0, pool0.size()); + CHECK_EQUAL(0U, pool0.size()); CHECK_EQUAL(pool1.max_size(), pool1.available()); - CHECK_EQUAL(0, pool1.size()); + CHECK_EQUAL(0U, pool1.size()); CHECK_EQUAL(pool2.max_size(), pool2.available()); - CHECK_EQUAL(0, pool2.size()); + CHECK_EQUAL(0U, pool2.size()); CHECK_EQUAL(pool3.max_size(), pool3.available()); - CHECK_EQUAL(0, pool3.size()); + CHECK_EQUAL(0U, pool3.size()); CHECK_EQUAL(pool4.max_size(), pool4.available()); - CHECK_EQUAL(0, pool4.size()); + CHECK_EQUAL(0U, pool4.size()); } } From c35f962e6fb496097c6462b1e4f4f9dcfee1320c Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 24 Feb 2018 10:55:36 +0000 Subject: [PATCH 44/50] Merge remote-tracking branch 'origin/master' into development # Conflicts: # test/codeblocks/ETL.layout # test/test_pool.cpp --- src/multimap.h | 134 ++++++++++++++++++++++----------------------- test/test_pool.cpp | 2 +- 2 files changed, 68 insertions(+), 68 deletions(-) diff --git a/src/multimap.h b/src/multimap.h index b5a5a897..ebb93c89 100644 --- a/src/multimap.h +++ b/src/multimap.h @@ -194,8 +194,8 @@ namespace etl /// Constructor //*********************************************************************** Node() : - weight(kNeither), - dir(kNeither) + weight((uint_least8_t) kNeither), + dir((uint_least8_t) kNeither) { } @@ -204,8 +204,8 @@ namespace etl //*********************************************************************** void mark_as_leaf() { - weight = kNeither; - dir = kNeither; + weight = (uint_least8_t) kNeither; + dir = (uint_least8_t) kNeither; parent = nullptr; children[0] = nullptr; children[1] = nullptr; @@ -245,13 +245,13 @@ namespace etl Node* weight_node = critical_node->children[critical_node->dir]; while (weight_node) { - // Keep going until we reach a terminal node (dir == kNeither) - if (kNeither != weight_node->dir) + // Keep going until we reach a terminal node (dir == (uint_least8_t) kNeither) + if ((uint_least8_t) kNeither != weight_node->dir) { // Does this insert balance the previous weight factor value? if (weight_node->weight == 1 - weight_node->dir) { - weight_node->weight = kNeither; + weight_node->weight = (uint_least8_t) kNeither; } else { @@ -269,14 +269,14 @@ namespace etl } // while(weight_node) // Step 2: Update weight for critical_node or rotate tree to balance node - if (kNeither == critical_node->weight) + if ((uint_least8_t) kNeither == critical_node->weight) { critical_node->weight = critical_node->dir; } // If direction is different than weight, then it will now be balanced else if (critical_node->dir != critical_node->weight) { - critical_node->weight = kNeither; + critical_node->weight = (uint_least8_t) kNeither; } // Rotate is required to balance the tree at the critical node else @@ -330,12 +330,12 @@ namespace etl new_root->dir = 1 - dir; // Clear weight factor from current position - position->weight = kNeither; + position->weight = (uint_least8_t) kNeither; // Position's parent becomes new_root position->parent = new_root; position = new_root; // Clear weight factor from new root - position->weight = kNeither; + position->weight = (uint_least8_t) kNeither; } //************************************************************************* @@ -358,7 +358,7 @@ namespace etl // Capture new root (either E or D depending on dir) Node* new_root = position->children[dir]->children[1 - dir]; // Set weight factor for B or C based on F or G existing and being a different than dir - position->children[dir]->weight = third != kNeither && third != dir ? dir : kNeither; + position->children[dir]->weight = third != (uint_least8_t) kNeither && third != dir ? dir : (uint_least8_t) kNeither; // Detach new root from its tree (replace with new roots child) position->children[dir]->children[1 - dir] = new_root->children[dir]; @@ -373,7 +373,7 @@ namespace etl position->children[dir]->parent = new_root; // Set weight factor for A based on F or G - position->weight = third != kNeither && third == dir ? 1 - dir : kNeither; + position->weight = third != (uint_least8_t) kNeither && third == dir ? 1 - dir : (uint_least8_t) kNeither; // Move new root's right tree to current roots left tree position->children[dir] = new_root->children[1 - dir]; @@ -391,7 +391,7 @@ namespace etl position->parent = new_root; position = new_root; // Clear weight factor for new current position - position->weight = kNeither; + position->weight = (uint_least8_t) kNeither; } //************************************************************************* @@ -402,10 +402,10 @@ namespace etl if (position) { // Is there a tree on the right? then find the minimum of that tree - if (position->children[kRight]) + if (position->children[(uint_least8_t) kRight]) { // Return minimum node found - position = find_limit_node(position->children[kRight], kLeft); + position = find_limit_node(position->children[(uint_least8_t) kRight], kLeft); } // Otherwise find the parent of this node else @@ -418,7 +418,7 @@ namespace etl // Find parent of current position parent = position->parent; // find_parent_node(root_node, position); // Repeat while previous position was on right side of parent tree - } while (parent && parent->children[kRight] == position); + } while (parent && parent->children[(uint_least8_t) kRight] == position); // Set parent node as the next position position = parent; @@ -434,10 +434,10 @@ namespace etl if (position) { // Is there a tree on the right? then find the minimum of that tree - if (position->children[kRight]) + if (position->children[(uint_least8_t) kRight]) { // Return minimum node found - position = find_limit_node(position->children[kRight], kLeft); + position = find_limit_node(position->children[(uint_least8_t) kRight], kLeft); } // Otherwise find the parent of this node else @@ -450,7 +450,7 @@ namespace etl // Find parent of current position parent = position->parent; // Repeat while previous position was on right side of parent tree - } while (parent && parent->children[kRight] == position); + } while (parent && parent->children[(uint_least8_t) kRight] == position); // Set parent node as the next position position = parent; @@ -472,10 +472,10 @@ namespace etl else { // Is there a tree on the left? then find the maximum of that tree - if (position->children[kLeft]) + if (position->children[(uint_least8_t) kLeft]) { // Return maximum node found - position = find_limit_node(position->children[kLeft], kRight); + position = find_limit_node(position->children[(uint_least8_t) kLeft], kRight); } // Otherwise find the parent of this node else @@ -488,7 +488,7 @@ namespace etl // Find parent of current position parent = position->parent; // Repeat while previous position was on left side of parent tree - } while (parent && parent->children[kLeft] == position); + } while (parent && parent->children[(uint_least8_t) kLeft] == position); // Set parent node as the next position position = parent; @@ -510,10 +510,10 @@ namespace etl else { // Is there a tree on the left? then find the maximum of that tree - if (position->children[kLeft]) + if (position->children[(uint_least8_t) kLeft]) { // Return maximum node found - position = find_limit_node(position->children[kLeft], kRight); + position = find_limit_node(position->children[(uint_least8_t) kLeft], kRight); } // Otherwise find the parent of this node else @@ -526,7 +526,7 @@ namespace etl // Find parent of current position parent = position->parent; // Repeat while previous position was on left side of parent tree - } while (parent && parent->children[kLeft] == position); + } while (parent && parent->children[(uint_least8_t) kLeft] == position); // Set parent node as the next position position = parent; @@ -589,15 +589,15 @@ namespace etl // Point swap node to detached node's parent, children and weight swap->parent = detached->parent; - swap->children[kLeft] = detached->children[kLeft]; - swap->children[kRight] = detached->children[kRight]; - if (swap->children[kLeft]) + swap->children[(uint_least8_t) kLeft] = detached->children[(uint_least8_t) kLeft]; + swap->children[(uint_least8_t) kRight] = detached->children[(uint_least8_t) kRight]; + if (swap->children[(uint_least8_t) kLeft]) { - swap->children[kLeft]->parent = swap; + swap->children[(uint_least8_t) kLeft]->parent = swap; } - if (swap->children[kRight]) + if (swap->children[(uint_least8_t) kRight]) { - swap->children[kRight]->parent = swap; + swap->children[(uint_least8_t) kRight]->parent = swap; } swap->weight = detached->weight; } @@ -1412,18 +1412,18 @@ namespace etl if (node_comp(key, data_node)) { // Keep searching for the node on the left - position = position->children[kLeft]; + position = position->children[(uint_least8_t) kLeft]; } else if (node_comp(data_node, key)) { // Keep searching for the node on the right - position = position->children[kRight]; + position = position->children[(uint_least8_t) kRight]; } else { // We found one, keep looking for more on the left found = position; - position = position->children[kLeft]; + position = position->children[(uint_least8_t) kLeft]; } } @@ -1445,18 +1445,18 @@ namespace etl if (node_comp(key, data_node)) { // Keep searching for the node on the left - position = position->children[kLeft]; + position = position->children[(uint_least8_t) kLeft]; } else if (node_comp(data_node, key)) { // Keep searching for the node on the right - position = position->children[kRight]; + position = position->children[(uint_least8_t) kRight]; } else { // We found one, keep looking for more on the left found = position; - position = position->children[kLeft]; + position = position->children[(uint_least8_t) kLeft]; } } @@ -1479,9 +1479,9 @@ namespace etl if (node_comp(key, data_node)) { lower_node = position; - if (position->children[kLeft]) + if (position->children[(uint_least8_t) kLeft]) { - position = position->children[kLeft]; + position = position->children[(uint_least8_t) kLeft]; } else { @@ -1491,13 +1491,13 @@ namespace etl } else if (node_comp(data_node, key)) { - position = position->children[kRight]; + position = position->children[(uint_least8_t) kRight]; } else { // Make note of current position, but keep looking to left for more lower_node = position; - position = position->children[kLeft]; + position = position->children[(uint_least8_t) kLeft]; } } @@ -1521,15 +1521,15 @@ namespace etl // Compare the key value to the current upper node key value if (node_comp(data_node, key)) { - position = position->children[kRight]; + position = position->children[(uint_least8_t) kRight]; } else if (node_comp(key, data_node)) { upper_node = position; // If a node equal to key hasn't been found go left - if (!found && position->children[kLeft]) + if (!found && position->children[(uint_least8_t) kLeft]) { - position = position->children[kLeft]; + position = position->children[(uint_least8_t) kLeft]; } else { @@ -1566,8 +1566,8 @@ namespace etl while (found) { // Search for critical weight node (all nodes whose weight factor - // is set to kNeither (balanced) - if (kNeither != found->weight) + // is set to (uint_least8_t) kNeither (balanced) + if ((uint_least8_t) kNeither != found->weight) { critical_node = found; } @@ -1579,27 +1579,27 @@ namespace etl if (node_comp(node, found_data_node)) { // Update direction taken to insert new node in parent node - found->dir = kLeft; + found->dir = (uint_least8_t) kLeft; } // Is the node provided to the right of the current position? else if (node_comp(found_data_node, node)) { // Update direction taken to insert new node in parent node - found->dir = kRight; + found->dir = (uint_least8_t) kRight; } else { // Update direction taken to insert new node in parent (and // duplicate) node to the right. - found->dir = kRight; + found->dir = (uint_least8_t) kRight; } // Is there a child of this parent node? if (found->children[found->dir]) { // Will this node be the parent of the next critical node whose - // weight factor is set to kNeither (balanced)? - if (kNeither != found->children[found->dir]->weight) + // weight factor is set to (uint_least8_t) kNeither (balanced)? + if ((uint_least8_t) kNeither != found->children[found->dir]->weight) { critical_parent_node = found; } @@ -1675,7 +1675,7 @@ namespace etl { // Which direction does parent use to get to this node? node->parent->dir = - node->parent->children[kLeft] == node ? kLeft : kRight; + node->parent->children[(uint_least8_t) kLeft] == node ? (uint_least8_t) kLeft : (uint_least8_t) kRight; // Make this nodes parent the next node node = node->parent; @@ -1697,20 +1697,20 @@ namespace etl if (node == found) { // Update the direction towards a replacement node at the found node - node->dir = node->children[kLeft] ? kLeft : kRight; + node->dir = node->children[(uint_least8_t) kLeft] ? (uint_least8_t) kLeft : (uint_least8_t) kRight; // Exit loop and proceed with step 3 break; } else { - // If this nodes weight is kNeither or we are taking the shorter path + // If this nodes weight is (uint_least8_t) kNeither or we are taking the shorter path // to the next node and our sibling (on longer path) is balanced then // we need to update the balance node to this node but all our // ancestors will not require rebalancing - if ((node->weight == kNeither) || + if ((node->weight == (uint_least8_t) kNeither) || (node->weight == (1 - node->dir) && - node->children[1 - node->dir]->weight == kNeither)) + node->children[1 - node->dir]->weight == (uint_least8_t) kNeither)) { // Update balance node to this node balance = node; @@ -1737,13 +1737,13 @@ namespace etl break; } - // If this nodes weight is kNeither or we are taking the shorter path + // If this nodes weight is (uint_least8_t) kNeither or we are taking the shorter path // to the next node and our sibling (on longer path) is balanced then // we need to update the balance node to this node but all our // ancestors will not require rebalancing - if ((node->weight == kNeither) || + if ((node->weight == (uint_least8_t) kNeither) || (node->weight == (1 - node->dir) && - node->children[1 - node->dir]->weight == kNeither)) + node->children[1 - node->dir]->weight == (uint_least8_t) kNeither)) { // Update balance node to this node balance = node; @@ -1759,17 +1759,17 @@ namespace etl if (node_comp(data_node, replace_data_node)) { // Update the direction to the replace node - node->dir = kLeft; + node->dir = (uint_least8_t) kLeft; } else if (node_comp(replace_data_node, data_node)) { // Update the direction to the replace node - node->dir = kRight; + node->dir = (uint_least8_t) kRight; } else { // Update the direction to the replace node - node->dir = node->children[kLeft] ? kLeft : kRight; + node->dir = node->children[(uint_least8_t) kLeft] ? (uint_least8_t) kLeft : (uint_least8_t) kRight; } } // while(node) @@ -1783,9 +1783,9 @@ namespace etl break; } - // If balance node is balanced already (kNeither) then just imbalance + // If balance node is balanced already ((uint_least8_t) kNeither) then just imbalance // the node in the opposite direction of the node being removed - if (balance->weight == kNeither) + if (balance->weight == (uint_least8_t) kNeither) { balance->weight = 1 - balance->dir; } @@ -1793,7 +1793,7 @@ namespace etl // node being removed then the node now becomes balanced else if (balance->weight == balance->dir) { - balance->weight = kNeither; + balance->weight = (uint_least8_t) kNeither; } // Otherwise a rotation is required at this node else @@ -1816,7 +1816,7 @@ namespace etl } // Already balanced, rebalance and make it heavy in opposite // direction of the node being removed - else if (weight == kNeither) + else if (weight == (uint_least8_t) kNeither) { // Is the root node being rebalanced (no parent) if (balance->parent == nullptr) diff --git a/test/test_pool.cpp b/test/test_pool.cpp index 4ae73d68..57c5363c 100644 --- a/test/test_pool.cpp +++ b/test/test_pool.cpp @@ -132,7 +132,7 @@ namespace return (lhs.a == rhs.a) && (lhs.b == rhs.b) && (lhs.c == rhs.c) && (lhs.d == rhs.d); } - std::ostream& operator <<(std::ostream& os, const D0& d) + std::ostream& operator <<(std::ostream& os, const D0&) { return os; } From d1adfab03c2f01bf717c7545ebb627fc6776538c Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 25 Feb 2018 13:21:00 +0000 Subject: [PATCH 45/50] Remove more GCC warnings from use of -Wextra --- src/multiset.h | 2 +- src/type_lookup.h | 36 ++++++++++++++++++------------------ test/murmurhash3.cpp | 2 ++ 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/src/multiset.h b/src/multiset.h index abdfd2e5..3d58d186 100644 --- a/src/multiset.h +++ b/src/multiset.h @@ -566,7 +566,7 @@ namespace etl // Capture new root (either E or D depending on dir) Node* new_root = position->children[dir]->children[1 - dir]; // Set weight factor for B or C based on F or G existing and being a different than dir - position->children[dir]->weight = third != kNeither && third != dir ? dir : kNeither; + position->children[dir]->weight = third != kNeither && third != dir ? dir : uint_least8_t(kNeither); // Detach new root from its tree (replace with new roots child) position->children[dir]->children[1 - dir] = new_root->children[dir]; diff --git a/src/type_lookup.h b/src/type_lookup.h index 1d8a98dc..01d254cf 100644 --- a/src/type_lookup.h +++ b/src/type_lookup.h @@ -101,7 +101,7 @@ namespace etl template struct type_from_id { - typedef + typedef typename etl::conditional::value ? T1::ID : - (unsigned int) etl::is_same::value ? T2::ID : - (unsigned int) etl::is_same::value ? T3::ID : - (unsigned int) etl::is_same::value ? T4::ID : - (unsigned int) etl::is_same::value ? T5::ID : - (unsigned int) etl::is_same::value ? T6::ID : - (unsigned int) etl::is_same::value ? T7::ID : - (unsigned int) etl::is_same::value ? T8::ID : - (unsigned int) etl::is_same::value ? T9::ID : - (unsigned int) etl::is_same::value ? T10::ID : - (unsigned int) etl::is_same::value ? T11::ID : - (unsigned int) etl::is_same::value ? T12::ID : - (unsigned int) etl::is_same::value ? T13::ID : - (unsigned int) etl::is_same::value ? T14::ID : - (unsigned int) etl::is_same::value ? T15::ID : - (unsigned int) etl::is_same::value ? T16::ID : + (unsigned int) etl::is_same::value ? (unsigned int)T1::ID : + (unsigned int) etl::is_same::value ? (unsigned int)T2::ID : + (unsigned int) etl::is_same::value ? (unsigned int)T3::ID : + (unsigned int) etl::is_same::value ? (unsigned int)T4::ID : + (unsigned int) etl::is_same::value ? (unsigned int)T5::ID : + (unsigned int) etl::is_same::value ? (unsigned int)T6::ID : + (unsigned int) etl::is_same::value ? (unsigned int)T7::ID : + (unsigned int) etl::is_same::value ? (unsigned int)T8::ID : + (unsigned int) etl::is_same::value ? (unsigned int)T9::ID : + (unsigned int) etl::is_same::value ? (unsigned int)T10::ID : + (unsigned int) etl::is_same::value ? (unsigned int)T11::ID : + (unsigned int) etl::is_same::value ? (unsigned int)T12::ID : + (unsigned int) etl::is_same::value ? (unsigned int)T13::ID : + (unsigned int) etl::is_same::value ? (unsigned int)T14::ID : + (unsigned int) etl::is_same::value ? (unsigned int)T15::ID : + (unsigned int) etl::is_same::value ? (unsigned int)T16::ID : (unsigned int) UNKNOWN }; @@ -202,7 +202,7 @@ namespace etl template struct type_from_type { - typedef + typedef typename etl::conditional::value, typename T1::type2, typename etl::conditional::value, typename T2::type2, typename etl::conditional::value, typename T3::type2, diff --git a/test/murmurhash3.cpp b/test/murmurhash3.cpp index eb453366..ba4f1443 100644 --- a/test/murmurhash3.cpp +++ b/test/murmurhash3.cpp @@ -7,6 +7,8 @@ // compile and run any of them on any platform, but your performance with the // non-native version will be less than optimal. +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" + #include "murmurhash3.h" //----------------------------------------------------------------------------- From d3493d601d73d4322caf317b5c6d7c8b1aca0a13 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 25 Feb 2018 13:21:27 +0000 Subject: [PATCH 46/50] Add full set of operators to etl::optional --- library.properties | 2 +- src/optional.h | 271 ++++++++++++++++++++++++++++++++++---- support/Release notes.txt | 5 + test/data.h | 20 +++ test/test_optional.cpp | 155 ++++++++++++++++++++++ 5 files changed, 428 insertions(+), 25 deletions(-) diff --git a/library.properties b/library.properties index 4fe9f709..6da68f3d 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=10.20.0 +version=10.21.0 author= John Wellbelove maintainer=John Wellbelove sentence=A C++ template library tailored for embedded systems. diff --git a/src/optional.h b/src/optional.h index f6f4ce10..a1ec6a64 100644 --- a/src/optional.h +++ b/src/optional.h @@ -97,6 +97,7 @@ namespace etl //***************************************************************************** /// An optional type. /// If the optional type is not initialised then a type is not constructed. + /// See http://en.cppreference.com/w/cpp/utility/optional ///\tparam The type to store. ///\ingroup utilities //***************************************************************************** @@ -329,7 +330,7 @@ void swap(etl::optional& lhs, etl::optional& rhs) } //*************************************************************************** -/// Equality operator. +/// Equality operator. cppreference 1 //*************************************************************************** template bool operator ==(const etl::optional& lhs, const etl::optional& rhs) @@ -349,7 +350,16 @@ bool operator ==(const etl::optional& lhs, const etl::optional& rhs) } //*************************************************************************** -/// Less than operator. +/// Equality operator. cppreference 2 +//*************************************************************************** +template +bool operator !=(const etl::optional& lhs, const etl::optional& rhs) +{ + return !(lhs == rhs); +} + +//*************************************************************************** +/// Less than operator. cppreference 3 //*************************************************************************** template bool operator <(const etl::optional& lhs, const etl::optional& rhs) @@ -369,7 +379,67 @@ bool operator <(const etl::optional& lhs, const etl::optional& rhs) } //*************************************************************************** -/// Equality operator. +/// Less than equal operator. cppreference 4 +//*************************************************************************** +template +bool operator <=(const etl::optional& lhs, const etl::optional& rhs) +{ + if (!bool(lhs)) + { + return true; + } + else if (!bool(rhs)) + { + return false; + } + else + { + return lhs.value() <= rhs.value(); + } +} + +//*************************************************************************** +/// greater than operator. cppreference 5 +//*************************************************************************** +template +bool operator >(const etl::optional& lhs, const etl::optional& rhs) +{ + if (!bool(lhs)) + { + return false; + } + else if (!bool(rhs)) + { + return true; + } + else + { + return lhs.value() > rhs.value(); + } +} + +//*************************************************************************** +/// greater than equal operator. cppreference 6 +//*************************************************************************** +template +bool operator >=(const etl::optional& lhs, const etl::optional& rhs) +{ + if (!bool(rhs)) + { + return true; + } + else if (!bool(lhs)) + { + return false; + } + else + { + return lhs.value() >= rhs.value(); + } +} + +//*************************************************************************** +/// Equality operator. cppreference 7 //*************************************************************************** template bool operator ==(const etl::optional& lhs, etl::nullopt_t) @@ -378,25 +448,43 @@ bool operator ==(const etl::optional& lhs, etl::nullopt_t) } //*************************************************************************** -/// Equality operator. +/// Equality operator. cppreference 8 //*************************************************************************** template bool operator ==(etl::nullopt_t, const etl::optional& rhs) +{ + return !bool(rhs); +} + +//*************************************************************************** +/// Inequality operator. cppreference 9 +//*************************************************************************** +template +bool operator !=(const etl::optional& lhs, etl::nullopt_t) +{ + return !(lhs == etl::nullopt); +} + +//*************************************************************************** +/// Inequality operator. cppreference 10 +//*************************************************************************** +template +bool operator !=(etl::nullopt_t , const etl::optional& rhs) +{ + return !(etl::nullopt == rhs); +} + +//*************************************************************************** +/// Less than operator. cppreference 11 +//*************************************************************************** +template +bool operator <(const etl::optional&, etl::nullopt_t) { return false; } //*************************************************************************** -/// Less than operator. -//*************************************************************************** -template -bool operator <(const etl::optional& lhs, etl::nullopt_t) -{ - return !bool(lhs); -} - -//*************************************************************************** -/// Less than operator. +/// Less than operator. cppreference 12 //*************************************************************************** template bool operator <(etl::nullopt_t, const etl::optional& rhs) @@ -405,32 +493,167 @@ bool operator <(etl::nullopt_t, const etl::optional& rhs) } //*************************************************************************** -/// Equality operator. -//************************************************************************** +/// Less than equal operator. cppreference 13 +//*************************************************************************** template -bool operator ==(const etl::optional& lhs, const T& rhs) +bool operator <=(const etl::optional& lhs, etl::nullopt_t) +{ + return !bool(lhs); +} + +//*************************************************************************** +/// Less than equal operator. cppreference 14 +//*************************************************************************** +template +bool operator <=(etl::nullopt_t, const etl::optional&) +{ + return true; +} + +//*************************************************************************** +/// Greater than operator. cppreference 15 +//*************************************************************************** +template +bool operator >(const etl::optional& lhs, etl::nullopt_t) +{ + return bool(lhs); +} + +//*************************************************************************** +/// Greater than operator. cppreference 16 +//*************************************************************************** +template +bool operator >(etl::nullopt_t, const etl::optional&) +{ + return false; +} + +//*************************************************************************** +/// Greater than equal operator. cppreference 17 +//*************************************************************************** +template +bool operator >=(const etl::optional&, etl::nullopt_t) +{ + return true; +} + +//*************************************************************************** +/// Greater than equal operator. cppreference 18 +//*************************************************************************** +template +bool operator >=(etl::nullopt_t, const etl::optional& rhs) +{ + return !bool(rhs); +} + +//*************************************************************************** +/// Equality operator. cppreference 19 +//************************************************************************** +template +bool operator ==(const etl::optional& lhs, const U& rhs) { return bool(lhs) ? lhs.value() == rhs : false; } //*************************************************************************** -/// Equality operator. +/// Inequality operator. cppreference 21 //************************************************************************** -template -bool operator ==(const T& value, const etl::optional& rhs) +template +bool operator !=(const etl::optional& lhs, const U& rhs) { - return bool(rhs) ? rhs.value() == value : false; + return !(lhs == rhs); } //*************************************************************************** -/// Less than operator. +/// Equality operator. cppreference 20 +//************************************************************************** +template +bool operator ==(const U& lhs, const etl::optional& rhs) +{ + return bool(rhs) ? rhs.value() == lhs : false; +} + //*************************************************************************** -template -bool operator <(const etl::optional& lhs, const T& rhs) +/// Inequality operator. cppreference 22 +//************************************************************************** +template +bool operator !=(const U& lhs, const etl::optional& rhs) +{ + return !(lhs == rhs); +} + +//*************************************************************************** +/// Less than operator. cppreference 23 +//*************************************************************************** +template +bool operator <(const etl::optional& lhs, const U& rhs) { return bool(lhs) ? lhs.value() < rhs : true; } +//*************************************************************************** +/// Less than operator. cppreference 24 +//*************************************************************************** +template +bool operator <(const U& lhs, const etl::optional& rhs) +{ + return bool(rhs) ? lhs < rhs.value() : false; +} + +//*************************************************************************** +/// Less than equal operator. cppreference 25 +//*************************************************************************** +template +bool operator <=(const etl::optional& lhs, const U& rhs) +{ + return bool(lhs) ? lhs.value() <= rhs : true; +} + +//*************************************************************************** +/// Less than equal operator. cppreference 26 +//*************************************************************************** +template +bool operator <=(const U& lhs, const etl::optional& rhs) +{ + return bool(rhs) ? lhs <= rhs.value() : false; +} + +//*************************************************************************** +/// Greater than operator. cppreference 27 +//*************************************************************************** +template +bool operator >(const etl::optional& lhs, const U& rhs) +{ + return bool(lhs) ? lhs.value() > rhs : false; +} + +//*************************************************************************** +/// Greater than operator. cppreference 28 +//*************************************************************************** +template +bool operator >(const U& lhs, const etl::optional& rhs) +{ + return bool(rhs) ? lhs > rhs.value() : true; +} + +//*************************************************************************** +/// Greater than equal operator. cppreference 29 +//*************************************************************************** +template +bool operator >=(const etl::optional& lhs, const U& rhs) +{ + return bool(lhs) ? lhs.value() >= rhs : false; +} + +//*************************************************************************** +/// Greater than equal operator. cppreference 30 +//*************************************************************************** +template +bool operator >=(const U& lhs, const etl::optional& rhs) +{ + return bool(rhs) ? lhs >= rhs.value() : true; +} + //*************************************************************************** /// Make an optional. //*************************************************************************** diff --git a/support/Release notes.txt b/support/Release notes.txt index 8a780b79..2dd20638 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,8 @@ +=============================================================================== +10.21.0 +Completion of operator set for etl::optional +Removal of more GCC warnings when using -Wextra. + =============================================================================== 10.20.0 Rewrite of debounce code to factor out commonality. diff --git a/test/data.h b/test/data.h index b66d2f8f..9db25ab4 100644 --- a/test/data.h +++ b/test/data.h @@ -63,6 +63,16 @@ public: return value > other.value; } + bool operator <= (const TestDataDC& other) const + { + return !(value > other.value); + } + + bool operator >= (const TestDataDC& other) const + { + return !(value < other.value); + } + T value; int index; }; @@ -109,6 +119,16 @@ public: return value > other.value; } + bool operator <= (const TestDataNDC& other) const + { + return !(value > other.value); + } + + bool operator >= (const TestDataNDC& other) const + { + return !(value < other.value); + } + T value; int index; }; diff --git a/test/test_optional.cpp b/test/test_optional.cpp index 2c66f275..e0d081f4 100644 --- a/test/test_optional.cpp +++ b/test/test_optional.cpp @@ -114,24 +114,71 @@ namespace etl::optional data2; CHECK(data1 == data2); + CHECK(data2 == data1); data1 = Data("Data1"); CHECK(!(data1 == data2)); + CHECK(!(data2 == data1)); data1 = etl::nullopt; data2 = Data("Data2"); CHECK(!(data1 == data2)); + CHECK(!(data2 == data1)); data1 = Data("Data1"); data2 = Data("Data1"); CHECK(data1 == data2); + CHECK(data2 == data1); data1 = Data("Data1"); data2 = Data("Data2"); CHECK(!(data1 == data2)); + CHECK(!(data2 == data1)); + + CHECK(!(etl::nullopt == data2)); + CHECK(!(data1 == etl::nullopt)); CHECK(data1 == Data("Data1")); CHECK(!(data1 == Data("Data2"))); + CHECK(Data("Data1") == data1); + CHECK(!(Data("Data2") == data1)); + } + + //************************************************************************* + TEST(test_inequality) + { + etl::optional data1; + etl::optional data2; + + CHECK(!(data1 != data2)); + CHECK(!(data2 != data1)); + + data1 = Data("Data1"); + CHECK(data1 != data2); + CHECK(data2 != data1); + + data1 = etl::nullopt; + data2 = Data("Data2"); + CHECK(data1 != data2); + CHECK(data2 != data1); + + data1 = Data("Data1"); + data2 = Data("Data1"); + CHECK(!(data1 != data2)); + CHECK(!(data2 != data1)); + + data1 = Data("Data1"); + data2 = Data("Data2"); + CHECK(data1 != data2); + CHECK(data2 != data1); + + CHECK(etl::nullopt != data2); + CHECK(data1 != etl::nullopt); + + CHECK(!(data1 != Data("Data1"))); + CHECK(data1 != Data("Data2")); + CHECK(!(Data("Data1") != data1)); + CHECK(Data("Data2") != data1); } //************************************************************************* @@ -140,22 +187,130 @@ namespace etl::optional data1; etl::optional data2; + CHECK(!(data2 < data1)); CHECK(!(data1 < data2)); data1 = Data("Data1"); CHECK(!(data1 < data2)); + CHECK(data2 < data1); data1 = etl::nullopt; data2 = Data("Data2"); CHECK(data1 < data2); + CHECK(!(data2 < data2)); data1 = Data("Data1"); data2 = Data("Data2"); CHECK(data1 < data2); CHECK(!(data2 < data1)); + CHECK(etl::nullopt < data2); + CHECK(!(data1 < etl::nullopt)); + CHECK(data1 < Data("Data2")); CHECK(!(data1 < Data("Data1"))); + CHECK(!(Data("Data2") < data1)); + CHECK(Data("Data1") < data2); + } + + //************************************************************************* + TEST(test_less_than_equal) + { + etl::optional data1; + etl::optional data2; + + CHECK(data1 <= data2); + CHECK(data2 <= data1); + + data1 = Data("Data1"); + CHECK(!(data1 <= data2)); + CHECK(data2 <= data1); + + data1 = etl::nullopt; + data2 = Data("Data2"); + CHECK(data1 <= data2); + CHECK(!(data2 <= data1)); + + data1 = Data("Data1"); + data2 = Data("Data2"); + CHECK(data1 <= data2); + CHECK(!(data2 <= data1)); + + CHECK(etl::nullopt <= data2); + CHECK(!(data1 <= etl::nullopt)); + + CHECK(data1 <= Data("Data2")); + CHECK(!(data2 <= Data("Data1"))); + CHECK(data1 <= Data("Data1")); + CHECK(!(Data("Data2") <= data1)); + CHECK(Data("Data1") <= data2); + CHECK(Data("Data1") <= data1); + } + + //************************************************************************* + TEST(test_greater_than) + { + etl::optional data1; + etl::optional data2; + + CHECK(!(data1 > data2)); + CHECK(!(data2 > data1)); + + data1 = Data("Data1"); + CHECK(data1 > data2); + CHECK(!(data2 > data1)); + + data1 = etl::nullopt; + data2 = Data("Data2"); + CHECK(!(data1 > data2)); + CHECK(data2 > data1); + + data1 = Data("Data1"); + data2 = Data("Data2"); + CHECK(data2 > data1); + CHECK(!(data1 > data2)); + + CHECK(!(etl::nullopt > data2)); + CHECK(data1 > etl::nullopt); + + CHECK(!(data1 > Data("Data2"))); + CHECK(data2 > Data("Data1")); + CHECK(Data("Data2") > data1); + CHECK(!(Data("Data1") > data2)); + } + + //************************************************************************* + TEST(test_greater_than_equal) + { + etl::optional data1; + etl::optional data2; + + CHECK(data1 >= data2); + CHECK(data2 >= data1); + + data1 = Data("Data1"); + CHECK(data1 >= data2); + CHECK(!(data2 >= data1)); + + data1 = etl::nullopt; + data2 = Data("Data2"); + CHECK(!(data1 >= data2)); + CHECK(data2 >= data1); + + data1 = Data("Data1"); + data2 = Data("Data2"); + CHECK(!(data1 >= data2)); + CHECK(data2 >= data1); + + CHECK(!(etl::nullopt >= data2)); + CHECK(data1 >= etl::nullopt); + + CHECK(!(data1 >= Data("Data2"))); + CHECK(data2 >= Data("Data1")); + CHECK(data1 >= Data("Data1")); + CHECK(Data("Data2") >= data1); + CHECK(!(Data("Data1") >= data2)); + CHECK(Data("Data1") >= data1); } //************************************************************************* From 1e34b5cf46b7a1c907380d5a6aee678b33d2d066 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 25 Feb 2018 13:41:40 +0000 Subject: [PATCH 47/50] Add #ifdef for GCC pragma --- test/murmurhash3.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/murmurhash3.cpp b/test/murmurhash3.cpp index ba4f1443..39663531 100644 --- a/test/murmurhash3.cpp +++ b/test/murmurhash3.cpp @@ -7,7 +7,11 @@ // compile and run any of them on any platform, but your performance with the // non-native version will be less than optimal. -#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#include "platform.h" + +#ifdef ETL_COMPILER_GCC + #pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#endif #include "murmurhash3.h" From 2872075b1ea94dcd03024ddf77790521249aff18 Mon Sep 17 00:00:00 2001 From: Prasenjit Sengupta Date: Sun, 25 Feb 2018 16:37:13 -0800 Subject: [PATCH 48/50] Remove unused variables in variant.h --- src/variant.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/variant.h b/src/variant.h index 61d8c892..25dcdaba 100644 --- a/src/variant.h +++ b/src/variant.h @@ -643,12 +643,12 @@ namespace etl { public: - TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) + TBase& operator()(uint_least8_t* p_data) { return reinterpret_cast(*p_data); } - const TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) const + const TBase& operator()(uint_least8_t* p_data) const { return reinterpret_cast(*p_data); } From a58d1f58617ce23b286b35c7067a4fd911a124fb Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 26 Feb 2018 21:03:22 +0000 Subject: [PATCH 49/50] Remove variant.h GCC warnings from use of -Wextra --- library.properties | 2 +- src/variant.h | 16 +- support/Release notes.txt | 4 + test/codeblocks/ETL.layout | 1079 ++++++++++++++++++------------------ 4 files changed, 557 insertions(+), 544 deletions(-) diff --git a/library.properties b/library.properties index 6da68f3d..b7dbe69a 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=10.21.0 +version=10.21.1 author= John Wellbelove maintainer=John Wellbelove sentence=A C++ template library tailored for embedded systems. diff --git a/src/variant.h b/src/variant.h index 25dcdaba..429ad708 100644 --- a/src/variant.h +++ b/src/variant.h @@ -643,14 +643,22 @@ namespace etl { public: - TBase& operator()(uint_least8_t* p_data) + TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) { - return reinterpret_cast(*p_data); + switch (typeId) + { + case 0: return reinterpret_cast(*p_data); + default: return reinterpret_cast(*reinterpret_cast(0)); + } } - const TBase& operator()(uint_least8_t* p_data) const + const TBase& operator()(uint_least8_t* p_data, uint_least8_t typeId) const { - return reinterpret_cast(*p_data); + switch (typeId) + { + case 0: return reinterpret_cast(*p_data); + default: return reinterpret_cast(*reinterpret_cast(0)); + } } }; diff --git a/support/Release notes.txt b/support/Release notes.txt index 2dd20638..4e3ecc79 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,7 @@ +=============================================================================== +10.21.1 +Removal of GCC warnings from variant.h. + =============================================================================== 10.21.0 Completion of operator set for etl::optional diff --git a/test/codeblocks/ETL.layout b/test/codeblocks/ETL.layout index 1306d367..1d941bce 100644 --- a/test/codeblocks/ETL.layout +++ b/test/codeblocks/ETL.layout @@ -1,584 +1,585 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From eee015737241b8fab117ff00e494f90587a72bd5 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 1 Mar 2018 09:14:11 +0000 Subject: [PATCH 50/50] Added version macros --- library.properties | 2 +- src/version.h | 46 ++ support/Release notes.txt | 4 + test/codeblocks/ETL.cbp | 1 + test/codeblocks/ETL.layout | 870 ++++++++++++++++---------------- test/vs2017/etl.vcxproj | 1 + test/vs2017/etl.vcxproj.filters | 3 + 7 files changed, 491 insertions(+), 436 deletions(-) create mode 100644 src/version.h diff --git a/library.properties b/library.properties index b7dbe69a..c9913f89 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library -version=10.21.1 +version=10.21.2 author= John Wellbelove maintainer=John Wellbelove sentence=A C++ template library tailored for embedded systems. diff --git a/src/version.h b/src/version.h new file mode 100644 index 00000000..70f29896 --- /dev/null +++ b/src/version.h @@ -0,0 +1,46 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2018 jwellbelove + +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_VERSION__ +#define __ETL_VERSION__ + +#include + +///\defgroup version version +/// Definitions of the ETL version +///\ingroup utilities + +#define ETL_VERSION "10.21.2" +#define ETL_VERSION_MAJOR 10 +#define ETL_VERSION_MINOR 21 +#define ETL_VERSION_PATCH 2 + +#endif + diff --git a/support/Release notes.txt b/support/Release notes.txt index 4e3ecc79..8b7238fd 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,7 @@ +=============================================================================== +10.21.2 +Added version.h + =============================================================================== 10.21.1 Removal of GCC warnings from variant.h. diff --git a/test/codeblocks/ETL.cbp b/test/codeblocks/ETL.cbp index 279a97cf..9857c6e7 100644 --- a/test/codeblocks/ETL.cbp +++ b/test/codeblocks/ETL.cbp @@ -208,6 +208,7 @@ + diff --git a/test/codeblocks/ETL.layout b/test/codeblocks/ETL.layout index 1d941bce..ccf9f11d 100644 --- a/test/codeblocks/ETL.layout +++ b/test/codeblocks/ETL.layout @@ -2,159 +2,14 @@ - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -162,109 +17,39 @@ + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - + @@ -272,14 +57,94 @@ - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -287,9 +152,129 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -302,14 +287,9 @@ - + - - - - - - + @@ -317,159 +297,19 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -477,9 +317,44 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -487,39 +362,19 @@ - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - + @@ -527,14 +382,9 @@ - + - - - - - - + @@ -542,14 +392,134 @@ - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -557,29 +527,59 @@ + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + diff --git a/test/vs2017/etl.vcxproj b/test/vs2017/etl.vcxproj index 46b66b98..5e1be754 100644 --- a/test/vs2017/etl.vcxproj +++ b/test/vs2017/etl.vcxproj @@ -172,6 +172,7 @@ + diff --git a/test/vs2017/etl.vcxproj.filters b/test/vs2017/etl.vcxproj.filters index 77db216e..4f5dbef1 100644 --- a/test/vs2017/etl.vcxproj.filters +++ b/test/vs2017/etl.vcxproj.filters @@ -576,6 +576,9 @@ ETL\Containers\Generators + + ETL\Utilities +