diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3ea9b73 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +src/etl/.vscode/settings.json diff --git a/README.md b/README.md index 8451a39..229357e 100644 --- a/README.md +++ b/README.md @@ -1 +1 @@ -# etl-arduino \ No newline at end of file +Embedded Template Library (ETL) ------------------------- ![GitHub release (latest by date)](https://img.shields.io/github/v/release/jwellbelove/etl-arduino) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT) ![CI](https://github.com/ETLCPP/etl/workflows/vs2019/badge.svg) ![CI](https://github.com/ETLCPP/etl/workflows/gcc/badge.svg) ![CI](https://github.com/ETLCPP/etl/workflows/clang/badge.svg) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/3c14cd918ccf40008d0bcd7b083d5946)](https://www.codacy.com/manual/jwellbelove/etl?utm_source=github.com&utm_medium=referral&utm_content=ETLCPP/etl&utm_campaign=Badge_Grade) **This repository is an Arduino compatible clone of the Embedded Template Library (ETL)** https://github.com/ETLCPP/etl See (https://www.etlcpp.com/arduino) for up-to-date information. \ No newline at end of file diff --git a/library.properties b/library.properties new file mode 100644 index 0000000..511d8ad --- /dev/null +++ b/library.properties @@ -0,0 +1,10 @@ +name=Embedded Template Library (ETL) +version=19.3.5 +author= John Wellbelove +maintainer=John Wellbelove +license=MIT +sentence=ETL. A C++ template library tailored for embedded systems. +paragraph= +category=Other +url=https://www.etlcpp.com/ +architectures=* diff --git a/src/Embedded_Template_Library.h b/src/Embedded_Template_Library.h new file mode 100644 index 0000000..df5fdcf --- /dev/null +++ b/src/Embedded_Template_Library.h @@ -0,0 +1,80 @@ + +#ifndef ETL_EMBEDDED_TEMPLATE_LIBRARY_INCLUDED +#define ETL_EMBEDDED_TEMPLATE_LIBRARY_INCLUDED + +#if defined(TEENSYDUINO) + + #if defined(__AVR_ATmega32U4__) + #define ARDUINO_BOARD "Teensy 2.0" + #elif defined(__AVR_AT90USB1286__) + #define ARDUINO_BOARD "Teensy++ 2.0" + #elif defined(__MK20DX128__) + #define ARDUINO_BOARD "Teensy 3.0" + #elif defined(__MK20DX256__) + #define ARDUINO_BOARD "Teensy 3.2" // and Teensy 3.1 + #elif defined(__MKL26Z64__) + #define ARDUINO_BOARD "Teensy LC" + #elif defined(__MK64FX512__) + #define ARDUINO_BOARD "Teensy 3.5" + #elif defined(__MK66FX1M0__) + #define ARDUINO_BOARD "Teensy 3.6" + #else + #error "Unknown" + #endif + +#else // --------------- Arduino ------------------ + + #if defined(ARDUINO_AVR_ADK) + #define ARDUINO_BOARD "Mega Adk" + #elif defined(ARDUINO_AVR_BT) + #define ARDUINO_BOARD "Bt" + #elif defined(ARDUINO_AVR_DUEMILANOVE) + #define ARDUINO_BOARD "Duemilanove" + #elif defined(ARDUINO_AVR_ESPLORA) + #define ARDUINO_BOARD "Esplora" + #elif defined(ARDUINO_AVR_ETHERNET) + #define ARDUINO_BOARD "Ethernet" + #elif defined(ARDUINO_AVR_FIO) + #define ARDUINO_BOARD "Fio" + #elif defined(ARDUINO_AVR_GEMMA) + #define ARDUINO_BOARD "Gemma" + #elif defined(ARDUINO_AVR_LEONARDO) + #define ARDUINO_BOARD "Leonardo" + #elif defined(ARDUINO_AVR_LILYPAD) + #define ARDUINO_BOARD "Lilypad" + #elif defined(ARDUINO_AVR_LILYPAD_USB) + #define ARDUINO_BOARD "Lilypad Usb" + #elif defined(ARDUINO_AVR_MEGA) + #define ARDUINO_BOARD "Mega" + #elif defined(ARDUINO_AVR_MEGA2560) + #define ARDUINO_BOARD "Mega 2560" + #elif defined(ARDUINO_AVR_MICRO) + #define ARDUINO_BOARD "Micro" + #elif defined(ARDUINO_AVR_MINI) + #define ARDUINO_BOARD "Mini" + #elif defined(ARDUINO_AVR_NANO) + #define ARDUINO_BOARD "Nano" + #elif defined(ARDUINO_AVR_NG) + #define ARDUINO_BOARD "NG" + #elif defined(ARDUINO_AVR_PRO) + #define ARDUINO_BOARD "Pro" + #elif defined(ARDUINO_AVR_ROBOT_CONTROL) + #define ARDUINO_BOARD "Robot Ctrl" + #elif defined(ARDUINO_AVR_ROBOT_MOTOR) + #define ARDUINO_BOARD "Robot Motor" + #elif defined(ARDUINO_AVR_UNO) + #define ARDUINO_BOARD "Uno" + #elif defined(ARDUINO_AVR_YUN) + #define ARDUINO_BOARD "Yun" + #elif defined(ARDUINO_SAM_DUE) + #define ARDUINO_BOARD "Due" + #elif defined(ARDUINO_SAMD_ZERO) + #define ARDUINO_BOARD "Zero" + #elif defined(ARDUINO_ARC32_TOOLS) + #define ARDUINO_BOARD "101" + #else + #error "Unknown" + #endif +#endif + +#endif \ No newline at end of file diff --git a/src/etl/absolute.h b/src/etl/absolute.h new file mode 100644 index 0000000..d473b3e --- /dev/null +++ b/src/etl/absolute.h @@ -0,0 +1,60 @@ +///\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_ABSOLUTE_INCLUDED +#define ETL_ABSOLUTE_INCLUDED + +#include "type_traits.h" + +namespace etl +{ + //*************************************************************************** + // For signed types. + //*************************************************************************** + template + ETL_CONSTEXPR typename etl::enable_if::value, T>::type + absolute(T value) + { + return (value < T(0)) ? -value : value; + } + + //*************************************************************************** + // For unsigned types. + //*************************************************************************** + template + ETL_CONSTEXPR typename etl::enable_if::value, T>::type + absolute(T value) + { + return value; + } +} + +#endif + diff --git a/src/etl/algorithm.h b/src/etl/algorithm.h new file mode 100644 index 0000000..b01f90d --- /dev/null +++ b/src/etl/algorithm.h @@ -0,0 +1,3424 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2014 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_ALGORITHM_INCLUDED +#define ETL_ALGORITHM_INCLUDED + +///\defgroup algorithm algorithm +/// Including reverse engineered algorithms from C++ 0x11, 0x14, 0x17 +/// Additional new variants of certain algorithms. +///\ingroup utilities + +#include +#include + +#include "platform.h" +#include "type_traits.h" +#include "container.h" +#include "iterator.h" +#include "functional.h" +#include "utility.h" + +#if ETL_USING_STL + #include + #include + #include + #include +#endif + +#include "private/minmax_push.h" + +namespace etl +{ + // Declare prototypes of the ETL's sort functions + template + void shell_sort(TIterator first, TIterator last); + + template + void shell_sort(TIterator first, TIterator last, TCompare compare); + + template + void insertion_sort(TIterator first, TIterator last); + + template + void insertion_sort(TIterator first, TIterator last, TCompare compare); +} + +//***************************************************************************** +// Algorithms defined by the ETL +//***************************************************************************** +namespace etl +{ +#if ETL_NOT_USING_STL + //*************************************************************************** + // iter_swap + template + void iter_swap(TIterator1 a, TIterator2 b) + { + using ETL_OR_STD::swap; // Allow ADL + swap(*a, *b); + } +#else + //*************************************************************************** + // iter_swap + template + void iter_swap(TIterator1 a, TIterator2 b) + { + std::iter_swap(a, b); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // swap_ranges + template + TIterator2 swap_ranges(T1terator1 first1, + T1terator1 last1, + TIterator2 first2) + { + while (first1 != last1) + { + iter_swap(first1++, first2++); + } + + return first2; + } +#else + //*************************************************************************** + // swap_ranges + template + TIterator2 swap_ranges(T1terator1 first1, + T1terator1 last1, + TIterator2 first2) + { + return std::swap_ranges(first1, last1, first2); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // copy + // Pointer + template + typename etl::enable_if::value && + etl::is_pointer::value && + etl::is_trivially_copyable::value_type>::value, TIterator2>::type + copy(TIterator1 sb, TIterator1 se, TIterator2 db) + { + typedef typename etl::iterator_traits::value_type value_t; + typedef typename etl::iterator_traits::difference_type difference_t; + + difference_t count = (se - sb); + + return TIterator2(memmove(db, sb, sizeof(value_t) * count)) + count; + } + + // Other iterator + template + typename etl::enable_if::value || + !etl::is_pointer::value || + !etl::is_trivially_copyable::value_type>::value, TIterator2>::type + copy(TIterator1 sb, TIterator1 se, TIterator2 db) + { + while (sb != se) + { + *db++ = *sb++; + } + + return db; + } +#else + //*************************************************************************** + // copy + template + TIterator2 copy(TIterator1 sb, TIterator1 se, TIterator2 db) + { + return std::copy(sb, se, db); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // reverse_copy + template + TIterator2 reverse_copy(TIterator1 sb, TIterator1 se, TIterator2 db) + { + while (sb != se) + { + *(db++) = *(--se); + } + + return db; + } +#else + //*************************************************************************** + // reverse_copy + template + TIterator2 reverse_copy(TIterator1 sb, TIterator1 se, TIterator2 db) + { + return std::reverse_copy(sb, se, db); + } +#endif + +#if ETL_NOT_USING_STL || ETL_CPP11_NOT_SUPPORTED + //*************************************************************************** + // copy_n + // Pointer + template + typename etl::enable_if::value && + etl::is_pointer::value && + etl::is_trivially_copyable::value_type>::value, TIterator2>::type + copy_n(TIterator1 sb, TSize count, TIterator2 db) + { + typedef typename etl::iterator_traits::value_type value_t; + + return TIterator2(memmove(db, sb, sizeof(value_t) * count)) + count; + } + + // Other iterator + template + typename etl::enable_if::value || + !etl::is_pointer::value || + !etl::is_trivially_copyable::value_type>::value, TIterator2>::type + copy_n(TIterator1 sb, TSize count, TIterator2 db) + { + while (count != 0) + { + *db++ = *sb++; + --count; + } + + return db; + } +#else + //*************************************************************************** + /// copy_n + ///\ingroup algorithm + /// + //*************************************************************************** + template + TOutputIterator copy_n(TInputIterator i_begin, + TSize n, + TOutputIterator o_begin) + { + return std::copy_n(i_begin, n, o_begin); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // copy_backward + // Pointer + template + typename etl::enable_if::value && + etl::is_pointer::value && + etl::is_trivially_copyable::value_type>::value, TIterator2>::type + copy_backward(TIterator1 sb, TIterator1 se, TIterator2 de) + { + typedef typename etl::iterator_traits::value_type value_t; + + const size_t length = (se - sb); + + return TIterator2(memmove(de - length, sb, sizeof(value_t) * length)); + } + + // Other iterator + template + typename etl::enable_if::value || + !etl::is_pointer::value || + !etl::is_trivially_copyable::value_type>::value, TIterator2>::type + copy_backward(TIterator1 sb, TIterator1 se, TIterator2 de) + { + while (se != sb) + { + *(--de) = *(--se); + } + + return de; + } +#else + //*************************************************************************** + // copy_backward + template + TIterator2 copy_backward(TIterator1 sb, TIterator1 se, TIterator2 de) + { + return std::copy_backward(sb, se, de); + } +#endif + +#if ETL_CPP11_SUPPORTED +#if ETL_NOT_USING_STL + //*************************************************************************** + // move + // non-pointer or not trivially copyable + template + typename etl::enable_if::value || + !etl::is_pointer::value || + !etl::is_trivially_copyable::value_type>::value, TIterator2>::type + move(TIterator1 sb, TIterator1 se, TIterator2 db) + { + while (sb != se) + { + *db++ = etl::move(*sb++); + } + + return db; + } + + // pointer and trivially copyable + template + typename etl::enable_if::value && + etl::is_pointer::value && + etl::is_trivially_copyable::value_type>::value, TIterator2>::type + move(TIterator1 sb, TIterator1 se, TIterator2 db) + { + typedef typename etl::iterator_traits::value_type value_t; + typedef typename etl::iterator_traits::difference_type difference_t; + + difference_t count = (se - sb); + + return TIterator2(memmove(db, sb, sizeof(value_t) * count)) + count; + } +#else + //*************************************************************************** + // move + template + TIterator2 move(TIterator1 sb, TIterator1 se, TIterator2 db) + { + return std::move(sb, se, db); + } +#endif +#else + // C++03 + //*************************************************************************** + // move + template + TIterator2 move(TIterator1 sb, TIterator1 se, TIterator2 db) + { + // Move not supported. Defer to copy. + return etl::copy(sb, se, db); + } +#endif + +#if ETL_CPP11_SUPPORTED +#if ETL_NOT_USING_STL + //*************************************************************************** + // move_backward + // non-pointer, non-pod + template + typename etl::enable_if::value || + !etl::is_pointer::value || + !etl::is_trivially_copyable::value_type>::value, TIterator2>::type + move_backward(TIterator1 sb, TIterator1 se, TIterator2 de) + { + while (sb != se) + { + *(--de) = etl::move(*(--se)); + } + + return de; + } + + // pointer and pod + template + typename etl::enable_if::value && + etl::is_pointer::value && + etl::is_trivially_copyable::value_type>::value, TIterator2>::type + move_backward(TIterator1 sb, TIterator1 se, TIterator2 de) + { + typedef typename etl::iterator_traits::value_type value_t; + typedef typename etl::iterator_traits::difference_type difference_t; + + difference_t count = (se - sb); + TIterator2 db = de - count; + + return TIterator2(memmove(db, sb, sizeof(value_t) * count)) + count; + } +#else + //*************************************************************************** + // move_backward + template + TIterator2 move_backward(TIterator1 sb, TIterator1 se, TIterator2 de) + { + return std::move_backward(sb, se, de); + } +#endif +#else + //*************************************************************************** + // move_backward + template + TIterator2 move_backward(TIterator1 sb, TIterator1 se, TIterator2 de) + { + // Move not supported. Defer to copy_backward. + return ETL_OR_STD::copy_backward(sb, se, de); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // reverse + // Pointers + template + typename etl::enable_if::value, void>::type + reverse(TIterator b, TIterator e) + { + if (b != e) + { + while (b < --e) + { + etl::iter_swap(b, e); + ++b; + } + } + } + + // Other + template + typename etl::enable_if::value, void>::type + reverse(TIterator b, TIterator e) + { + while ((b != e) && (b != --e)) + { + etl::iter_swap(b++, e); + } + } +#else + //*************************************************************************** + // reverse + template + void reverse(TIterator b, TIterator e) + { + std::reverse(b, e); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // lower_bound + template + ETL_NODISCARD + TIterator lower_bound(TIterator first, TIterator last, const TValue& value, TCompare compare) + { + typedef typename etl::iterator_traits::difference_type difference_t; + + difference_t count = etl::distance(first, last); + + while (count > 0) + { + TIterator itr = first; + difference_t step = count / 2; + + etl::advance(itr, step); + + if (compare(*itr, value)) + { + first = ++itr; + count -= step + 1; + } + else + { + count = step; + } + } + + return first; + } + + template + ETL_NODISCARD + TIterator lower_bound(TIterator first, TIterator last, const TValue& value) + { + typedef etl::less::value_type> compare; + + return etl::lower_bound(first, last, value, compare()); + } +#else + //*************************************************************************** + // lower_bound + template + ETL_NODISCARD + TIterator lower_bound(TIterator first, TIterator last, const TValue& value, TCompare compare) + { + return std::lower_bound(first, last, value, compare); + } + + template + ETL_NODISCARD + TIterator lower_bound(TIterator first, TIterator last, const TValue& value) + { + return std::lower_bound(first, last, value); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // upper_bound + template + ETL_NODISCARD + TIterator upper_bound(TIterator first, TIterator last, const TValue& value, TCompare compare) + { + typedef typename etl::iterator_traits::difference_type difference_t; + + difference_t count = etl::distance(first, last); + + while (count > 0) + { + TIterator itr = first; + difference_t step = count / 2; + + etl::advance(itr, step); + + if (!compare(value, *itr)) + { + first = ++itr; + count -= step + 1; + } + else + { + count = step; + } + } + + return first; + } + + template + ETL_NODISCARD + TIterator upper_bound(TIterator first, TIterator last, const TValue& value) + { + typedef etl::less::value_type> compare; + + return etl::upper_bound(first, last, value, compare()); + } +#else + //*************************************************************************** + // upper_bound + template + ETL_NODISCARD + TIterator upper_bound(TIterator first, TIterator last, const TValue& value, TCompare compare) + { + return std::upper_bound(first, last, value, compare); + } + + template + ETL_NODISCARD + TIterator upper_bound(TIterator first, TIterator last, const TValue& value) + { + return std::upper_bound(first, last, value); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // equal_range + template + ETL_NODISCARD + ETL_OR_STD::pair equal_range(TIterator first, TIterator last, const TValue& value, TCompare compare) + { + return ETL_OR_STD::make_pair(etl::lower_bound(first, last, value, compare), + etl::upper_bound(first, last, value, compare)); + } + + template + ETL_NODISCARD + ETL_OR_STD::pair equal_range(TIterator first, TIterator last, const TValue& value) + { + typedef etl::less::value_type> compare; + + return ETL_OR_STD::make_pair(etl::lower_bound(first, last, value, compare()), + etl::upper_bound(first, last, value, compare())); + } +#else + //*************************************************************************** + // equal_range + template + ETL_NODISCARD + std::pair equal_range(TIterator first, TIterator last, const TValue& value, TCompare compare) + { + return std::equal_range(first, last, value, compare); + } + + template + ETL_NODISCARD + std::pair equal_range(TIterator first, TIterator last, const TValue& value) + { + return std::equal_range(first, last, value); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // find_if + template + ETL_NODISCARD + TIterator find_if(TIterator first, TIterator last, TUnaryPredicate predicate) + { + while (first != last) + { + if (predicate(*first)) + { + return first; + } + + ++first; + } + + return last; + } +#else + //*************************************************************************** + // find_if + template + ETL_NODISCARD + TIterator find_if(TIterator first, TIterator last, TUnaryPredicate predicate) + { + return std::find_if(first, last, predicate); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // find + template + ETL_NODISCARD + TIterator find(TIterator first, TIterator last, const T& value) + { + while (first != last) + { + if (*first == value) + { + return first; + } + + ++first; + } + + return last; + } +#else + //*************************************************************************** + // find + template + ETL_NODISCARD + TIterator find(TIterator first, TIterator last, const T& value) + { + return std::find(first, last, value); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // fill + template + typename etl::enable_if::value || etl::is_same::value) || !etl::is_pointer::value, void>::type + fill(TIterator first, TIterator last, const TValue& value) + { + while (first != last) + { + *first++ = value; + } + } + + template + typename etl::enable_if<(etl::is_same::value || etl::is_same::value) && etl::is_pointer::value, void>::type + fill(TIterator first, TIterator last, const TValue& value) + { + memset(first, value, last - first); + } +#else + //*************************************************************************** + // fill + template + void fill(TIterator first, TIterator last, const TValue& value) + { + std::fill(first, last, value); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // fill_n + template + typename etl::enable_if::value || etl::is_same::value) || !etl::is_pointer::value, TIterator>::type + fill_n(TIterator first, TSize count, const TValue& value) + { + for (TSize i = 0; i < count; ++i) + { + *first++ = value; + } + + return first; + } + + template + typename etl::enable_if<(etl::is_same::value || etl::is_same::value) && etl::is_pointer::value, void>::type + fill_n(TIterator first, TSize count, const TValue& value) + { + memset(first, value, count); + } +#else + //*************************************************************************** + // fill_n + template + TIterator fill_n(TIterator first, TSize count, const TValue& value) + { +#if ETL_CPP11_SUPPORTED + return std::fill_n(first, count, value); +#else + std::fill_n(first, count, value); + std::advance(first, count); + return first; +#endif + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // count + template + ETL_NODISCARD + typename etl::iterator_traits::difference_type count(TIterator first, TIterator last, const T& value) + { + typename iterator_traits::difference_type n = 0; + + while (first != last) + { + if (*first == value) + { + ++n; + } + + ++first; + } + + return n; + } +#else + //*************************************************************************** + // count + template + ETL_NODISCARD + typename std::iterator_traits::difference_type count(TIterator first, TIterator last, const T& value) + { + return std::count(first, last, value); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // count_if + template + ETL_NODISCARD + typename etl::iterator_traits::difference_type count_if(TIterator first, TIterator last, TUnaryPredicate predicate) + { + typename iterator_traits::difference_type n = 0; + + while (first != last) + { + if (predicate(*first)) + { + ++n; + } + + ++first; + } + + return n; + } +#else + //*************************************************************************** + // count_if + template + ETL_NODISCARD + typename std::iterator_traits::difference_type count_if(TIterator first, TIterator last, TUnaryPredicate predicate) + { + return std::count_if(first, last, predicate); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // equal + template + ETL_NODISCARD + typename etl::enable_if::value || !etl::is_pointer::value || !etl::is_trivially_copyable::value_type>::value, bool>::type + equal(TIterator1 first1, TIterator1 last1, TIterator2 first2) + { + while (first1 != last1) + { + if (*first1++ != *first2++) + { + return false; + } + } + + return true; + } + + template + ETL_NODISCARD + typename etl::enable_if::value && etl::is_pointer::value && etl::is_trivially_copyable::value_type>::value, bool>::type + equal(TIterator1 first1, TIterator1 last1, TIterator2 first2) + { + typedef typename etl::iterator_traits::value_type value_t; + + return (memcmp(first1, first2, sizeof(value_t) * (last1 - first1)) == 0); + } + + template + ETL_NODISCARD + bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2, TIterator2 last2) + { + return (etl::distance(first1, last1) == etl::distance(first2, last2)) && + etl::equal(first1, last1, first2); + } + +#else + //*************************************************************************** + // equal + template + ETL_NODISCARD + bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2) + { + return std::equal(first1, last1, first2); + } + +#if ETL_CPP14_SUPPORTED + template + ETL_NODISCARD + bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2, TIterator2 last2) + { + return std::equal(first1, last1, first2, last2); + } +#else + template + ETL_NODISCARD + bool equal(TIterator1 first1, TIterator1 last1, TIterator2 first2, TIterator2 last2) + { + return (etl::distance(first1, last1) == etl::distance(first2, last2)) && + etl::equal(first1, last1, first2); + } +#endif +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // lexicographical_compare + template + ETL_NODISCARD + bool lexicographical_compare(TIterator1 first1, TIterator1 last1, + TIterator2 first2, TIterator2 last2, + TCompare compare) + { + while ((first1 != last1) && (first2 != last2)) + { + if (compare(*first1, *first2)) + { + return true; + } + + if (compare(*first2, *first1)) + { + return false; + } + + ++first1; + ++first2; + } + + return (first1 == last1) && (first2 != last2); + } + + //*************************************************************************** + // lexicographical_compare + template + ETL_NODISCARD + bool lexicographical_compare(TIterator1 first1, TIterator1 last1, + TIterator2 first2, TIterator2 last2) + { + typedef etl::less::value_type> compare; + + return etl::lexicographical_compare(first1, last1, first2, last2, compare()); + } +#else + //*************************************************************************** + // lexicographical_compare + template + ETL_NODISCARD + bool lexicographical_compare(TIterator1 first1, TIterator1 last1, + TIterator2 first2, TIterator2 last2, + TCompare compare) + { + return std::lexicographical_compare(first1, last1, first2, last2, compare); + } + + //*************************************************************************** + // lexicographical_compare + template + ETL_NODISCARD + bool lexicographical_compare(TIterator1 first1, TIterator1 last1, + TIterator2 first2, TIterator2 last2) + { + return std::lexicographical_compare(first1, last1, first2, last2); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // min + template + ETL_NODISCARD + ETL_CONSTEXPR const T& min(const T& a, const T& b, TCompare compare) + { + return (compare(a, b)) ? a : b; + } + + template + ETL_NODISCARD + ETL_CONSTEXPR const T& min(const T& a, const T& b) + { + typedef etl::less compare; + + return etl::min(a, b, compare()); + } +#else + //*************************************************************************** + // min + template + ETL_NODISCARD + ETL_CONSTEXPR const T& min(const T& a, const T& b, TCompare compare) + { + return std::min(a, b, compare); + } + + template + ETL_NODISCARD + ETL_CONSTEXPR const T& min(const T& a, const T& b) + { + return std::min(a, b); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // max + template + ETL_NODISCARD + ETL_CONSTEXPR const T& max(const T& a, const T& b, TCompare compare) + { + return (compare(a, b)) ? b : a; + } + + template + ETL_NODISCARD + ETL_CONSTEXPR const T& max(const T& a, const T& b) + { + typedef etl::less compare; + + return etl::max(a, b, compare()); + } +#else + //*************************************************************************** + // max + template + ETL_NODISCARD + ETL_CONSTEXPR const T& max(const T& a, const T& b, TCompare compare) + { + return std::max(a, b, compare); + } + + template + ETL_NODISCARD + ETL_CONSTEXPR const T& max(const T& a, const T& b) + { + return std::max(a, b); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // transform + template + TIteratorOut transform(TIteratorIn first1, TIteratorIn last1, TIteratorOut d_first, TUnaryOperation unary_operation) + { + while (first1 != last1) + { + *d_first++ = unary_operation(*first1++); + } + + return d_first; + } + + template + TIteratorOut transform(TIteratorIn1 first1, TIteratorIn1 last1, TIteratorIn2 first2, TIteratorOut d_first, TBinaryOperation binary_operation) + { + while (first1 != last1) + { + *d_first++ = binary_operation(*first1++, *first2++); + } + + return d_first; + } +#else + //*************************************************************************** + // transform + template + TIteratorOut transform(TIteratorIn first1, TIteratorIn last1, TIteratorOut d_first, TUnaryOperation unary_operation) + { + return std::transform(first1, last1, d_first, unary_operation);; + } + + template + TIteratorOut transform(TIteratorIn1 first1, TIteratorIn1 last1, TIteratorIn2 first2, TIteratorOut d_first, TBinaryOperation binary_operation) + { + return std::transform(first1, last1, first2, d_first, binary_operation); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // replace + template + ETL_CONSTEXPR14 void replace(TIterator first, TIterator last, const T& old_value, const T& new_value) + { + while (first != last) + { + if (*first == old_value) + { + *first = new_value; + } + + ++first; + } + } + + //*************************************************************************** + // replace_if + template + ETL_CONSTEXPR14 void replace_if(TIterator first, TIterator last, TPredicate predicate, const T& new_value) + { + while (first != last) + { + if (predicate(*first)) + { + *first = new_value; + } + + ++first; + } + } +#else + //*************************************************************************** + // replace + template + ETL_CONSTEXPR14 void replace(TIterator first, TIterator last, const T& old_value, const T& new_value) + { + std::replace(first, last, old_value, new_value); + } + + //*************************************************************************** + // replace_if + template + ETL_CONSTEXPR14 void replace_if(TIterator first, TIterator last, TPredicate predicate, const T& new_value) + { + std::replace_if(first, last, predicate, new_value); + } +#endif + + //*************************************************************************** + // Heap + namespace private_heap + { + // Push Heap Helper + template + void push_heap(TIterator first, TDistance value_index, TDistance top_index, TValue value, TCompare compare) + { + TDistance parent = (value_index - 1) / 2; + + while ((value_index > top_index) && compare(first[parent], value)) + { + first[value_index] = etl::move(first[parent]); + value_index = parent; + parent = (value_index - 1) / 2; + } + + first[value_index] = etl::move(value); + } + + // Adjust Heap Helper + template + void adjust_heap(TIterator first, TDistance value_index, TDistance length, TValue value, TCompare compare) + { + TDistance top_index = value_index; + TDistance child2nd = (2 * value_index) + 2; + + while (child2nd < length) + { + if (compare(first[child2nd], first[child2nd - 1])) + { + --child2nd; + } + + first[value_index] = etl::move(first[child2nd]); + value_index = child2nd; + child2nd = 2 * (child2nd + 1); + } + + if (child2nd == length) + { + first[value_index] = etl::move(first[child2nd - 1]); + value_index = child2nd - 1; + } + + push_heap(first, value_index, top_index, etl::move(value), compare); + } + + // Is Heap Helper + template + bool is_heap(const TIterator first, const TDistance n, TCompare compare) + { + TDistance parent = 0; + + for (TDistance child = 1; child < n; ++child) + { + if (compare(first[parent], first[child])) + { + return false; + } + + if ((child & 1) == 0) + { + ++parent; + } + } + + return true; + } + } + + #if ETL_NOT_USING_STL + // Pop Heap + template + void pop_heap(TIterator first, TIterator last, TCompare compare) + { + typedef typename etl::iterator_traits::value_type value_t; + typedef typename etl::iterator_traits::difference_type distance_t; + + value_t value = etl::move(last[-1]); + last[-1] = etl::move(first[0]); + + private_heap::adjust_heap(first, distance_t(0), distance_t(last - first - 1), etl::move(value), compare); + } + + // Pop Heap + template + void pop_heap(TIterator first, TIterator last) + { + typedef etl::less::value_type> compare; + + etl::pop_heap(first, last, compare()); + } + + // Push Heap + template + void push_heap(TIterator first, TIterator last, TCompare compare) + { + typedef typename etl::iterator_traits::difference_type difference_t; + typedef typename etl::iterator_traits::value_type value_t; + + private_heap::push_heap(first, difference_t(last - first - 1), difference_t(0), value_t(etl::move(*(last - 1))), compare); + } + + // Push Heap + template + void push_heap(TIterator first, TIterator last) + { + typedef etl::less::value_type> compare; + + etl::push_heap(first, last, compare()); + } + + // Make Heap + template + void make_heap(TIterator first, TIterator last, TCompare compare) + { + typedef typename etl::iterator_traits::difference_type difference_t; + + if ((last - first) < 2) + { + return; + } + + difference_t length = last - first; + difference_t parent = (length - 2) / 2; + + while (true) + { + private_heap::adjust_heap(first, parent, length, etl::move(*(first + parent)), compare); + + if (parent == 0) + { + return; + } + + --parent; + } + } + + // Make Heap + template + void make_heap(TIterator first, TIterator last) + { + typedef etl::less::value_type> compare; + + etl::make_heap(first, last, compare()); + } + + // Is Heap + template + ETL_NODISCARD + bool is_heap(TIterator first, TIterator last) + { + typedef etl::less::value_type> compare; + + return private_heap::is_heap(first, last - first, compare()); + } + + // Is Heap + template + ETL_NODISCARD + bool is_heap(TIterator first, TIterator last, TCompare compare) + { + return private_heap::is_heap(first, last - first, compare); + } + + // Sort Heap + template + void sort_heap(TIterator first, TIterator last) + { + while (first != last) + { + etl::pop_heap(first, last--); + } + } + + // Sort Heap + template + void sort_heap(TIterator first, TIterator last, TCompare compare) + { + while (first != last) + { + etl::pop_heap(first, last--, compare); + } + } + +#else + //*************************************************************************** + // Heap + // Pop Heap + template + void pop_heap(TIterator first, TIterator last, TCompare compare) + { + std::pop_heap(first, last, compare); + } + + // Pop Heap + template + void pop_heap(TIterator first, TIterator last) + { + std::pop_heap(first, last); + } + + // Push Heap + template + void push_heap(TIterator first, TIterator last, TCompare compare) + { + std::push_heap(first, last, compare); + } + + // Push Heap + template + void push_heap(TIterator first, TIterator last) + { + std::push_heap(first, last); + } + + // Make Heap + template + void make_heap(TIterator first, TIterator last, TCompare compare) + { + std::make_heap(first, last, compare); + } + + // Make Heap + template + void make_heap(TIterator first, TIterator last) + { + std::make_heap(first, last); + } + + // Is Heap + template + ETL_NODISCARD + bool is_heap(TIterator first, TIterator last, TCompare compare) + { +#if ETL_CPP11_SUPPORTED + return std::is_heap(first, last, compare); +#else + return private_heap::is_heap(first, last - first, compare()); +#endif + } + + // Is Heap + template + ETL_NODISCARD + bool is_heap(TIterator first, TIterator last) + { +#if ETL_CPP11_SUPPORTED + return std::is_heap(first, last); +#else + typedef etl::less::value_type> compare; + return private_heap::is_heap(first, last - first, compare()); +#endif + } + + // Sort Heap + template + void sort_heap(TIterator first, TIterator last, TCompare compare) + { + std::sort_heap(first, last, compare); + } + + // Sort Heap + template + void sort_heap(TIterator first, TIterator last) + { + std::sort_heap(first, last); + } + +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // Search + template + ETL_NODISCARD + TIterator1 search(TIterator1 first, TIterator1 last, TIterator2 search_first, TIterator2 search_last, TCompare compare) + { + while (true) + { + TIterator1 itr = first; + TIterator2 search_itr = search_first; + + while (true) + { + if (search_itr == search_last) + { + return first; + } + + if (itr == last) + { + return last; + } + + if (!compare(*itr, *search_itr)) + { + break; + } + + ++itr; + ++search_itr; + } + + ++first; + } + } + + // Search + template + ETL_NODISCARD + TIterator1 search(TIterator1 first, TIterator1 last, TIterator2 search_first, TIterator2 search_last) + { + typedef etl::equal_to::value_type> compare; + + return etl::search(first, last, search_first, search_last, compare()); + } +#else + //*************************************************************************** + // Search + template + ETL_NODISCARD + TIterator1 search(TIterator1 first, TIterator1 last, TIterator2 search_first, TIterator2 search_last, TCompare compare) + { + return std::search(first, last, search_first, search_last, compare); + } + + // Search + template + ETL_NODISCARD + TIterator1 search(TIterator1 first, TIterator1 last, TIterator2 search_first, TIterator2 search_last) + { + return std::search(first, last, search_first, search_last); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // Rotate + namespace private_algorithm + { + //********************************* + template + TIterator rotate_general(TIterator first, TIterator middle, TIterator last) + { + TIterator next = middle; + + while (first != next) + { + using ETL_OR_STD::swap; // Allow ADL + + swap(*first++, *next++); + + if (next == last) + { + next = middle; + } + else if (first == middle) + { + middle = next; + } + } + + return first; + } + + //********************************* + template + TIterator rotate_left_by_one(TIterator first, TIterator last) + { + typedef typename etl::iterator_traits::value_type value_type; + + // Save the first item. + value_type temp(etl::move(*first)); + + // Move the rest. + TIterator result = etl::move(etl::next(first), last, first); + + // Restore the first item in its rotated position. + *result = etl::move(temp); + + // The new position of the first item. + return result; + } + + //********************************* + template + TIterator rotate_right_by_one(TIterator first, TIterator last) + { + typedef typename etl::iterator_traits::value_type value_type; + + // Save the last item. + TIterator previous = etl::prev(last); + value_type temp(etl::move(*previous)); + + // Move the rest. + TIterator result = etl::move_backward(first, previous, last); + + // Restore the last item in its rotated position. + *first = etl::move(temp); + + // The new position of the first item. + return result; + } + } + + //********************************* + template + TIterator rotate(TIterator first, TIterator middle, TIterator last) + { + if (etl::next(first) == middle) + { + return private_algorithm::rotate_left_by_one(first, last); + } + + if (etl::next(middle) == last) + { + return private_algorithm::rotate_right_by_one(first, last); + } + + return private_algorithm::rotate_general(first, middle, last); + } +#else + //*************************************************************************** + // Rotate + template + TIterator rotate(TIterator first, TIterator middle, TIterator last) + { + return std::rotate(first, middle, last); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + // find_end + // Predicate + template + ETL_NODISCARD + TIterator1 find_end(TIterator1 b, TIterator1 e, + TIterator2 sb, TIterator2 se, + TPredicate predicate) + { + if (sb == se) + { + return e; + } + + TIterator1 result = e; + + while (true) + { + TIterator1 new_result = etl::search(b, e, sb, se, predicate); + + if (new_result == e) + { + break; + } + else + { + result = new_result; + b = result; + ++b; + } + } + return result; + } + + // Default + template + ETL_NODISCARD + TIterator1 find_end(TIterator1 b, TIterator1 e, + TIterator2 sb, TIterator2 se) + { + typedef etl::equal_to::value_type> predicate; + + return find_end(b, e, sb, se, predicate()); + } +#else + //*************************************************************************** + // find_end + // Predicate + template + ETL_NODISCARD + TIterator1 find_end(TIterator1 b, TIterator1 e, + TIterator2 sb, TIterator2 se, + TPredicate predicate) + { + return std::find_end(b, e, sb, se, predicate); + } + + // Default + template + ETL_NODISCARD + TIterator1 find_end(TIterator1 b, TIterator1 e, + TIterator2 sb, TIterator2 se) + { + return std::find_end(b, e, sb, se); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + /// Finds the iterator to the smallest element in the range (begin, end).
+ /// + ///\ingroup algorithm + //*************************************************************************** + template + ETL_NODISCARD + TIterator min_element(TIterator begin, + TIterator end, + TCompare compare) + { + TIterator minimum = begin; + + while (begin != end) + { + if (compare(*begin, *minimum)) + { + minimum = begin; + } + + ++begin; + } + + return minimum; + } + + //*************************************************************************** + /// min_element + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + TIterator min_element(TIterator begin, + TIterator end) + { + typedef typename etl::iterator_traits::value_type value_t; + + return etl::min_element(begin, end, etl::less()); + } +#else + //*************************************************************************** + /// Finds the iterator to the smallest element in the range (begin, end).
+ /// + ///\ingroup algorithm + //*************************************************************************** + template + ETL_NODISCARD + TIterator min_element(TIterator begin, + TIterator end, + TCompare compare) + { + return std::min_element(begin, end, compare); + } + + //*************************************************************************** + /// min_element + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + TIterator min_element(TIterator begin, + TIterator end) + { + return std::min_element(begin, end); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + /// Finds the iterator to the largest element in the range (begin, end).
+ /// + ///\ingroup algorithm + //*************************************************************************** + template + ETL_NODISCARD + TIterator max_element(TIterator begin, + TIterator end, + TCompare compare) + { + TIterator maximum = begin; + + while (begin != end) + { + if (!compare(*begin, *maximum)) + { + maximum = begin; + } + + ++begin; + } + + return maximum; + } + + //*************************************************************************** + /// max_element + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + TIterator max_element(TIterator begin, + TIterator end) + { + typedef typename etl::iterator_traits::value_type value_t; + + return etl::max_element(begin, end, etl::less()); + } +#else + //*************************************************************************** + /// Finds the iterator to the largest element in the range (begin, end).
+ /// + ///\ingroup algorithm + //*************************************************************************** + template + ETL_NODISCARD + TIterator max_element(TIterator begin, + TIterator end, + TCompare compare) + { + return std::max_element(begin, end, compare); + } + + //*************************************************************************** + /// max_element + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + TIterator max_element(TIterator begin, + TIterator end) + { + return std::max_element(begin, end); + } +#endif + +#if ETL_NOT_USING_STL || ETL_CPP11_NOT_SUPPORTED + //*************************************************************************** + /// Finds the greatest and the smallest element in the range (begin, end).
+ /// + ///\ingroup algorithm + //*************************************************************************** + template + ETL_NODISCARD + ETL_OR_STD::pair minmax_element(TIterator begin, + TIterator end, + TCompare compare) + { + TIterator minimum = begin; + TIterator maximum = begin; + + while (begin != end) + { + if (compare(*begin, *minimum)) + { + minimum = begin; + } + + if (compare(*maximum, *begin)) + { + maximum = begin; + } + + ++begin; + } + + return ETL_OR_STD::pair(minimum, maximum); + } + + //*************************************************************************** + /// minmax_element + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + ETL_OR_STD::pair minmax_element(TIterator begin, + TIterator end) + { + typedef typename etl::iterator_traits::value_type value_t; + + return etl::minmax_element(begin, end, etl::less()); + } +#else + //*************************************************************************** +/// Finds the greatest and the smallest element in the range (begin, end).
+/// +///\ingroup algorithm +//*************************************************************************** + template + ETL_NODISCARD + std::pair minmax_element(TIterator begin, + TIterator end, + TCompare compare) + { + return std::minmax_element(begin, end, compare); + } + + //*************************************************************************** + /// minmax_element + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + std::pair minmax_element(TIterator begin, + TIterator end) + { + return std::minmax_element(begin, end); + } +#endif + +#if ETL_NOT_USING_STL || ETL_CPP11_NOT_SUPPORTED + //*************************************************************************** + /// minmax + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + ETL_OR_STD::pair minmax(const T& a, + const T& b) + { + return (b < a) ? ETL_OR_STD::pair(b, a) : ETL_OR_STD::pair(a, b); + } + + //*************************************************************************** + /// minmax + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + ETL_OR_STD::pair minmax(const T& a, + const T& b, + TCompare compare) + { + return compare(b, a) ? ETL_OR_STD::pair(b, a) : ETL_OR_STD::pair(a, b); + } +#else + //*************************************************************************** + /// minmax + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + std::pair minmax(const T& a, + const T& b) + { + return std::minmax(a, b); + } + + //*************************************************************************** + /// minmax + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + std::pair minmax(const T& a, + const T& b, + TCompare compare) + { + return std::minmax(a, b, compare); + } +#endif + +#if ETL_NOT_USING_STL || ETL_CPP11_NOT_SUPPORTED + //*************************************************************************** + /// is_sorted_until + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + TIterator is_sorted_until(TIterator begin, + TIterator end) + { + if (begin != end) + { + TIterator next = begin; + + while (++next != end) + { + if (*next < *begin) + { + return next; + } + + ++begin; + } + } + + return end; + } + + //*************************************************************************** + /// is_sorted_until + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + TIterator is_sorted_until(TIterator begin, + TIterator end, + TCompare compare) + { + if (begin != end) + { + TIterator next = begin; + + while (++next != end) + { + if (compare(*next, *begin)) + { + return next; + } + + ++begin; + } + } + + return end; + } +#else + //*************************************************************************** + /// is_sorted_until + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + TIterator is_sorted_until(TIterator begin, + TIterator end) + { + return std::is_sorted_until(begin, end); + } + + //*************************************************************************** + /// is_sorted_until + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + TIterator is_sorted_until(TIterator begin, + TIterator end, + TCompare compare) + { + return std::is_sorted_until(begin, end, compare); + } +#endif + +#if ETL_NOT_USING_STL || ETL_CPP11_NOT_SUPPORTED + //*************************************************************************** + /// is_sorted + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool is_sorted(TIterator begin, + TIterator end) + { + return etl::is_sorted_until(begin, end) == end; + } + + //*************************************************************************** + /// is_sorted + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool is_sorted(TIterator begin, + TIterator end, + TCompare compare) + { + return etl::is_sorted_until(begin, end, compare) == end; + } +#else + //*************************************************************************** + /// is_sorted + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool is_sorted(TIterator begin, + TIterator end) + { + return std::is_sorted(begin, end); + } + + //*************************************************************************** + /// is_sorted + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool is_sorted(TIterator begin, + TIterator end, + TCompare compare) + { + return std::is_sorted(begin, end, compare); + } +#endif + +#if ETL_NOT_USING_STL || ETL_CPP11_NOT_SUPPORTED + //*************************************************************************** + /// find_if_not + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + TIterator find_if_not(TIterator begin, + TIterator end, + TUnaryPredicate predicate) + { + while (begin != end) + { + if (!predicate(*begin)) + { + return begin; + } + + ++begin; + } + + return end; + } +#else + //*************************************************************************** + /// find_if_not + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + TIterator find_if_not(TIterator begin, + TIterator end, + TUnaryPredicate predicate) + { + return std::find_if_not(begin, end, predicate); + } +#endif + +#if ETL_NOT_USING_STL || ETL_CPP11_NOT_SUPPORTED + //*************************************************************************** + /// is_permutation + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool is_permutation(TIterator1 begin1, + TIterator1 end1, + TIterator2 begin2) + { + if (begin1 != end1) + { + TIterator2 end2 = begin2; + + etl::advance(end2, etl::distance(begin1, end1)); + + for (TIterator1 i = begin1; i != end1; ++i) + { + if (i == etl::find(begin1, i, *i)) + { + size_t n = etl::count(begin2, end2, *i); + + if (n == 0 || size_t(etl::count(i, end1, *i)) != n) + { + return false; + } + } + } + } + + return true; + } + + //*************************************************************************** + /// is_permutation + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool is_permutation(TIterator1 begin1, + TIterator1 end1, + TIterator2 begin2, + TBinaryPredicate predicate) + { + if (begin1 != end1) + { + TIterator2 end2 = begin2; + + etl::advance(end2, etl::distance(begin1, end1)); + + for (TIterator1 i = begin1; i != end1; ++i) + { + if (i == etl::find_if(begin1, i, etl::bind1st(predicate, *i))) + { + size_t n = etl::count(begin2, end2, *i); + + if (n == 0 || size_t(etl::count(i, end1, *i)) != n) + { + return false; + } + } + } + } + + return true; + } + + //*************************************************************************** + /// is_permutation + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool is_permutation(TIterator1 begin1, + TIterator1 end1, + TIterator2 begin2, + TIterator2 end2) + { + if (begin1 != end1) + { + for (TIterator1 i = begin1; i != end1; ++i) + { + if (i == etl::find(begin1, i, *i)) + { + size_t n = etl::count(begin2, end2, *i); + + if (n == 0 || size_t(etl::count(i, end1, *i)) != n) + { + return false; + } + } + } + } + + return true; + } + + //*************************************************************************** + /// is_permutation + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool is_permutation(TIterator1 begin1, + TIterator1 end1, + TIterator2 begin2, + TIterator2 end2, + TBinaryPredicate predicate) + { + if (begin1 != end1) + { + for (TIterator1 i = begin1; i != end1; ++i) + { + if (i == etl::find_if(begin1, i, etl::bind1st(predicate, *i))) + { + size_t n = etl::count(begin2, end2, *i); + + if (n == 0 || size_t(etl::count(i, end1, *i)) != n) + { + return false; + } + } + } + } + + return true; + } +#else + //*************************************************************************** + /// is_permutation + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool is_permutation(TIterator1 begin1, + TIterator1 end1, + TIterator2 begin2) + { + return std::is_permutation(begin1, end1, begin2); + } + + //*************************************************************************** + /// is_permutation + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool is_permutation(TIterator1 begin1, + TIterator1 end1, + TIterator2 begin2, + TBinaryPredicate predicate) + { + return std::is_permutation(begin1, end1, begin2, predicate); + } + + #if ETL_CPP14_SUPPORTED + //*************************************************************************** + /// is_permutation + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool is_permutation(TIterator1 begin1, + TIterator1 end1, + TIterator2 begin2, + TIterator2 end2) + { + return std::is_permutation(begin1, end1, begin2, end2); + } + + //*************************************************************************** + /// is_permutation + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool is_permutation(TIterator1 begin1, + TIterator1 end1, + TIterator2 begin2, + TIterator2 end2, + TBinaryPredicate predicate) + { + return std::is_permutation(begin1, end1, begin2, end2, predicate); + } + #endif +#endif + +#if ETL_NOT_USING_STL || ETL_CPP11_NOT_SUPPORTED + //*************************************************************************** + /// is_partitioned + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool is_partitioned(TIterator begin, + TIterator end, + TUnaryPredicate predicate) + { + while (begin != end) + { + if (!predicate(*begin++)) + { + break; + } + } + + while (begin != end) + { + if (predicate(*begin++)) + { + return false; + } + } + + return true; + } +#else + //*************************************************************************** + /// is_partitioned + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool is_partitioned(TIterator begin, + TIterator end, + TUnaryPredicate predicate) + { + return std::is_partitioned(begin, end, predicate); + } +#endif + +#if ETL_NOT_USING_STL || ETL_CPP11_NOT_SUPPORTED + //*************************************************************************** + /// partition_point + /// + ///\ingroup algorithm + //*************************************************************************** + template + ETL_NODISCARD + TIterator partition_point(TIterator begin, + TIterator end, + TUnaryPredicate predicate) + { + while (begin != end) + { + if (!predicate(*begin)) + { + return begin; + } + + ++begin; + } + + return begin; + } +#else + //*************************************************************************** + /// partition_point + /// + ///\ingroup algorithm + //*************************************************************************** + template + ETL_NODISCARD + TIterator partition_point(TIterator begin, + TIterator end, + TUnaryPredicate predicate) + { + return std::partition_point(begin, end, predicate); + } +#endif + +#if ETL_NOT_USING_STL || ETL_CPP11_NOT_SUPPORTED + //*************************************************************************** + /// Copies the elements from the range (begin, end) to two different ranges + /// depending on the value returned by the predicate.
+ /// + ///\ingroup algorithm + //*************************************************************************** + template + ETL_OR_STD::pair partition_copy(TSource begin, + TSource end, + TDestinationTrue destination_true, + TDestinationFalse destination_false, + TUnaryPredicate predicate) + { + while (begin != end) + { + if (predicate(*begin)) + { + *destination_true++ = *begin++; + } + else + { + *destination_false++ = *begin++; + } + } + + return ETL_OR_STD::pair(destination_true, destination_false); + } +#else + //*************************************************************************** + /// Copies the elements from the range (begin, end) to two different ranges + /// depending on the value returned by the predicate.
+ /// + ///\ingroup algorithm + //*************************************************************************** + template + std::pair partition_copy(TSource begin, + TSource end, + TDestinationTrue destination_true, + TDestinationFalse destination_false, + TUnaryPredicate predicate) + { + return std::partition_copy(begin, end, destination_true, destination_false, predicate); + } +#endif + +#if ETL_NOT_USING_STL || ETL_CPP11_NOT_SUPPORTED + //*************************************************************************** + /// copy_if + ///\ingroup algorithm + /// + //*************************************************************************** + template + TOutputIterator copy_if(TIterator begin, + TIterator end, + TOutputIterator out, + TUnaryPredicate predicate) + { + while (begin != end) + { + if (predicate(*begin)) + { + *out++ = *begin; + } + + ++begin; + } + + return out; + } +#else + //*************************************************************************** + /// copy_if + ///\ingroup algorithm + /// + //*************************************************************************** + template + TOutputIterator copy_if(TIterator begin, + TIterator end, + TOutputIterator out, + TUnaryPredicate predicate) + { + return std::copy_if(begin, end, out, predicate); + } +#endif + +#if ETL_NOT_USING_STL || ETL_CPP11_NOT_SUPPORTED + //*************************************************************************** + /// all_of + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool all_of(TIterator begin, + TIterator end, + TUnaryPredicate predicate) + { + return etl::find_if_not(begin, end, predicate) == end; + } +#else + //*************************************************************************** + /// all_of + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool all_of(TIterator begin, + TIterator end, + TUnaryPredicate predicate) + { + return std::all_of(begin, end, predicate); + } +#endif + +#if ETL_NOT_USING_STL || ETL_CPP11_NOT_SUPPORTED + //*************************************************************************** + /// any_of + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool any_of(TIterator begin, + TIterator end, + TUnaryPredicate predicate) + { + return etl::find_if(begin, end, predicate) != end; + } +#else + //*************************************************************************** + /// any_of + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool any_of(TIterator begin, + TIterator end, + TUnaryPredicate predicate) + { + return std::any_of(begin, end, predicate); + } +#endif + +#if ETL_NOT_USING_STL || ETL_CPP11_NOT_SUPPORTED + //*************************************************************************** + /// none_of + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool none_of(TIterator begin, + TIterator end, + TUnaryPredicate predicate) + { + return etl::find_if(begin, end, predicate) == end; + } +#else + //*************************************************************************** + /// none_of + ///\ingroup algorithm + /// + //*************************************************************************** + template + ETL_NODISCARD + bool none_of(TIterator begin, + TIterator end, + TUnaryPredicate predicate) + { + return std::none_of(begin, end, predicate); + } +#endif + +#if ETL_NOT_USING_STL + //*************************************************************************** + /// Sorts the elements. + /// Uses user defined comparison. + ///\ingroup algorithm + //*************************************************************************** + template + void sort(TIterator first, TIterator last, TCompare compare) + { + etl::shell_sort(first, last, compare); + } + + //*************************************************************************** + /// Sorts the elements. + ///\ingroup algorithm + //*************************************************************************** + template + void sort(TIterator first, TIterator last) + { + etl::shell_sort(first, last, etl::less::value_type>()); + } + + //*************************************************************************** + /// Sorts the elements. + /// Stable. + /// Uses user defined comparison. + ///\ingroup algorithm + //*************************************************************************** + template + void stable_sort(TIterator first, TIterator last, TCompare compare) + { + etl::insertion_sort(first, last, compare); + } + + //*************************************************************************** + /// Sorts the elements. + /// Stable. + ///\ingroup algorithm + //*************************************************************************** + template + void stable_sort(TIterator first, TIterator last) + { + etl::insertion_sort(first, last, etl::less::value_type>()); + } +#else + //*************************************************************************** + /// Sorts the elements. + /// Uses user defined comparison. + ///\ingroup algorithm + //*************************************************************************** + template + void sort(TIterator first, TIterator last, TCompare compare) + { + std::sort(first, last, compare); + } + + //*************************************************************************** + /// Sorts the elements. + ///\ingroup algorithm + //*************************************************************************** + template + void sort(TIterator first, TIterator last) + { + std::sort(first, last); + } + + //*************************************************************************** + /// Sorts the elements. + /// Stable. + /// Uses user defined comparison. + ///\ingroup algorithm + //*************************************************************************** + template + void stable_sort(TIterator first, TIterator last, TCompare compare) + { + std::stable_sort(first, last, compare); + } + + //*************************************************************************** + /// Sorts the elements. + /// Stable. + ///\ingroup algorithm + //*************************************************************************** + template + void stable_sort(TIterator first, TIterator last) + { + std::stable_sort(first, last); + } +#endif +} + +//***************************************************************************** +// ETL extensions to the STL algorithms. +//***************************************************************************** +namespace etl +{ + //*************************************************************************** + /// copy_s + /// A safer form of copy where the smallest of the two ranges is used. + /// There is currently no STL equivalent. + /// Specialisation for random access iterators. + ///\param i_begin Beginning of the input range. + ///\param i_end End of the input range. + ///\param o_begin Beginning of the output range. + ///\param o_end End of the output range. + ///\ingroup algorithm + //*************************************************************************** + template + typename etl::enable_if::value && + etl::is_random_iterator::value, TOutputIterator>::type + copy_s(TInputIterator i_begin, + TInputIterator i_end, + TOutputIterator o_begin, + TOutputIterator o_end) + { + size_t s_size = etl::distance(i_begin, i_end); + size_t d_size = etl::distance(o_begin, o_end); + size_t size = (s_size < d_size) ? s_size : d_size; + + return etl::copy(i_begin, i_begin + size, o_begin); + } + + //*************************************************************************** + /// copy + /// A safer form of copy where the smallest of the two ranges is used. + /// There is currently no STL equivalent. + /// Specialisation for non random access iterators. + ///\param i_begin Beginning of the input range. + ///\param i_end End of the input range. + ///\param o_begin Beginning of the output range. + ///\param o_end End of the output range. + ///\ingroup algorithm + //*************************************************************************** + template + typename etl::enable_if::value || + !etl::is_random_iterator::value, TOutputIterator>::type + copy_s(TInputIterator i_begin, + TInputIterator i_end, + TOutputIterator o_begin, + TOutputIterator o_end) + { + while ((i_begin != i_end) && (o_begin != o_end)) + { + *o_begin++ = *i_begin++; + } + + return o_begin; + } + + //*************************************************************************** + /// copy_n + /// A safer form of copy_n where the smallest of the two ranges is used. + ///\ingroup algorithm + //*************************************************************************** + template + TOutputIterator copy_n_s(TInputIterator i_begin, + TSize n, + TOutputIterator o_begin, + TOutputIterator o_end) + { + while ((n-- > 0) && (o_begin != o_end)) + { + *o_begin++ = *i_begin++; + } + + return o_begin; + } + + //*************************************************************************** + /// copy_n + /// A safer form of copy_n where the smallest of the two ranges is used. + ///\ingroup algorithm + //*************************************************************************** + template + TOutputIterator copy_n_s(TInputIterator i_begin, + TSize1 n1, + TOutputIterator o_begin, + TSize2 n2) + { + while ((n1-- > 0) && (n2-- > 0)) + { + *o_begin++ = *i_begin++; + } + + return o_begin; + } + + //*************************************************************************** + /// copy_if + /// A safer form of copy_if where it terminates when the first end iterator is reached. + /// There is currently no STL equivelent. + ///\ingroup algorithm + //*************************************************************************** + template + TOutputIterator copy_if_s(TInputIterator i_begin, + TInputIterator i_end, + TOutputIterator o_begin, + TOutputIterator o_end, + TUnaryPredicate predicate) + { + while ((i_begin != i_end) && (o_begin != o_end)) + { + if (predicate(*i_begin)) + { + *o_begin++ = *i_begin; + } + + ++i_begin; + } + + return o_begin; + } + + //*************************************************************************** + /// copy_n_if + /// Combination of copy_n and copy_if. + ///\ingroup algorithm + //*************************************************************************** + template + TOutputIterator copy_n_if(TInputIterator i_begin, + TSize n, + TOutputIterator o_begin, + TUnaryPredicate predicate) + { + while (n-- > 0) + { + if (predicate(*i_begin)) + { + *o_begin++ = *i_begin; + } + + ++i_begin; + } + + return o_begin; + } + +#if ETL_CPP11_SUPPORTED + //*************************************************************************** + /// move_s + /// A safer form of move where the smallest of the two ranges is used. + /// There is currently no STL equivalent. + /// Specialisation for random access iterators. + ///\param i_begin Beginning of the input range. + ///\param i_end End of the input range. + ///\param o_begin Beginning of the output range. + ///\param o_end End of the output range. + ///\ingroup algorithm + //*************************************************************************** + template + typename etl::enable_if::value && + etl::is_random_iterator::value, TOutputIterator>::type + move_s(TInputIterator i_begin, + TInputIterator i_end, + TOutputIterator o_begin, + TOutputIterator o_end) + { + size_t s_size = etl::distance(i_begin, i_end); + size_t d_size = etl::distance(o_begin, o_end); + size_t size = (s_size < d_size) ? s_size : d_size; + + return etl::move(i_begin, i_begin + size, o_begin); + } + + //*************************************************************************** + /// move_s + /// A safer form of move where the smallest of the two ranges is used. + /// There is currently no STL equivalent. + /// Specialisation for non random access iterators. + ///\param i_begin Beginning of the input range. + ///\param i_end End of the input range. + ///\param o_begin Beginning of the output range. + ///\param o_end End of the output range. + ///\ingroup algorithm + //*************************************************************************** + template + typename etl::enable_if::value || + !etl::is_random_iterator::value, TOutputIterator>::type + move_s(TInputIterator i_begin, + TInputIterator i_end, + TOutputIterator o_begin, + TOutputIterator o_end) + { + while ((i_begin != i_end) && (o_begin != o_end)) + { + *o_begin++ = etl::move(*i_begin++); + } + + return o_begin; + } +#else + //*************************************************************************** + /// move_s + /// C++03 + /// A safer form of move where the smallest of the two ranges is used. + /// There is currently no STL equivalent. + /// Specialisation for non random access iterators. + ///\param i_begin Beginning of the input range. + ///\param i_end End of the input range. + ///\param o_begin Beginning of the output range. + ///\param o_end End of the output range. + ///\ingroup algorithm + //*************************************************************************** + template + TOutputIterator move_s(TInputIterator i_begin, + TInputIterator i_end, + TOutputIterator o_begin, + TOutputIterator o_end) + { + // Move not supported. Defer to copy. + return etl::copy_s(i_begin, i_end, o_begin, o_end); + } +#endif + + //*************************************************************************** + /// binary_find + ///\ingroup algorithm + /// Does a binary search and returns an iterator to the value or end if not found. + //*************************************************************************** + template + ETL_NODISCARD + TIterator binary_find(TIterator begin, + TIterator end, + const TValue& value) + { + TIterator it = etl::lower_bound(begin, end, value); + + if ((it == end) || (*it != value)) + { + it = end; + } + + return it; + } + + //*************************************************************************** + /// binary_find + ///\ingroup algorithm + /// Does a binary search and returns an iterator to the value or end if not found. + //*************************************************************************** + template + ETL_NODISCARD + TIterator binary_find(TIterator begin, + TIterator end, + const TValue& value, + TBinaryPredicate predicate, + TBinaryEquality equality) + { + TIterator it = etl::lower_bound(begin, end, value, predicate); + + if ((it == end) || !equality(*it, value)) + { + it = end; + } + + return it; + } + + //*************************************************************************** + /// Like std::for_each but applies a predicate before calling the function. + ///\ingroup algorithm + //*************************************************************************** + template + TUnaryFunction for_each_if(TIterator begin, + const TIterator end, + TUnaryFunction function, + TUnaryPredicate predicate) + { + while (begin != end) + { + if (predicate(*begin)) + { + function(*begin); + } + + ++begin; + } + + return function; + } + + //*************************************************************************** + /// Like std::for_each but for 'n' iterations. + ///\ingroup algorithm + //*************************************************************************** + template + TIterator for_each_n(TIterator begin, + TSize n, + TUnaryFunction function) + { + while (n-- > 0) + { + function(*begin++); + } + + return begin; + } + + //*************************************************************************** + /// Like std::for_each but applies a predicate before calling the function, for 'n' iterations + ///\ingroup algorithm + //*************************************************************************** + template + TIterator for_each_n_if(TIterator begin, + TSize n, + TUnaryFunction function, + TUnaryPredicate predicate) + { + while (n-- > 0) + { + if (predicate(*begin)) + { + function(*begin); + } + + ++begin; + } + + return begin; + } + + //*************************************************************************** + /// A safer form of std::transform where the transform returns when the first + /// range end is reached. + /// There is currently no STL equivalent. + ///\ingroup algorithm + //*************************************************************************** + template + TOutputIterator transform_s(TInputIterator i_begin, + TInputIterator i_end, + TOutputIterator o_begin, + TOutputIterator o_end, + TUnaryFunction function) + { + while ((i_begin != i_end) && (o_begin != o_end)) + { + *o_begin++ = function(*i_begin++); + } + + return o_begin; + } + + //*************************************************************************** + /// Transform 'n' items. + /// Random iterators. + /// There is currently no STL equivalent. + ///\ingroup algorithm + //*************************************************************************** + template + void transform_n(TInputIterator i_begin, + TSize n, + TOutputIterator o_begin, + TUnaryFunction function) + { + TInputIterator i_end(i_begin); + etl::advance(i_end, n); + + etl::transform(i_begin, i_end, o_begin, function); + } + + //*************************************************************************** + /// Transform 'n' items from two ranges. + /// Random iterators. + /// There is currently no STL equivalent. + ///\ingroup algorithm + //*************************************************************************** + template + void transform_n(TInputIterator1 i_begin1, + TInputIterator2 i_begin2, + TSize n, + TOutputIterator o_begin, + TBinaryFunction function) + { + TInputIterator1 i_end1(i_begin1); + etl::advance(i_end1, n); + + etl::transform(i_begin1, i_end1, i_begin2, o_begin, function); + } + + //*************************************************************************** + /// Like std::transform but applies a predicate before calling the function. + ///\ingroup algorithm + //*************************************************************************** + template + TOutputIterator transform_if(TInputIterator i_begin, + const TInputIterator i_end, + TOutputIterator o_begin, + TUnaryFunction function, + TUnaryPredicate predicate) + { + while (i_begin != i_end) + { + if (predicate(*i_begin)) + { + *o_begin++ = function(*i_begin); + } + + ++i_begin; + } + + return o_begin; + } + + //*************************************************************************** + /// Like etl::transform_if but inputs from two ranges. + ///\ingroup algorithm + //*************************************************************************** + template + TOutputIterator transform_if(TInputIterator1 i_begin1, + const TInputIterator1 i_end1, + TInputIterator2 i_begin2, + TOutputIterator o_begin, + TBinaryFunction function, + TBinaryPredicate predicate) + { + while (i_begin1 != i_end1) + { + if (predicate(*i_begin1, *i_begin2)) + { + *o_begin++ = function(*i_begin1, *i_begin2); + } + + ++i_begin1; + ++i_begin2; + } + + return o_begin; + } + + //*************************************************************************** + /// Like std::transform_if, for 'n' items. + ///\ingroup algorithm + //*************************************************************************** + template + TOutputIterator transform_n_if(TInputIterator i_begin, + TSize n, + TOutputIterator o_begin, + TUnaryFunction function, + TUnaryPredicate predicate) + { + while (n-- > 0) + { + if (predicate(*i_begin)) + { + *o_begin++ = function(*i_begin); + } + + ++i_begin; + } + + return o_begin; + } + + //*************************************************************************** + /// Like etl::transform_if but inputs from two ranges for 'n' items. + ///\ingroup algorithm + //*************************************************************************** + template + TOutputIterator transform_n_if(TInputIterator1 i_begin1, + TInputIterator2 i_begin2, + TSize n, + TOutputIterator o_begin, + TBinaryFunction function, + TBinaryPredicate predicate) + { + while (n-- > 0) + { + if (predicate(*i_begin1, *i_begin2)) + { + *o_begin++ = function(*i_begin1, *i_begin2); + } + + ++i_begin1; + ++i_begin2; + } + + return o_begin; + } + + //*************************************************************************** + /// Transforms the elements from the range (begin, end) to two different ranges + /// depending on the value returned by the predicate.
+ ///\ingroup algorithm + //*************************************************************************** + template + ETL_OR_STD::pair partition_transform(TSource begin, + TSource end, + TDestinationTrue destination_true, + TDestinationFalse destination_false, + TUnaryFunctionTrue function_true, + TUnaryFunctionFalse function_false, + TUnaryPredicate predicate) + { + while (begin != end) + { + if (predicate(*begin)) + { + *destination_true++ = function_true(*begin++); + } + else + { + *destination_false++ = function_false(*begin++); + } + } + + return ETL_OR_STD::pair(destination_true, destination_false); + } + + //*************************************************************************** + /// Transforms the elements from the ranges (begin1, end1) & (begin2) + /// to two different ranges depending on the value returned by the predicate. + ///\ingroup algorithm + //*************************************************************************** + template + ETL_OR_STD::pair partition_transform(TSource1 begin1, + TSource1 end1, + TSource2 begin2, + TDestinationTrue destination_true, + TDestinationFalse destination_false, + TBinaryFunctionTrue function_true, + TBinaryFunctionFalse function_false, + TBinaryPredicate predicate) + { + while (begin1 != end1) + { + if (predicate(*begin1, *begin2)) + { + *destination_true++ = function_true(*begin1++, *begin2++); + } + else + { + *destination_false++ = function_false(*begin1++, *begin2++); + } + } + + return ETL_OR_STD::pair(destination_true, destination_false); + } + + //*************************************************************************** + /// Sorts the elements using shell sort. + /// Uses user defined comparison. + ///\ingroup algorithm + //*************************************************************************** + template + void shell_sort(TIterator first, TIterator last, TCompare compare) + { + if (first == last) + { + return; + } + + typedef typename etl::iterator_traits::difference_type difference_t; + + difference_t n = etl::distance(first, last); + + for (difference_t i = n / 2; i > 0; i /= 2) + { + for (difference_t j = i; j < n; ++j) + { + for (difference_t k = j - i; k >= 0; k -= i) + { + TIterator itr1 = first; + TIterator itr2 = first; + + etl::advance(itr1, k); + etl::advance(itr2, k + i); + + if (compare(*itr2, *itr1)) + { + etl::iter_swap(itr1, itr2); + } + } + } + } + } + + //*************************************************************************** + /// Sorts the elements using shell sort. + ///\ingroup algorithm + //*************************************************************************** + template + void shell_sort(TIterator first, TIterator last) + { + etl::shell_sort(first, last, etl::less::value_type>()); + } + + //*************************************************************************** + /// Sorts the elements using insertion sort. + /// Uses user defined comparison. + ///\ingroup algorithm + //*************************************************************************** + template + void insertion_sort(TIterator first, TIterator last, TCompare compare) + { + for (TIterator itr = first; itr != last; ++itr) + { + etl::rotate(etl::upper_bound(first, itr, *itr, compare), itr, etl::next(itr)); + } + } + + //*************************************************************************** + /// Sorts the elements using insertion sort. + ///\ingroup algorithm + //*************************************************************************** + template + void insertion_sort(TIterator first, TIterator last) + { + etl::insertion_sort(first, last, etl::less::value_type>()); + } + + //*************************************************************************** + /// Sorts the elements using heap sort. + /// Uses user defined comparison. + ///\ingroup algorithm + //*************************************************************************** + template + void heap_sort(TIterator first, TIterator last, TCompare compare) + { + if (!etl::is_heap(first, last, compare)) + { + etl::make_heap(first, last, compare); + } + + etl::sort_heap(first, last, compare); + } + + //*************************************************************************** + /// Sorts the elements using heap sort. + ///\ingroup algorithm + //*************************************************************************** + template + void heap_sort(TIterator first, TIterator last) + { + if (!etl::is_heap(first, last)) + { + etl::make_heap(first, last); + } + + etl::sort_heap(first, last); + } + + //*************************************************************************** + /// Returns the maximum value. + //*************************************************************************** +#if ETL_CPP11_SUPPORTED + template + ETL_NODISCARD + constexpr const T& multimax(const T& a, const T& b) + { + return a < b ? b : a; + } + + template + ETL_NODISCARD + constexpr const T& multimax(const T& t, const Tx&... tx) + { + return multimax(t, multimax(tx...)); + } +#endif + + //*************************************************************************** + /// Returns the maximum value. + /// User supplied compare function. + //*************************************************************************** +#if ETL_CPP11_SUPPORTED + template + ETL_NODISCARD + constexpr const T& multimax_compare(TCompare compare, const T& a, const T& b) + { + return compare(a, b) ? b : a; + } + + template + ETL_NODISCARD + constexpr const T& multimax_compare(TCompare compare, const T& t, const Tx&... tx) + { + return multimax_compare(compare, t, multimax_compare(compare, tx...)); + } +#endif + + //*************************************************************************** + /// Returns the maximum value. + //*************************************************************************** +#if ETL_CPP11_SUPPORTED + template + ETL_NODISCARD + constexpr const T& multimin(const T& a, const T& b) + { + return a < b ? a : b; + } + + template + ETL_NODISCARD + constexpr const T& multimin(const T& t, const Tx&... tx) + { + return multimin(t, multimin(tx...)); + } +#endif + + //*************************************************************************** + /// Returns the minimum value. + /// User supplied compare function. + //*************************************************************************** +#if ETL_CPP11_SUPPORTED + template + ETL_NODISCARD + constexpr const T& multimin_compare(TCompare compare, const T& a, const T& b) + { + return compare(a, b) ? a : b; + } + + template + ETL_NODISCARD + constexpr const T& multimin_compare(TCompare compare, const T& t, const Tx&... tx) + { + return multimin_compare(compare, t, multimin_compare(compare, tx...)); + } +#endif + + //*************************************************************************** + /// Returns the iterator to the maximum value. + //*************************************************************************** +#if ETL_CPP11_SUPPORTED + template + ETL_NODISCARD + constexpr const TIterator& multimax_iter(const TIterator& a, const TIterator& b) + { + return *a < *b ? b : a; + } + + template + ETL_NODISCARD + constexpr const TIterator& multimax_iter(const TIterator& t, const TIteratorx&... tx) + { + return multimax_iter(t, multimax_iter(tx...)); + } +#endif + + //*************************************************************************** + /// Returns the iterator to the maximum value. + /// User supplied compare function. + //*************************************************************************** +#if ETL_CPP11_SUPPORTED + template + ETL_NODISCARD + constexpr const TIterator& multimax_iter_compare(TCompare compare, const TIterator& a, const TIterator& b) + { + return compare(*a, *b) ? b : a; + } + + template + ETL_NODISCARD + constexpr const TIterator& multimax_iter_compare(TCompare compare, const TIterator& t, const TIteratorx&... tx) + { + return multimax_iter_compare(compare, t, multimax_iter_compare(compare, tx...)); + } +#endif + + //*************************************************************************** + /// Returns the iterator to the minimum value. + //*************************************************************************** +#if ETL_CPP11_SUPPORTED + template + ETL_NODISCARD + constexpr const TIterator& multimin_iter(const TIterator& a, const TIterator& b) + { + return *a < *b ? a : b; + } + + template + ETL_NODISCARD + constexpr const TIterator& multimin_iter(const TIterator& t, const Tx&... tx) + { + return multimin_iter(t, multimin_iter(tx...)); + } +#endif + + //*************************************************************************** + /// Returns the iterator to the minimum value. + /// User supplied compare function. + //*************************************************************************** +#if ETL_CPP11_SUPPORTED + template + ETL_NODISCARD + constexpr const TIterator& multimin_iter_compare(TCompare compare, const TIterator& a, const TIterator& b) + { + return compare(*a, *b) ? a : b; + } + + template + ETL_NODISCARD + constexpr const TIterator& multimin_iter_compare(TCompare compare, const TIterator& t, const Tx&... tx) + { + return multimin_iter_compare(compare, t, multimin_iter_compare(compare, tx...)); + } +#endif +} + +#include "private/minmax_pop.h" + +#endif diff --git a/src/etl/alignment.h b/src/etl/alignment.h new file mode 100644 index 0000000..6b2fcbe --- /dev/null +++ b/src/etl/alignment.h @@ -0,0 +1,219 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2014 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_ALIGNEMENT_INCLUDED +#define ETL_ALIGNEMENT_INCLUDED + +#include + +#include "platform.h" +#include "type_traits.h" +#include "static_assert.h" + +///\defgroup alignment alignment +/// Creates a variable of the specified type at the specified alignment. +/// \ingroup utilities + +namespace etl +{ + namespace private_alignment + { + //*************************************************************************** + // Matcher. + //*************************************************************************** + template + class type_with_alignment_matcher; + + // Matching alignment. + template + class type_with_alignment_matcher + { + public: + + typedef T1 type; + }; + + // Non-matching alignment. + template + class type_with_alignment_matcher + { + public: + + typedef typename type_with_alignment_matcher::value, ALIGNMENT, T2, T3, T4, T5, T6, T7, T8, void>::type type; + }; + + // Non-matching alignment, none left. + template + class type_with_alignment_matcher + { + public: + + typedef char type; + }; + + //*************************************************************************** + // Helper. + //*************************************************************************** + template + class type_with_alignment_helper + { + public: + + typedef typename type_with_alignment_matcher::value, ALIGNMENT, T1, T2, T3, T4, T5, T6, T7, T8>::type type; + }; + } + + //*************************************************************************** + /// Gets a type that has the same as the specified alignment. + ///\ingroup alignment + //*************************************************************************** + template + class type_with_alignment + { + public: + +#if ETL_NOT_USING_64BIT_TYPES + typedef typename private_alignment::type_with_alignment_helper::type type; +#else + typedef typename private_alignment::type_with_alignment_helper::type type; +#endif + }; + + //*************************************************************************** + /// Aligned storage + /// LENGTH should be determined in terms of sizeof() + ///\ingroup alignment + //*************************************************************************** + template + struct aligned_storage + { + struct type + { + /// Convert to T reference. + template + operator T& () + { + ETL_STATIC_ASSERT((etl::is_same:: value || ((ALIGNMENT % etl::alignment_of::value) == 0)), "Incompatible alignment"); + T* t = *this; + return *t; + } + + /// Convert to const T reference. + template + operator const T& () const + { + ETL_STATIC_ASSERT((etl::is_same:: value || ((ALIGNMENT % etl::alignment_of::value) == 0)), "Incompatible alignment"); + const T* t = *this; + return *t; + } + + /// Convert to T pointer. + template + operator T* () + { + ETL_STATIC_ASSERT((etl::is_same:: value || ((ALIGNMENT % etl::alignment_of::value) == 0)), "Incompatible alignment"); + return reinterpret_cast(data); + } + + /// Convert to const T pointer. + template + operator const T* () const + { + ETL_STATIC_ASSERT((etl::is_same:: value || ((ALIGNMENT % etl::alignment_of::value) == 0)), "Incompatible alignment"); + return reinterpret_cast(data); + } + + /// Get address as T reference. + template + T& get_reference() + { + ETL_STATIC_ASSERT((etl::is_same:: value || ((ALIGNMENT % etl::alignment_of::value) == 0)), "Incompatible alignment"); + T* t = *this; + return *t; + } + + /// Get address as const T reference. + template + const T& get_reference() const + { + ETL_STATIC_ASSERT((etl::is_same:: value || ((ALIGNMENT % etl::alignment_of::value) == 0)), "Incompatible alignment"); + const T* t = *this; + return *t; + } + + /// Get address as T pointer. + template + T* get_address() + { + ETL_STATIC_ASSERT((etl::is_same:: value || ((ALIGNMENT % etl::alignment_of::value) == 0)), "Incompatible alignment"); + return reinterpret_cast(data); + } + + /// Get address as const T pointer. + template + const T* get_address() const + { + ETL_STATIC_ASSERT((etl::is_same:: value || ((ALIGNMENT % etl::alignment_of::value) == 0)), "Incompatible alignment"); + return reinterpret_cast(data); + } + +#if ETL_CPP11_SUPPORTED && !defined(ETL_COMPILER_ARM5) + alignas(ALIGNMENT) char data[LENGTH]; +#else + union + { + char data[LENGTH]; + typename etl::type_with_alignment::type etl_alignment_type; // A POD type that has the same alignment as ALIGNMENT. + }; +#endif + }; + }; + +#if ETL_CPP14_SUPPORTED + template + using aligned_storage_t = typename aligned_storage::type; +#endif + + //*************************************************************************** + /// Aligned storage as + ///\ingroup alignment + //*************************************************************************** + template + struct aligned_storage_as : public etl::aligned_storage::value> + { + }; + +#if ETL_CPP14_SUPPORTED + template + using aligned_storage_as_t = typename aligned_storage_as::type; +#endif +} + +#endif diff --git a/src/etl/array.h b/src/etl/array.h new file mode 100644 index 0000000..410603c --- /dev/null +++ b/src/etl/array.h @@ -0,0 +1,681 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2014 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_INCLUDED +#define ETL_ARRAY_INCLUDED + +#include + +#include "platform.h" + +#include "algorithm.h" +#include "iterator.h" +#include "functional.h" +#include "exception.h" +#include "type_traits.h" +#include "parameter_type.h" +#include "static_assert.h" +#include "error_handler.h" + +///\defgroup array array +/// A replacement for std::array if you haven't got C++0x11. +///\ingroup containers + +namespace etl +{ + //*************************************************************************** + ///\ingroup array + /// The base class for array exceptions. + //*************************************************************************** + class array_exception : public exception + { + public: + + array_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + : exception(reason_, file_name_, line_number_) + { + } + }; + + //*************************************************************************** + ///\ingroup array + /// The out of range exceptions. + //*************************************************************************** + class array_out_of_range : public array_exception + { + public: + + array_out_of_range(string_type file_name_, numeric_type line_number_) + : array_exception("array:range", file_name_, line_number_) + { + } + }; + + //*************************************************************************** + ///\ingroup array + /// A replacement for std::array if you haven't got C++0x11. + //*************************************************************************** + template + class array + { + private: + + typedef typename etl::parameter_type::type parameter_t; + + public: + + enum + { + SIZE = SIZE_ + }; + + typedef T value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_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 ETL_OR_STD::reverse_iterator reverse_iterator; + typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; + + //************************************************************************* + // Element access + //************************************************************************* + + //************************************************************************* + /// Returns a reference to the value at index 'i'. + ///\param i The index of the element to access. + //************************************************************************* + reference at(size_t i) + { + ETL_ASSERT(i < SIZE, ETL_ERROR(array_out_of_range)); + + return _buffer[i]; + } + + //************************************************************************* + /// Returns a const reference to the value at index 'i'. + ///\param i The index of the element to access. + //************************************************************************* + const_reference at(size_t i) const + { + ETL_ASSERT(i < SIZE, ETL_ERROR(array_out_of_range)); + + return _buffer[i]; + } + + //************************************************************************* + /// [] operator. + /// Returns a reference to the value at index 'i'. + ///\param i The index of the element to access. + //************************************************************************* + reference operator[](size_t i) + { + return _buffer[i]; + } + + //************************************************************************* + /// [] operator. + /// Returns a const reference to the value at index 'i'. + ///\param i The index of the element to access. + //************************************************************************* + const_reference operator[](size_t i) const + { + return _buffer[i]; + } + + //************************************************************************* + /// Returns a reference to the first element. + //************************************************************************* + reference front() + { + return _buffer[0]; + } + + //************************************************************************* + /// Returns a const reference to the first element. + //************************************************************************* + const_reference front() const + { + return _buffer[0]; + } + + //************************************************************************* + /// Returns a reference to the last element. + //************************************************************************* + reference back() + { + return _buffer[SIZE - 1]; + } + + //************************************************************************* + /// Returns a const reference to the last element. + //************************************************************************* + const_reference back() const + { + return _buffer[SIZE - 1]; + } + + //************************************************************************* + /// Returns a pointer to the first element of the internal buffer. + //************************************************************************* + pointer data() + { + return &_buffer[0]; + } + + //************************************************************************* + /// Returns a const pointer to the first element of the internal buffer. + //************************************************************************* + const_pointer data() const + { + return &_buffer[0]; + } + + //************************************************************************* + // Iterators + //************************************************************************* + + //************************************************************************* + /// Returns an iterator to the beginning of the array. + //************************************************************************* + iterator begin() + { + return &_buffer[0]; + } + + //************************************************************************* + /// Returns a const iterator to the beginning of the array. + //************************************************************************* + const_iterator begin() const + { + return &_buffer[0]; + } + + //************************************************************************* + /// Returns a const iterator to the beginning of the array. + //************************************************************************* + const_iterator cbegin() const + { + return begin(); + } + + //************************************************************************* + /// Returns an iterator to the end of the array. + //************************************************************************* + iterator end() + { + return &_buffer[SIZE]; + } + + //************************************************************************* + /// Returns a const iterator to the end of the array. + //************************************************************************* + const_iterator end() const + { + return &_buffer[SIZE]; + } + + //************************************************************************* + // Returns a const iterator to the end of the array. + //************************************************************************* + const_iterator cend() const + { + return &_buffer[SIZE]; + } + + //************************************************************************* + // Returns an reverse iterator to the reverse beginning of the array. + //************************************************************************* + reverse_iterator rbegin() + { + return reverse_iterator(end()); + } + + //************************************************************************* + /// Returns a const reverse iterator to the reverse beginning of the array. + //************************************************************************* + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(end()); + } + + //************************************************************************* + /// Returns a const reverse iterator to the reverse beginning of the array. + //************************************************************************* + const_reverse_iterator crbegin() const + { + return const_reverse_iterator(end()); + } + + //************************************************************************* + /// Returns a reverse iterator to the end of the array. + //************************************************************************* + reverse_iterator rend() + { + return reverse_iterator(begin()); + } + + //************************************************************************* + /// Returns a const reverse iterator to the end of the array. + //************************************************************************* + const_reverse_iterator rend() const + { + return const_reverse_iterator(begin()); + } + + //************************************************************************* + /// Returns a const reverse iterator to the end of the array. + //************************************************************************* + const_reverse_iterator crend() const + { + return const_reverse_iterator(begin()); + } + + //************************************************************************* + // Capacity + //************************************************************************* + + //************************************************************************* + /// Returns true if the array size is zero. + //************************************************************************* + bool empty() const + { + return (SIZE == 0); + } + + //************************************************************************* + /// Returns the size of the array. + //************************************************************************* + size_t size() const + { + return SIZE; + } + + //************************************************************************* + /// Returns the maximum possible size of the array. + //************************************************************************* + size_t max_size() const + { + return SIZE; + } + + //************************************************************************* + // Operations + //************************************************************************* + + //************************************************************************* + /// Fills the array with the specified value. + ///\param value The value to fill the array with. + //************************************************************************* + void fill(parameter_t value) + { + etl::fill(begin(), end(), value); + } + + //************************************************************************* + /// Swaps the contents of this array and another. + ///\param other A reference to the other array. + //************************************************************************* + void swap(array& other) + { + using ETL_OR_STD::swap; // Allow ADL + + for (size_t i = 0; i < SIZE; ++i) + { + swap(_buffer[i], other._buffer[i]); + } + } + + //************************************************************************* + /// Fills the array from the range. + /// If the range is smaller than the array then the unused array elements are left unmodified. + ///\param first The iterator to the first item in the ramge. + ///\param last The iterator to one past the final item in the range. + //************************************************************************* + template + void assign(TIterator first, const TIterator last) + { + etl::copy_s(first, last, begin(), end()); + } + + //************************************************************************* + /// Fills the array from the range. + /// If the range is smaller than the array then the unused array elements are initialised with the supplied value. + ///\param first The iterator to the first item in the ramge. + ///\param last The iterator to one past the final item in the range. + //************************************************************************* + template + void assign(TIterator first, const TIterator last, parameter_t value) + { + // Copy from the range. + iterator p = etl::copy(first, last, begin()); + + // Initialise any that are left. + etl::fill(p, end(), value); + } + + //************************************************************************* + /// Inserts a value into the array. + ///\param position The index of the position to insert at. + ///\param value The value to insert. + //************************************************************************* + inline iterator insert_at(size_t position, parameter_t value) + { + return insert(begin() + position, value); + } + + //************************************************************************* + /// Inserts a value into the array. + ///\param position The iterator to the position to insert at. + ///\param value The value to insert. + //************************************************************************* + iterator insert(const_iterator position, parameter_t value) + { + iterator p = const_cast(position); + + etl::move_backward(p, end() - 1, end()); + *p = value; + + return p; + } + + //************************************************************************* + /// Insert into the array from the range. + ///\param position The position to insert at. + ///\param first The iterator to the first item in the range. + ///\param last The iterator to one past the final item in the range. + //************************************************************************* + template + inline iterator insert_at(size_t position, TIterator first, const TIterator last) + { + return insert(begin() + position, first, last); + } + + //************************************************************************* + /// Insert into the array from the range. + ///\param position The position to insert at. + ///\param first The iterator to the first item in the range. + ///\param last The iterator to one past the final item in the range. + //************************************************************************* + template + iterator insert(const_iterator position, TIterator first, const TIterator last) + { + iterator p = const_cast(position); + iterator result(p); + + size_t source_size = etl::distance(first, last); + size_t destination_space = etl::distance(position, cend()); + + // Do we need to move anything? + if (source_size < destination_space) + { + size_t length = SIZE - (etl::distance(begin(), p) + source_size); + etl::move_backward(p, p + length, end()); + } + + // Copy from the range. + etl::copy_s(first, last, p, end()); + + return result; + } + + //************************************************************************* + /// Erases a value from the array. + /// After erase, the last value in the array will be unmodified. + ///\param position The index of the position to erase at. + //************************************************************************* + inline iterator erase_at(size_t position) + { + return erase(begin() + position); + } + + //************************************************************************* + /// Erases a value from the array. + /// After erase, the last value in the array will be unmodified. + ///\param position The iterator to the position to erase at. + //************************************************************************* + iterator erase(const_iterator position) + { + iterator p = const_cast(position); + etl::move(p + 1, end(), p); + + return p; + } + + //************************************************************************* + /// Erases a range of values from the array. + /// After erase, the last values in the array will be unmodified. + ///\param first The first item to erase. + ///\param last The one past the last item to erase. + //************************************************************************* + iterator erase_range(size_t first, size_t last) + { + return erase(begin() + first, begin() + last); + } + + //************************************************************************* + /// Erases a range of values from the array. + /// After erase, the last values in the array will be unmodified. + ///\param first The first item to erase. + ///\param last The one past the last item to erase. + //************************************************************************* + iterator erase(const_iterator first, const_iterator last) + { + iterator p = const_cast(first); + etl::move(last, cend(), p); + return p; + } + + //************************************************************************* + /// Erases a value from the array. + ///\param position The index of the position to erase at. + ///\param value The value to use to overwrite the last element in the array. + //************************************************************************* + inline iterator erase_at(size_t position, parameter_t value) + { + return erase(begin() + position, value); + } + + //************************************************************************* + /// Erases a value from the array. + ///\param position The iterator to the position to erase at. + ///\param value The value to use to overwrite the last element in the array. + //************************************************************************* + iterator erase(const_iterator position, parameter_t value) + { + iterator p = const_cast(position); + + etl::move(p + 1, end(), p); + back() = value; + + return p; + } + + //************************************************************************* + /// Erases a range of values from the array. + ///\param first The first item to erase. + ///\param last The one past the last item to erase. + ///\param value The value to use to overwrite the last elements in the array. + //************************************************************************* + iterator erase_range(size_t first, size_t last, parameter_t value) + { + return erase(begin() + first, begin() + last, value); + } + + //************************************************************************* + /// Erases a range of values from the array. + ///\param position The iterator to the position to erase at. + ///\param value The value to use to overwrite the last elements in the array. + //************************************************************************* + iterator erase(const_iterator first, const_iterator last, parameter_t value) + { + iterator p = const_cast(first); + + p = etl::move(last, cend(), p); + etl::fill(p, end(), value); + + return const_cast(first); + } + + /// The array data. + T _buffer[SIZE]; + }; + + //************************************************************************* + /// Template deduction guides. + //************************************************************************* +#if ETL_CPP17_SUPPORTED + template + array(T, Ts...) + -> array && ...), T>, 1U + sizeof...(Ts)>; +#endif + + //************************************************************************* + /// Overloaded swap for etl::array + ///\param lhs The first array. + ///\param rhs The second array. + //************************************************************************* + template + void swap(etl::array &lhs, etl::array &rhs) + { + lhs.swap(rhs); + } + + //************************************************************************* + /// Equal operator. + ///\param lhs The first array. + ///\param rhs The second array. + ///\return true if the arrays are equal, otherwise false + //************************************************************************* + template + bool operator ==(const etl::array& lhs, const etl::array& rhs) + { + return etl::equal(lhs.cbegin(), lhs.cend(), rhs.cbegin()); + } + + //************************************************************************* + /// Not equal operator. + ///\param lhs The first array. + ///\param rhs The second array. + ///\return true if the arrays are not equal, otherwise false + //************************************************************************* + template + bool operator !=(const etl::array& lhs, const etl::array& rhs) + { + return !(lhs == rhs); + } + + //************************************************************************* + /// Less than operator. + ///\param lhs The first array. + ///\param rhs The second array. + ///\return true if the first array is lexicographically less than the second, otherwise false + //************************************************************************* + template + bool operator <(const etl::array& lhs, const etl::array& rhs) + { + return etl::lexicographical_compare(lhs.cbegin(), + lhs.cend(), + rhs.cbegin(), + rhs.cend()); + } + + //************************************************************************* + /// Less than or equal operator. + ///\param lhs The first array. + ///\param rhs The second array. + ///\return true if the first array is lexicographically less than or equal to the second, otherwise false + //************************************************************************* + template + bool operator <=(const etl::array& lhs, const etl::array& rhs) + { + return !(lhs > rhs); + } + + //************************************************************************* + /// Greater than operator. + ///\param lhs The first array. + ///\param rhs The second array. + ///\return true if the first array is lexicographically greater than the second, otherwise false + template + //************************************************************************* + bool operator >(const etl::array& lhs, const etl::array& rhs) + { + return (rhs < lhs); + } + + //************************************************************************* + /// Greater than or equal operator. + ///\param lhs The first array. + ///\param rhs The second array. + ///\return true if the first array is lexicographically greater than or equal to the second, otherwise false + //************************************************************************* + template + bool operator >=(const etl::array& lhs, const etl::array& rhs) + { + return !(lhs < rhs); + } + + //************************************************************************* + /// Gets a reference to an element in the array. + ///\tparam I The index. + ///\tparam T The type. + ///\tparam MAXN The array size. + ///\param a The array. + ///\return A reference to the element + //************************************************************************* + template + inline T& get(array& a) + { + ETL_STATIC_ASSERT(I < MAXN, "Index out of bounds"); + return a[I]; + } + + //************************************************************************* + /// Gets a const reference to an element in the array. + ///\tparam I The index. + ///\tparam T The type. + ///\tparam MAXN The array size. + ///\param a The array. + ///\return A const reference to the element + //************************************************************************* + template + inline const T& get(const array& a) + { + ETL_STATIC_ASSERT(I < MAXN, "Index out of bounds"); + return a[I]; + } +} + +#endif diff --git a/src/etl/array_view.h b/src/etl/array_view.h new file mode 100644 index 0000000..09cbef7 --- /dev/null +++ b/src/etl/array_view.h @@ -0,0 +1,554 @@ +///\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_VIEW_INCLUDED +#define ETL_ARRAY_VIEW_INCLUDED + +#include "platform.h" +#include "memory.h" +#include "iterator.h" +#include "error_handler.h" +#include "exception.h" +#include "nullptr.h" +#include "hash.h" +#include "algorithm.h" +#include "memory.h" +#include "type_traits.h" + +///\defgroup array array +/// A wrapper for arrays +///\ingroup containers + +#undef ETL_FILE +#define ETL_FILE "41" + +namespace etl +{ + //*************************************************************************** + /// The base class for array_view exceptions. + //*************************************************************************** + class array_view_exception : public exception + { + public: + + array_view_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_view_bounds : public array_view_exception + { + public: + + array_view_bounds(string_type file_name_, numeric_type line_number_) + : array_view_exception(ETL_ERROR_TEXT("array_view:bounds", ETL_FILE"A"), file_name_, line_number_) + { + } + }; + + //*************************************************************************** + ///\ingroup stack + /// The exception thrown when the view is uninitialised. + //*************************************************************************** + class array_view_uninitialised : public array_view_exception + { + public: + + array_view_uninitialised(string_type file_name_, numeric_type line_number_) + : array_view_exception(ETL_ERROR_TEXT("array_view:uninitialised", ETL_FILE"B"), file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// Array view. + //*************************************************************************** + template + class array_view + { + public: + + typedef T value_type; + typedef size_t size_type; + typedef const T& const_reference; + typedef const T* const_pointer; + typedef const T* const_iterator; + typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; + +#if defined(ETL_ARRAY_VIEW_IS_MUTABLE) + typedef T* pointer; + typedef T& reference; + typedef T* iterator; + typedef ETL_OR_STD::reverse_iterator reverse_iterator; +#else + typedef const_pointer pointer; + typedef const_reference reference; + typedef const_pointer iterator; + typedef const_reverse_iterator reverse_iterator; +#endif + + //************************************************************************* + /// Default constructor. + //************************************************************************* + ETL_CONSTEXPR array_view() + : mbegin(ETL_NULLPTR), + mend(ETL_NULLPTR) + { + } + + //************************************************************************* + /// Construct from std::array or etl::array or other type that supports + /// data() and size() member functions. + //************************************************************************* + template + ETL_CONSTEXPR array_view(TArray& a) + : mbegin(a.data()), + mend(a.data() + a.size()) + { + } + + //************************************************************************* + /// Construct from iterators + //************************************************************************* + template + ETL_CONSTEXPR array_view(const TIterator begin_, const TIterator end_) + : mbegin(etl::addressof(*begin_)), + mend(etl::addressof(*begin_) + etl::distance(begin_, end_)) + { + } + + //************************************************************************* + /// Construct from C array + //************************************************************************* + template + ETL_CONSTEXPR array_view(const TIterator begin_, const TSize size_) + : mbegin(etl::addressof(*begin_)), + mend(etl::addressof(*begin_) + size_) + { + } + + //************************************************************************* + /// Construct from C array + //************************************************************************* + template + ETL_CONSTEXPR array_view(T(&begin_)[ARRAY_SIZE]) + : mbegin(begin_), + mend(begin_ + ARRAY_SIZE) + { + } + + //************************************************************************* + /// Copy constructor + //************************************************************************* + ETL_CONSTEXPR array_view(const array_view& other) + : mbegin(other.mbegin), + mend(other.mend) + { + } + + //************************************************************************* + /// Returns a reference to the first element. + //************************************************************************* + reference front() + { + return *mbegin; + } + + //************************************************************************* + /// Returns a const reference to the first element. + //************************************************************************* + const_reference front() const + { + return *mbegin; + } + + //************************************************************************* + /// Returns a reference to the last element. + //************************************************************************* + reference back() + { + return *(mend - 1); + } + + //************************************************************************* + /// Returns a const reference to the last element. + //************************************************************************* + const_reference back() const + { + return *(mend - 1); + } + + //************************************************************************* + /// Returns a pointer to the first element of the internal storage. + //************************************************************************* + pointer data() + { + return mbegin; + } + + //************************************************************************* + /// Returns a const pointer to the first element of the internal storage. + //************************************************************************* + const_pointer data() const + { + return mbegin; + } + + //************************************************************************* + /// Returns an iterator to the beginning of the array. + //************************************************************************* + iterator begin() + { + return mbegin; + } + + //************************************************************************* + /// Returns a const iterator to the beginning of the array. + //************************************************************************* + const_iterator begin() const + { + return mbegin; + } + + //************************************************************************* + /// Returns a const iterator to the beginning of the array. + //************************************************************************* + const_iterator cbegin() const + { + return mbegin; + } + + //************************************************************************* + /// Returns an iterator to the end of the array. + //************************************************************************* + iterator end() + { + return mend; + } + + //************************************************************************* + /// Returns a const iterator to the end of the array. + //************************************************************************* + const_iterator end() const + { + return mend; + } + + //************************************************************************* + // Returns a const iterator to the end of the array. + //************************************************************************* + const_iterator cend() const + { + return mend; + } + + //************************************************************************* + // Returns an reverse iterator to the reverse beginning of the array. + //************************************************************************* + reverse_iterator rbegin() + { + return reverse_iterator(mend); + } + + //************************************************************************* + /// Returns a const reverse iterator to the reverse beginning of the array. + //************************************************************************* + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(mend); + } + + //************************************************************************* + /// Returns a const reverse iterator to the reverse beginning of the array. + //************************************************************************* + const_reverse_iterator crbegin() const + { + return const_reverse_iterator(mend); + } + + //************************************************************************* + /// Returns a reverse iterator to the end of the array. + //************************************************************************* + reverse_iterator rend() + { + return reverse_iterator(mbegin); + } + + //************************************************************************* + /// Returns a const reverse iterator to the end of the array. + //************************************************************************* + const_reverse_iterator rend() const + { + return const_reverse_iterator(mbegin); + } + + //************************************************************************* + /// Returns a const reverse iterator to the end of the array. + //************************************************************************* + const_reverse_iterator crend() const + { + return const_reverse_iterator(mbegin); + } + + //************************************************************************* + /// Returns true if the array size is zero. + //************************************************************************* + bool empty() const + { + return (mbegin == mend); + } + + //************************************************************************* + /// Returns the size of the array. + //************************************************************************* + size_t size() const + { + return (mend - mbegin); + } + + //************************************************************************* + /// Returns the maximum possible size of the array. + //************************************************************************* + size_t max_size() const + { + return size(); + } + + //************************************************************************* + /// Assign from a view. + //************************************************************************* + array_view& operator=(const array_view& other) + { + mbegin = other.mbegin; + mend = other.mend; + return *this; + } + + //************************************************************************* + /// Assign from iterators + //************************************************************************* + template + void assign(const TIterator begin_, const TIterator end_) + { + mbegin = etl::addressof(*begin_); + mend = etl::addressof(*begin_) + etl::distance(begin_, end_); + } + + //************************************************************************* + /// Assign from iterator and size. + //************************************************************************* + template + void assign(const TIterator begin_, const TSize size_) + { + mbegin = etl::addressof(*begin_); + mend = etl::addressof(*begin_) + size_; + } + +#if defined(ETL_ARRAY_VIEW_IS_MUTABLE) + //************************************************************************* + /// Returns a reference to the indexed value. + //************************************************************************* + reference operator[](const size_t i) + { + return mbegin[i]; + } +#endif + + //************************************************************************* + /// Returns a const reference to the indexed value. + //************************************************************************* + const_reference operator[](const size_t i) const + { + return mbegin[i]; + } + +#if defined(ETL_ARRAY_VIEW_IS_MUTABLE) + //************************************************************************* + /// Returns a reference to the indexed value. + //************************************************************************* + reference at(const size_t i) + { + ETL_ASSERT((mbegin != ETL_NULLPTR && mend != ETL_NULLPTR), ETL_ERROR(array_view_uninitialised)); + ETL_ASSERT(i < size(), ETL_ERROR(array_view_bounds)); + return mbegin[i]; + } +#endif + + //************************************************************************* + /// Returns a const reference to the indexed value. + //************************************************************************* + const_reference at(const size_t i) const + { + ETL_ASSERT((mbegin != ETL_NULLPTR && mend != ETL_NULLPTR), ETL_ERROR(array_view_uninitialised)); + ETL_ASSERT(i < size(), ETL_ERROR(array_view_bounds)); + return mbegin[i]; + } + + //************************************************************************* + /// Swaps with another array_view. + //************************************************************************* + void swap(array_view& other) + { + using ETL_OR_STD::swap; // Allow ADL + + swap(mbegin, other.mbegin); + swap(mend, other.mend); + } + + //************************************************************************* + /// Shrinks the view by moving its start forward. + //************************************************************************* + void remove_prefix(const size_type n) + { + if (n < size()) + mbegin += n; + else + mbegin = mend; + } + + //************************************************************************* + /// Shrinks the view by moving its end backward. + //************************************************************************* + void remove_suffix(const size_type n) + { + if (n < size()) + mend -= n; + else + mend = mbegin; + } + + //************************************************************************* + /// Equality for array views. + //************************************************************************* + friend bool operator == (const array_view& lhs, const array_view& rhs) + { + return (lhs.size() == rhs.size()) && + etl::equal(lhs.begin(), lhs.end(), rhs.begin()); + } + + //************************************************************************* + /// Inequality for array views. + //************************************************************************* + friend bool operator != (const array_view& lhs, const array_view& rhs) + { + return !(lhs == rhs); + } + + //************************************************************************* + /// Less-than for array views. + //************************************************************************* + friend bool operator < (const array_view& lhs, const array_view& rhs) + { + return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); + } + + //************************************************************************* + /// Greater-than for array views. + //************************************************************************* + friend bool operator > (const array_view& lhs, const array_view& rhs) + { + return rhs < lhs; + } + + //************************************************************************* + /// Less-than-equal for array views. + //************************************************************************* + friend bool operator <= (const array_view& lhs, const array_view& rhs) + { + return !(lhs > rhs); + } + + //************************************************************************* + /// Greater-than-equal for array views. + //************************************************************************* + friend bool operator >= (const array_view& lhs, const array_view& rhs) + { + return !(lhs < rhs); + } + + private: + + pointer mbegin; + pointer mend; + }; + + //************************************************************************* + /// Template deduction guides. + //************************************************************************* +#if ETL_CPP17_SUPPORTED + template + array_view(TArray& a) + -> array_view; + + template + array_view(const TIterator begin_, const TIterator end_) + -> array_view>; + + template + array_view(const TIterator begin_, const TSize size_) + -> array_view>; +#endif + + //************************************************************************* + /// Hash function. + //************************************************************************* +#if ETL_8BIT_SUPPORT + template + struct hash > + { + size_t operator()(const etl::array_view& view) const + { + return etl::private_hash::generic_hash(reinterpret_cast(&view[0]), + reinterpret_cast(&view[view.size()])); + } + }; +#endif +} + +//************************************************************************* +/// Swaps the values. +//************************************************************************* +template +void swap(etl::array_view& lhs, etl::array_view& rhs) +{ + lhs.swap(rhs); +} + +#undef ETL_FILE + +#endif diff --git a/src/etl/array_wrapper.h b/src/etl/array_wrapper.h new file mode 100644 index 0000000..cf72edb --- /dev/null +++ b/src/etl/array_wrapper.h @@ -0,0 +1,423 @@ +///\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_INCLUDED +#define ETL_ARRAY_WRAPPER_INCLUDED + +#include "platform.h" +#include "iterator.h" +#include "error_handler.h" +#include "exception.h" +#include "hash.h" +#include "container.h" +#include "parameter_type.h" + +#include "algorithm.h" + +///\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 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 ETL_OR_STD::reverse_iterator reverse_iterator; + typedef ETL_OR_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. + //************************************************************************* + 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. + //************************************************************************* + 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. + //************************************************************************* + 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. + //************************************************************************* + 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. + //************************************************************************* + 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. + //************************************************************************* + 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. + //************************************************************************* + 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. + //************************************************************************* + 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. + //************************************************************************* + 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. + //************************************************************************* + 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) + { + etl::fill(begin(), end(), value); + } + + //************************************************************************* + /// Swaps the contents of arrays. + //************************************************************************* + template + typename etl::enable_if::value, void>::type + swap(etl::array_wrapper& other) + { + using ETL_OR_STD::swap; // Allow ADL + + for (size_t i = 0; i < SIZE; ++i) + { + 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) && etl::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 etl::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/etl/atomic.h b/src/etl/atomic.h new file mode 100644 index 0000000..8e03029 --- /dev/null +++ b/src/etl/atomic.h @@ -0,0 +1,53 @@ +/****************************************************************************** +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_ATOMIC_INCLUDED +#define ETL_ATOMIC_INCLUDED + +#include "platform.h" + +#if ETL_CPP11_SUPPORTED && (ETL_USING_STL || defined(ETL_IN_UNIT_TEST)) + #include "atomic/atomic_std.h" + #define ETL_HAS_ATOMIC 1 +#elif defined(ETL_COMPILER_ARM5) + #include "atomic/atomic_arm.h" + #define ETL_HAS_ATOMIC 1 +#elif defined(ETL_COMPILER_ARM6) + #include "atomic/atomic_arm.h" + #define ETL_HAS_ATOMIC 1 +#elif defined(ETL_COMPILER_GCC) + #include "atomic/atomic_gcc_sync.h" + #define ETL_HAS_ATOMIC 1 +#elif defined(ETL_COMPILER_CLANG) + #include "atomic/atomic_clang_sync.h" + #define ETL_HAS_ATOMIC 1 +#else + #define ETL_HAS_ATOMIC 0 +#endif + +#endif diff --git a/src/etl/atomic/atomic_arm.h b/src/etl/atomic/atomic_arm.h new file mode 100644 index 0000000..9893fee --- /dev/null +++ b/src/etl/atomic/atomic_arm.h @@ -0,0 +1,34 @@ +/****************************************************************************** +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_ATOMIC_ARM_INCLUDED +#define ETL_ATOMIC_ARM_INCLUDED + +#include "atomic_gcc_sync.h" + +#endif diff --git a/src/etl/atomic/atomic_clang_sync.h b/src/etl/atomic/atomic_clang_sync.h new file mode 100644 index 0000000..d4a3c93 --- /dev/null +++ b/src/etl/atomic/atomic_clang_sync.h @@ -0,0 +1,34 @@ +/****************************************************************************** +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_ATOMIC_CLANG_INCLUDED +#define ETL_ATOMIC_CLANG_INCLUDED + +#include "atomic_gcc_sync.h" + +#endif \ No newline at end of file diff --git a/src/etl/atomic/atomic_gcc_sync.h b/src/etl/atomic/atomic_gcc_sync.h new file mode 100644 index 0000000..be18865 --- /dev/null +++ b/src/etl/atomic/atomic_gcc_sync.h @@ -0,0 +1,810 @@ +/****************************************************************************** +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_ATOMIC_GCC_SYNC_INCLUDED +#define ETL_ATOMIC_GCC_SYNC_INCLUDED + +#include "../platform.h" +#include "../type_traits.h" +#include "../static_assert.h" +#include "../nullptr.h" +#include "../char_traits.h" + +#include +#include + +#if defined(ETL_COMPILER_GCC) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wunused-value" +#endif + +namespace etl +{ + //*************************************************************************** + // Atomic type for pre C++11 GCC compilers that support the builtin '__sync' functions. + // Only integral and pointer types are supported. + //*************************************************************************** + + typedef enum memory_order + { + memory_order_relaxed, + memory_order_consume, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst + } memory_order; + + //*************************************************************************** + /// For all types except bool and pointers + //*************************************************************************** + template + class atomic + { + public: + + ETL_STATIC_ASSERT(etl::is_integral::value, "Only integral types are supported"); + + atomic() + : value(0) + { + } + + atomic(T v) + : value(v) + { + } + + // Assignment + T operator =(T v) + { + store(v); + + return v; + } + + T operator =(T v) volatile + { + store(v); + + return v; + } + + // Pre-increment + T operator ++() + { + return __sync_add_and_fetch(&value, 1); + } + + T operator ++() volatile + { + return __sync_add_and_fetch(&value, 1); + } + + // Post-increment + T operator ++(int) + { + return __sync_fetch_and_add(&value, 1); + } + + T operator ++(int) volatile + { + return __sync_fetch_and_add(&value, 1); + } + + // Pre-decrement + T operator --() + { + return __sync_sub_and_fetch(&value, 1); + } + + T operator --() volatile + { + return __sync_sub_and_fetch(&value, 1); + } + + // Post-decrement + T operator --(int) + { + return __sync_fetch_and_sub(&value, 1); + } + + T operator --(int) volatile + { + return __sync_fetch_and_sub(&value, 1); + } + + // Add + T operator +=(T v) + { + return __sync_fetch_and_add(&value, v); + } + + T operator +=(T v) volatile + { + return __sync_fetch_and_add(&value, v); + } + + // Subtract + T operator -=(T v) + { + return __sync_fetch_and_sub(&value, v); + } + + T operator -=(T v) volatile + { + return __sync_fetch_and_sub(&value, v); + } + + // And + T operator &=(T v) + { + return __sync_fetch_and_and(&value, v); + } + + T operator &=(T v) volatile + { + return __sync_fetch_and_and(&value, v); + } + + // Or + T operator |=(T v) + { + return __sync_fetch_and_or(&value, v); + } + + T operator |=(T v) volatile + { + return __sync_fetch_and_or(&value, v); + } + + // Exclusive or + T operator ^=(T v) + { + return __sync_fetch_and_xor(&value, v); + } + + T operator ^=(T v) volatile + { + return __sync_fetch_and_xor(&value, v); + } + + // Conversion operator + operator T () const + { + return __sync_fetch_and_add(&value, 0); + } + + operator T() volatile const + { + return __sync_fetch_and_add(&value, 0); + } + + // Is lock free? + bool is_lock_free() const + { + return true; + } + + bool is_lock_free() const volatile + { + return true; + } + + // Store + void store(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + (void)__sync_lock_test_and_set(&value, v); + } + + void store(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + (void)__sync_lock_test_and_set(&value, v); + } + + // Load + T load(etl::memory_order order = etl::memory_order_seq_cst) const + { + return __sync_fetch_and_add(&value, 0); + } + + T load(etl::memory_order order = etl::memory_order_seq_cst) const volatile + { + return __sync_fetch_and_add(&value, 0); + } + + // Fetch add + T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return __sync_fetch_and_add(&value, v); + } + + T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return __sync_fetch_and_add(&value, v); + } + + // Fetch subtract + T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return __sync_fetch_and_sub(&value, v); + } + + T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return __sync_fetch_and_sub(&value, v); + } + + // Fetch or + T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return __sync_fetch_and_or(&value, v); + } + + T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return __sync_fetch_and_or(&value, v); + } + + // Fetch and + T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return __sync_fetch_and_and(&value, v); + } + + T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return __sync_fetch_and_and(&value, v); + } + + // Fetch exclusive or + T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return __sync_fetch_and_xor(&value, v); + } + + T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return __sync_fetch_and_xor(&value, v); + } + + // Exchange + T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return __sync_lock_test_and_set(&value, v); + } + + T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return __sync_lock_test_and_set(&value, v); + } + + // Compare exchange weak + bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) + { + T old = __sync_val_compare_and_swap(&value, expected, desired); + + if (old == expected) + { + return true; + } + else + { + expected = old; + return false; + } + } + + bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + T old = __sync_val_compare_and_swap(&value, expected, desired); + + if (old == expected) + { + return true; + } + else + { + expected = old; + return false; + } + } + + bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) + { + T old = __sync_val_compare_and_swap(&value, expected, desired); + + if (old == expected) + { + return true; + } + else + { + expected = old; + return false; + } + } + + bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile + { + T old = __sync_val_compare_and_swap(&value, expected, desired); + + if (old == expected) + { + return true; + } + else + { + expected = old; + return false; + } + } + + // Compare exchange strong + bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) + { + T old = expected; + + while (!compare_exchange_weak(old, desired)) + { + if (memcmp(&old, &expected, sizeof(T))) + { + expected = old; + return false; + } + } + + return true; + } + + bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + T old = expected; + + while (!compare_exchange_weak(old, desired)) + { + if (memcmp(&old, &expected, sizeof(T))) + { + expected = old; + return false; + } + } + + return true; + } + + bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) + { + T old = expected; + + while (!compare_exchange_weak(old, desired)) + { + if (memcmp(&old, &expected, sizeof(T))) + { + expected = old; + return false; + } + } + + return true; + } + + bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile + { + T old = expected; + + while (!compare_exchange_weak(old, desired)) + { + if (memcmp(&old, &expected, sizeof(T))) + { + expected = old; + return false; + } + } + + return true; + } + + private: + + atomic& operator =(const atomic&) ETL_DELETE; + atomic& operator =(const atomic&) volatile ETL_DELETE; + + mutable volatile T value; + }; + + //*************************************************************************** + /// Specialisation for pointers + //*************************************************************************** + template + class atomic + { + public: + + atomic() + : value(0U) + { + } + + atomic(T* v) + : value(uintptr_t(v)) + { + } + + // Assignment + T* operator =(T* v) + { + store(v); + + return v; + } + + T* operator =(T* v) volatile + { + store(v); + + return v; + } + + // Pre-increment + T* operator ++() + { + return (T*)__sync_add_and_fetch(&value, sizeof(T)); + } + + T* operator ++() volatile + { + return (T*)__sync_add_and_fetch(&value, sizeof(T)); + } + + // Post-increment + T* operator ++(int) + { + return (T*)__sync_fetch_and_add(&value, sizeof(T)); + } + + T* operator ++(int) volatile + { + return (T*)__sync_fetch_and_add(&value, sizeof(T)); + } + + // Pre-decrement + T* operator --() + { + return (T*)__sync_sub_and_fetch(&value, sizeof(T)); + } + + T* operator --() volatile + { + return (T*)__sync_sub_and_fetch(&value, sizeof(T)); + } + + // Post-decrement + T* operator --(int) + { + return (T*)__sync_fetch_and_sub(&value, sizeof(T)); + } + + T* operator --(int) volatile + { + return (T*)__sync_fetch_and_sub(&value, sizeof(T)); + } + + // Add + T* operator +=(ptrdiff_t v) + { + return (T*)__sync_fetch_and_add(&value, v * sizeof(T)); + } + + T* operator +=(ptrdiff_t v) volatile + { + return (T*)__sync_fetch_and_add(&value, v * sizeof(T)); + } + + // Subtract + T* operator -=(ptrdiff_t v) + { + return (T*)__sync_fetch_and_sub(&value, v * sizeof(T)); + } + + T* operator -=(ptrdiff_t v) volatile + { + return (T*)__sync_fetch_and_sub(&value, v * sizeof(T)); + } + + // Conversion operator + operator T* () const + { + return (T*)__sync_fetch_and_add(&value, 0); + } + + operator T*() volatile const + { + return (T*)__sync_fetch_and_add(&value, 0); + } + + // Is lock free? + bool is_lock_free() const + { + return true; + } + + bool is_lock_free() const volatile + { + return true; + } + + // Store + void store(T* v, etl::memory_order order = etl::memory_order_seq_cst) + { + __sync_lock_test_and_set(&value, uintptr_t(v)); + } + + void store(T* v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + __sync_lock_test_and_set(&value, uintptr_t(v)); + } + + // Load + T* load(etl::memory_order order = etl::memory_order_seq_cst) const + { + return (T*)__sync_fetch_and_add(&value, 0); + } + + T* load(etl::memory_order order = etl::memory_order_seq_cst) const volatile + { + return (T*)__sync_fetch_and_add(&value, 0); + } + + // Fetch add + T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) + { + return (T*)__sync_fetch_and_add(&value, v); + } + + T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return (T*)__sync_fetch_and_add(&value, v); + } + + // Fetch subtract + T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) + { + return (T*)__sync_fetch_and_sub(&value, v); + } + + T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return (T*)__sync_fetch_and_sub(&value, v); + } + + // Exchange + T* exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst) + { + return (T*)__sync_lock_test_and_set(&value, uintptr_t(v)); + } + + T* exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return (T*)__sync_lock_test_and_set(&value, uintptr_t(v)); + } + + // Compare exchange weak + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) + { + T* old = (T*)__sync_val_compare_and_swap(&value, uintptr_t(expected), uintptr_t(desired)); + + if (old == expected) + { + return true; + } + else + { + expected = old; + return false; + } + } + + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + T* old = (T*)__sync_val_compare_and_swap(&value, uintptr_t(expected), uintptr_t(desired)); + + if (old == expected) + { + return true; + } + else + { + expected = old; + return false; + } + } + + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) + { + T* old = (T*)__sync_val_compare_and_swap(&value, uintptr_t(expected), uintptr_t(desired)); + + if (old == expected) + { + return true; + } + else + { + expected = old; + return false; + } + } + + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) volatile + { + T* old = (T*)__sync_val_compare_and_swap(&value, uintptr_t(expected), uintptr_t(desired)); + + if (old == expected) + { + return true; + } + else + { + expected = old; + return false; + } + } + + // Compare exchange strong + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) + { + T* old = expected; + + while (!compare_exchange_weak(old, desired)) + { + if (memcmp(&old, &expected, sizeof(T*))) + { + expected = old; + return false; + } + } + + return true; + } + + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + T* old = expected; + + while (!compare_exchange_weak(old, desired)) + { + if (memcmp(&old, &expected, sizeof(T*))) + { + expected = old; + return false; + } + } + + return true; + } + + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) + { + T* old = expected; + + while (!compare_exchange_weak(old, desired)) + { + if (memcmp(&old, &expected, sizeof(T*))) + { + expected = old; + return false; + } + } + + return true; + } + + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) volatile + { + T* old = expected; + + while (!compare_exchange_weak(old, desired)) + { + if (memcmp(&old, &expected, sizeof(T*))) + { + expected = old; + return false; + } + } + + return true; + } + + private: + + atomic& operator =(const atomic&) ETL_DELETE; + atomic& operator =(const atomic&) volatile ETL_DELETE; + + mutable uintptr_t value; + }; + + typedef etl::atomic atomic_char; + typedef etl::atomic atomic_schar; + typedef etl::atomic atomic_uchar; + typedef etl::atomic atomic_short; + typedef etl::atomic atomic_ushort; + typedef etl::atomic atomic_int; + typedef etl::atomic atomic_uint; + typedef etl::atomic atomic_long; + typedef etl::atomic atomic_ulong; + typedef etl::atomic atomic_llong; + typedef etl::atomic atomic_ullong; + typedef etl::atomic atomic_wchar_t; + typedef etl::atomic atomic_char16_t; + typedef etl::atomic atomic_char32_t; +#if ETL_USING_8BIT_TYPES + typedef etl::atomic atomic_uint8_t; + typedef etl::atomic atomic_int8_t; +#endif + typedef etl::atomic atomic_uint16_t; + typedef etl::atomic atomic_int16_t; + typedef etl::atomic atomic_uint32_t; + typedef etl::atomic atomic_int32_t; +#if ETL_USING_64BIT_TYPES + typedef etl::atomic atomic_uint64_t; + typedef etl::atomic atomic_int64_t; +#endif + typedef etl::atomic atomic_int_least8_t; + typedef etl::atomic atomic_uint_least8_t; + typedef etl::atomic atomic_int_least16_t; + typedef etl::atomic atomic_uint_least16_t; + typedef etl::atomic atomic_int_least32_t; + typedef etl::atomic atomic_uint_least32_t; +#if ETL_USING_64BIT_TYPES + typedef etl::atomic atomic_int_least64_t; + typedef etl::atomic atomic_uint_least64_t; +#endif + typedef etl::atomic atomic_int_fast8_t; + typedef etl::atomic atomic_uint_fast8_t; + typedef etl::atomic atomic_int_fast16_t; + typedef etl::atomic atomic_uint_fast16_t; + typedef etl::atomic atomic_int_fast32_t; + typedef etl::atomic atomic_uint_fast32_t; +#if ETL_USING_64BIT_TYPES + typedef etl::atomic atomic_int_fast64_t; + typedef etl::atomic atomic_uint_fast64_t; +#endif + typedef etl::atomic atomic_intptr_t; + typedef etl::atomic atomic_uintptr_t; + typedef etl::atomic atomic_size_t; + typedef etl::atomic atomic_ptrdiff_t; + typedef etl::atomic atomic_intmax_t; + typedef etl::atomic atomic_uintmax_t; +} + +#if defined(ETL_COMPILER_GCC) +#pragma GCC diagnostic pop +#endif + +#endif diff --git a/src/etl/atomic/atomic_std.h b/src/etl/atomic/atomic_std.h new file mode 100644 index 0000000..7dce364 --- /dev/null +++ b/src/etl/atomic/atomic_std.h @@ -0,0 +1,614 @@ +/****************************************************************************** +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_ATOMIC_STD_INCLUDED +#define ETL_ATOMIC_STD_INCLUDED + +#include "../platform.h" +#include "../nullptr.h" +#include "../char_traits.h" + +#include +#include + +namespace etl +{ + //*************************************************************************** + // ETL Atomic type for compilers that support std::atomic. + // etl::atomic is a simple wrapper around std::atomic. + //*************************************************************************** + + typedef std::memory_order memory_order; + + static const etl::memory_order memory_order_relaxed = std::memory_order_relaxed; + static const etl::memory_order memory_order_consume = std::memory_order_consume; + static const etl::memory_order memory_order_acquire = std::memory_order_acquire; + static const etl::memory_order memory_order_release = std::memory_order_release; + static const etl::memory_order memory_order_acq_rel = std::memory_order_acq_rel; + static const etl::memory_order memory_order_seq_cst = std::memory_order_seq_cst; + + template + class atomic + { + public: + + atomic() + : value(0) + { + } + + atomic(T v) + : value(v) + { + } + + // Assignment + T operator =(T v) + { + return value = v; + } + + T operator =(T v) volatile + { + return value = v; + } + + // Pre-increment + T operator ++() + { + return ++value; + } + + T operator ++() volatile + { + return ++value; + } + + // Post-increment + T operator ++(int) + { + return value++; + } + + T operator ++(int) volatile + { + return value++; + } + + // Pre-decrement + T operator --() + { + return --value; + } + + T operator --() volatile + { + return --value; + } + + // Post-decrement + T operator --(int) + { + return value--; + } + + T operator --(int) volatile + { + return value--; + } + + // Add + T operator +=(T v) + { + return value += v; + } + + T operator +=(T v) volatile + { + return value += v; + } + + // Subtract + T operator -=(T v) + { + return value -= v; + } + + T operator -=(T v) volatile + { + return value -= v; + } + + // And + T operator &=(T v) + { + return value &= v; + } + + T operator &=(T v) volatile + { + return value &= v; + } + + // Or + T operator |=(T v) + { + return value |= v; + } + + T operator |=(T v) volatile + { + return value |= v; + } + + // Exclusive or + T operator ^=(T v) + { + return value ^= v; + } + + T operator ^=(T v) volatile + { + return value ^= v; + } + + // Conversion operator + operator T () const + { + return T(value); + } + + operator T() volatile const + { + return T(value); + } + + // Is lock free? + bool is_lock_free() const + { + return value.is_lock_free(); + } + + bool is_lock_free() const volatile + { + return value.is_lock_free(); + } + + // Store + void store(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + value.store(v, order); + } + + void store(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + value.store(v, order); + } + + // Load + T load(etl::memory_order order = etl::memory_order_seq_cst) const + { + return value.load(order); + } + + T load(etl::memory_order order = etl::memory_order_seq_cst) const volatile + { + return value.load(order); + } + + // Fetch add + T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.fetch_add(v, order); + } + + T fetch_add(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.fetch_add(v, order); + } + + // Fetch subtract + T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.fetch_sub(v, order); + } + + T fetch_sub(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.fetch_sub(v, order); + } + + // Fetch or + T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.fetch_or(v, order); + } + + T fetch_or(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.fetch_or(v, order); + } + + // Fetch and + T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.fetch_and(v, order); + } + + T fetch_and(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.fetch_and(v, order); + } + + // Fetch exclusive or + T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.fetch_xor(v, order); + } + + T fetch_xor(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.fetch_xor(v, order); + } + + // Exchange + T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.exchange(v, order); + } + + T exchange(T v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.exchange(v, order); + } + + // Compare exchange weak + bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.compare_exchange_weak(expected, desired, order); + } + + bool compare_exchange_weak(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.compare_exchange_weak(expected, desired, order); + } + + bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) + { + return value.compare_exchange_weak(expected, desired, success, failure); + } + + bool compare_exchange_weak(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile + { + return value.compare_exchange_weak(expected, desired, success, failure); + } + + // Compare exchange strong + bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.compare_exchange_strong(expected, desired, order); + } + + bool compare_exchange_strong(T& expected, T desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.compare_exchange_strong(expected, desired, order); + } + + bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) + { + return value.compare_exchange_strong(expected, desired, success, failure); + } + + bool compare_exchange_strong(T& expected, T desired, etl::memory_order success, etl::memory_order failure) volatile + { + return value.compare_exchange_strong(expected, desired, success, failure); + } + + private: + + atomic& operator =(const atomic&); + //atomic& operator =(const atomic&) volatile; + + std::atomic value; + }; + + template + class atomic + { + public: + + atomic() + : value(ETL_NULLPTR) + { + } + + atomic(T* v) + : value(v) + { + } + + // Assignment + T* operator =(T* v) + { + return value = v; + } + + T* operator =(T* v) volatile + { + return value = v; + } + + // Pre-increment + T* operator ++() + { + return ++value; + } + + T* operator ++() volatile + { + return ++value; + } + + // Post-increment + T* operator ++(int) + { + return value++; + } + + T* operator ++(int) volatile + { + return value++; + } + + // Pre-decrement + T* operator --() + { + return --value; + } + + T* operator --() volatile + { + return --value; + } + + // Post-decrement + T* operator --(int) + { + return value--; + } + + T* operator --(int) volatile + { + return value--; + } + + // Add + T* operator +=(ptrdiff_t v) + { + return value += v; + } + + T* operator +=(ptrdiff_t v) volatile + { + return value += v; + } + + // Subtract + T* operator -=(ptrdiff_t v) + { + return value -= v; + } + + T* operator -=(ptrdiff_t v) volatile + { + return value -= v; + } + + // Conversion operator + operator T* () const + { + return (T*)value; + } + + operator T*() volatile const + { + return (T*)value; + } + + // Is lock free? + bool is_lock_free() const + { + return value.is_lock_free(); + } + + bool is_lock_free() const volatile + { + return value.is_lock_free(); + } + + // Store + void store(T* v, etl::memory_order order = etl::memory_order_seq_cst) + { + value.store(v, order); + } + + void store(T* v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + value.store(v, order); + } + + // Load + T* load(etl::memory_order order = etl::memory_order_seq_cst) + { + return value.load(order); + } + + T* load(etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.load(order); + } + + // Fetch add + T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.fetch_add(v, order); + } + + T* fetch_add(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.fetch_add(v, order); + } + + // Fetch subtract + T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.fetch_sub(v, order); + } + + T* fetch_sub(ptrdiff_t v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.fetch_sub(v, order); + } + + // Exchange + T* exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.exchange(v, order); + } + + T* exchange(T* v, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.exchange(v, order); + } + + // Compare exchange weak + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.compare_exchange_weak(expected, desired, order); + } + + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.compare_exchange_weak(expected, desired, order); + } + + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) + { + return value.compare_exchange_weak(expected, desired, success, failure); + } + + bool compare_exchange_weak(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) volatile + { + return value.compare_exchange_weak(expected, desired, success, failure); + } + + // Compare exchange strong + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) + { + return value.compare_exchange_strong(expected, desired, order); + } + + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order order = etl::memory_order_seq_cst) volatile + { + return value.compare_exchange_strong(expected, desired, order); + } + + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) + { + return value.compare_exchange_strong(expected, desired, success, failure); + } + + bool compare_exchange_strong(T*& expected, T* desired, etl::memory_order success, etl::memory_order failure) volatile + { + return value.compare_exchange_strong(expected, desired, success, failure); + } + + private: + + atomic & operator =(const atomic&) ETL_DELETE; + atomic& operator =(const atomic&) volatile ETL_DELETE; + + std::atomic value; + }; + + typedef std::atomic atomic_bool; + typedef std::atomic atomic_char; + typedef std::atomic atomic_schar; + typedef std::atomic atomic_uchar; + typedef std::atomic atomic_short; + typedef std::atomic atomic_ushort; + typedef std::atomic atomic_int; + typedef std::atomic atomic_uint; + typedef std::atomic atomic_long; + typedef std::atomic atomic_ulong; + typedef std::atomic atomic_llong; + typedef std::atomic atomic_ullong; + typedef std::atomic atomic_wchar_t; + typedef std::atomic atomic_char16_t; + typedef std::atomic atomic_char32_t; +#if ETL_USING_8BIT_TYPES + typedef std::atomic atomic_uint8_t; + typedef std::atomic atomic_int8_t; +#endif + typedef std::atomic atomic_uint16_t; + typedef std::atomic atomic_int16_t; + typedef std::atomic atomic_uint32_t; + typedef std::atomic atomic_int32_t; +#if ETL_USING_64BIT_TYPES + typedef std::atomic atomic_uint64_t; + typedef std::atomic atomic_int64_t; +#endif + typedef std::atomic atomic_int_least8_t; + typedef std::atomic atomic_uint_least8_t; + typedef std::atomic atomic_int_least16_t; + typedef std::atomic atomic_uint_least16_t; + typedef std::atomic atomic_int_least32_t; + typedef std::atomic atomic_uint_least32_t; +#if ETL_USING_64BIT_TYPES + typedef std::atomic atomic_int_least64_t; + typedef std::atomic atomic_uint_least64_t; +#endif + typedef std::atomic atomic_int_fast8_t; + typedef std::atomic atomic_uint_fast8_t; + typedef std::atomic atomic_int_fast16_t; + typedef std::atomic atomic_uint_fast16_t; + typedef std::atomic atomic_int_fast32_t; + typedef std::atomic atomic_uint_fast32_t; +#if ETL_USING_64BIT_TYPES + typedef std::atomic atomic_int_fast64_t; + typedef std::atomic atomic_uint_fast64_t; +#endif + typedef std::atomic atomic_intptr_t; + typedef std::atomic atomic_uintptr_t; + typedef std::atomic atomic_size_t; + typedef std::atomic atomic_ptrdiff_t; + typedef std::atomic atomic_intmax_t; + typedef std::atomic atomic_uintmax_t; +} + +#endif diff --git a/src/etl/basic_format_spec.h b/src/etl/basic_format_spec.h new file mode 100644 index 0000000..43cfe80 --- /dev/null +++ b/src/etl/basic_format_spec.h @@ -0,0 +1,496 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2019 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_BASIC_FORMAT_SPEC_INCLUDED +#define ETL_BASIC_FORMAT_SPEC_INCLUDED + +///\ingroup string + +#include "platform.h" +#include "type_traits.h" +#include "static_assert.h" + +namespace etl +{ + namespace private_basic_format_spec + { + //******************************************************* + // Structures returned by stream formatting manipulators. + //******************************************************* + struct base_spec + { + ETL_CONSTEXPR base_spec(uint_least8_t base_) + : base(base_) + { + } + + const uint_least8_t base; + }; + + //********************************* + struct width_spec + { + ETL_CONSTEXPR width_spec(uint_least8_t width_) + : width(width_) + { + } + + const uint_least8_t width; + }; + + //********************************* + template + struct fill_spec + { + ETL_CONSTEXPR fill_spec(TChar fill_) + : fill(fill_) + { + } + + const TChar fill; + }; + + //********************************* + struct precision_spec + { + ETL_CONSTEXPR precision_spec(uint_least8_t precision_) + : precision(precision_) + { + } + + const uint_least8_t precision; + }; + + //********************************* + struct uppercase_spec + { + ETL_CONSTEXPR uppercase_spec(bool upper_case_) + : upper_case(upper_case_) + { + } + + const bool upper_case; + }; + + //********************************* + struct boolalpha_spec + { + ETL_CONSTEXPR boolalpha_spec(bool boolalpha_) + : boolalpha(boolalpha_) + { + } + + const bool boolalpha; + }; + + //********************************* + struct showbase_spec + { + ETL_CONSTEXPR showbase_spec(bool show_base_) + : show_base(show_base_) + { + } + + const bool show_base; + }; + + //********************************* + struct left_spec + { + }; + + //********************************* + struct right_spec + { + }; + } + + //*************************************************************************** + // Stream formatting manipulators. + //*************************************************************************** + static ETL_CONSTEXPR private_basic_format_spec::base_spec setbase(uint32_t base) + { + return private_basic_format_spec::base_spec(base); + } + + //********************************* + static ETL_CONSTEXPR private_basic_format_spec::width_spec setw(uint32_t width) + { + return private_basic_format_spec::width_spec(width); + } + + //********************************* + template + static ETL_CONSTEXPR private_basic_format_spec::fill_spec setfill(TChar fill) + { + return private_basic_format_spec::fill_spec(fill); + } + + //********************************* + static ETL_CONSTEXPR private_basic_format_spec::precision_spec setprecision(uint32_t precision) + { + return private_basic_format_spec::precision_spec(precision); + } + + //********************************* + static ETL_CONSTANT private_basic_format_spec::base_spec bin = { 2U }; + + //********************************* + static ETL_CONSTANT private_basic_format_spec::base_spec oct = { 8U }; + + //********************************* + static ETL_CONSTANT private_basic_format_spec::base_spec dec = { 10U }; + + //********************************* + static ETL_CONSTANT private_basic_format_spec::base_spec hex = { 16U }; + + //********************************* + static ETL_CONSTANT private_basic_format_spec::left_spec left; + + //********************************* + static ETL_CONSTANT private_basic_format_spec::right_spec right; + + //********************************* + static ETL_CONSTANT private_basic_format_spec::boolalpha_spec boolalpha = { true }; + + //********************************* + static ETL_CONSTANT private_basic_format_spec::boolalpha_spec noboolalpha = { false }; + + //********************************* + static ETL_CONSTANT private_basic_format_spec::uppercase_spec uppercase = { true }; + + //********************************* + static ETL_CONSTANT private_basic_format_spec::uppercase_spec nouppercase = { false }; + + //********************************* + static ETL_CONSTANT private_basic_format_spec::showbase_spec showbase = { true }; + + //********************************* + static ETL_CONSTANT private_basic_format_spec::showbase_spec noshowbase = { false }; + + //*************************************************************************** + /// basic_format_spec + //*************************************************************************** + template + class basic_format_spec + { + public: + + //*************************************************************************** + /// Default constructor. + //*************************************************************************** + ETL_CONSTEXPR basic_format_spec() + : base_(10U) + , width_(0U) + , precision_(0U) + , upper_case_(false) + , left_justified_(false) + , boolalpha_(false) + , show_base_(false) + , fill_(typename TString::value_type(' ')) + { + } + + //*************************************************************************** + /// Cconstructor. + //*************************************************************************** + ETL_CONSTEXPR basic_format_spec(uint_least8_t base__, + uint_least8_t width__, + uint_least8_t precision__, + bool upper_case__, + bool left_justified__, + bool boolalpha__, + bool show_base__, + typename TString::value_type fill__) + : base_(base__) + , width_(width__) + , precision_(precision__) + , upper_case_(upper_case__) + , left_justified_(left_justified__) + , boolalpha_(boolalpha__) + , show_base_(show_base__) + , fill_(fill__) + { + } + + //*************************************************************************** + /// Clears the format spec back to default. + //*************************************************************************** + ETL_CONSTEXPR14 void clear() + { + base_ = 10U; + width_ = 0U; + precision_ = 0U; + upper_case_ = false; + left_justified_ = false; + boolalpha_ = false; + show_base_ = false; + fill_ = typename TString::value_type(' '); + } + + //*************************************************************************** + /// Sets the base. + /// \return A reference to the basic_format_spec. + //*************************************************************************** + ETL_CONSTEXPR14 basic_format_spec& base(uint32_t b) + { + base_ = static_cast(b); + return *this; + } + + //*************************************************************************** + /// Sets the base to binary. + /// \return A reference to the basic_format_spec. + //*************************************************************************** + ETL_CONSTEXPR14 basic_format_spec& binary() + { + base(2); + return *this; + } + + //*************************************************************************** + /// Sets the base to octal. + /// \return A reference to the basic_format_spec. + //*************************************************************************** + ETL_CONSTEXPR14 basic_format_spec& octal() + { + base(8); + return *this; + } + + //*************************************************************************** + /// Sets the base to decimal. + /// \return A reference to the basic_format_spec. + //*************************************************************************** + ETL_CONSTEXPR14 basic_format_spec& decimal() + { + base(10); + return *this; + } + + //*************************************************************************** + /// Sets the base to hex. + /// \return A reference to the basic_format_spec. + //*************************************************************************** + ETL_CONSTEXPR14 basic_format_spec& hex() + { + base(16); + return *this; + } + + //*************************************************************************** + /// Gets the base. + //*************************************************************************** + ETL_CONSTEXPR uint32_t get_base() const + { + return base_; + } + + //*************************************************************************** + /// Sets the show base flag. + /// \return A reference to the basic_format_spec. + //*************************************************************************** + ETL_CONSTEXPR14 basic_format_spec& show_base(bool b) + { + show_base_ = b; + return *this; + } + + //*************************************************************************** + /// Gets the show base flag. + //*************************************************************************** + ETL_CONSTEXPR bool is_show_base() const + { + return show_base_; + } + + //*************************************************************************** + /// Sets the width. + /// \return A reference to the basic_format_spec. + //*************************************************************************** + ETL_CONSTEXPR14 basic_format_spec& width(uint32_t w) + { + width_ = static_cast(w); + return *this; + } + + //*************************************************************************** + /// Gets the width. + //*************************************************************************** + ETL_CONSTEXPR uint32_t get_width() const + { + return width_; + } + + //*************************************************************************** + /// Sets the precision. + /// \return A reference to the basic_format_spec. + //*************************************************************************** + ETL_CONSTEXPR14 basic_format_spec& precision(uint32_t p) + { + precision_ = static_cast(p); + return *this; + } + + //*************************************************************************** + /// Gets the precision. + //*************************************************************************** + ETL_CONSTEXPR uint32_t get_precision() const + { + return precision_; + } + + //*************************************************************************** + /// Sets the upper case flag. + /// \return A reference to the basic_format_spec. + //*************************************************************************** + ETL_CONSTEXPR14 basic_format_spec& upper_case(bool u) + { + upper_case_ = u; + return *this; + } + + //*************************************************************************** + /// Gets the upper case flag. + //*************************************************************************** + ETL_CONSTEXPR bool is_upper_case() const + { + return upper_case_; + } + + //*************************************************************************** + /// Sets the fill character. + /// \return A reference to the basic_format_spec. + //*************************************************************************** + ETL_CONSTEXPR14 basic_format_spec& fill(typename TString::value_type c) + { + fill_ = c; + return *this; + } + + //*************************************************************************** + /// Gets the fill character. + //*************************************************************************** + ETL_CONSTEXPR typename TString::value_type get_fill() const + { + return fill_; + } + + //*************************************************************************** + /// Sets the left justify flag. + /// \return A reference to the basic_format_spec. + //*************************************************************************** + ETL_CONSTEXPR14 basic_format_spec& left() + { + left_justified_ = true; + return *this; + } + + //*************************************************************************** + /// Gets the left justify flag. + //*************************************************************************** + ETL_CONSTEXPR bool is_left() const + { + return left_justified_; + } + + //*************************************************************************** + /// Sets the right justify flag. + /// \return A reference to the basic_format_spec. + //*************************************************************************** + ETL_CONSTEXPR14 basic_format_spec& right() + { + left_justified_ = false; + return *this; + } + + //*************************************************************************** + /// Gets the right justify flag. + //*************************************************************************** + ETL_CONSTEXPR bool is_right() const + { + return !left_justified_; + } + + //*************************************************************************** + /// Sets the bool alpha flag. + /// \return A reference to the basic_format_spec. + //*************************************************************************** + ETL_CONSTEXPR14 basic_format_spec& boolalpha(bool b) + { + boolalpha_ = b; + return *this; + } + + //*************************************************************************** + /// Gets the boolalpha flag. + //*************************************************************************** + ETL_CONSTEXPR bool is_boolalpha() const + { + return boolalpha_; + } + + //*************************************************************************** + /// Equality operator. + //*************************************************************************** + ETL_CONSTEXPR friend bool operator ==(const basic_format_spec& lhs, const basic_format_spec& rhs) + { + return (lhs.base_ == rhs.base_) && + (lhs.width_ == rhs.width_) && + (lhs.precision_ == rhs.precision_) && + (lhs.upper_case_ == rhs.upper_case_) && + (lhs.left_justified_ == rhs.left_justified_) && + (lhs.boolalpha_ == rhs.boolalpha_) && + (lhs.show_base_ == rhs.show_base_) && + (lhs.fill_ == rhs.fill_); + } + + //*************************************************************************** + /// Inequality operator. + //*************************************************************************** + ETL_CONSTEXPR friend bool operator !=(const basic_format_spec& lhs, const basic_format_spec& rhs) + { + return !(lhs == rhs); + } + + private: + + uint_least8_t base_; + uint_least8_t width_; + uint_least8_t precision_; + bool upper_case_; + bool left_justified_; + bool boolalpha_; + bool show_base_; + typename TString::value_type fill_; + }; +} + +#endif diff --git a/src/etl/basic_string.h b/src/etl/basic_string.h new file mode 100644 index 0000000..1702367 --- /dev/null +++ b/src/etl/basic_string.h @@ -0,0 +1,2551 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2016 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_BASIC_STRING_INCLUDED +#define ETL_BASIC_STRING_INCLUDED + +#include +#include +#include + +#include "platform.h" + +#include "algorithm.h" +#include "iterator.h" +#include "functional.h" +#include "char_traits.h" +#include "container.h" +#include "alignment.h" +#include "array.h" +#include "algorithm.h" +#include "type_traits.h" +#include "error_handler.h" +#include "integral_limits.h" +#include "exception.h" +#include "memory.h" +#include "exception.h" +#include "binary.h" +#include "flags.h" + +#undef ETL_FILE +#define ETL_FILE "27" + +#ifdef ETL_COMPILER_GCC +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-variable" +#endif + +#include "private/minmax_push.h" + +//***************************************************************************** +///\defgroup basic_string basic_string +/// A basic_string with the capacity defined at compile time. +///\ingroup containers +//***************************************************************************** + +namespace etl +{ + //*************************************************************************** + ///\ingroup string + /// Exception base for strings + //*************************************************************************** + class string_exception : public etl::exception + { + public: + + string_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + : exception(reason_, file_name_, line_number_) + { + } + }; + + //*************************************************************************** + ///\ingroup string + /// String empty exception. + //*************************************************************************** + class string_empty : public etl::string_exception + { + public: + + string_empty(string_type file_name_, numeric_type line_number_) + : string_exception(ETL_ERROR_TEXT("string:empty", ETL_FILE"A"), file_name_, line_number_) + { + } + }; + + //*************************************************************************** + ///\ingroup string + /// String out of bounds exception. + //*************************************************************************** + class string_out_of_bounds : public etl::string_exception + { + public: + + string_out_of_bounds(string_type file_name_, numeric_type line_number_) + : string_exception(ETL_ERROR_TEXT("string:bounds", ETL_FILE"B"), file_name_, line_number_) + { + } + }; + + //*************************************************************************** + ///\ingroup string + /// String iterator exception. + //*************************************************************************** + class string_iterator : public etl::string_exception + { + public: + + string_iterator(string_type file_name_, numeric_type line_number_) + : string_exception(ETL_ERROR_TEXT("string:iterator", ETL_FILE"C"), file_name_, line_number_) + { + } + }; + + //*************************************************************************** + ///\ingroup string + /// String truncation exception. + //*************************************************************************** + class string_truncation : public etl::string_exception + { + public: + + string_truncation(string_type file_name_, numeric_type line_number_) + : string_exception(ETL_ERROR_TEXT("string:iterator", ETL_FILE"D"), file_name_, line_number_) + { + } + }; + + //*************************************************************************** + ///\ingroup string + /// The base class for all templated string types. + //*************************************************************************** + class string_base + { + public: + + typedef size_t size_type; + +#if ETL_CPP11_SUPPORTED + static constexpr size_type npos = etl::integral_limits::max; +#else + enum + { + npos = etl::integral_limits::max + }; +#endif + + //************************************************************************* + /// Gets the current size of the string. + ///\return The current size of the string. + //************************************************************************* + size_type size() const + { + return current_size; + } + + //************************************************************************* + /// Gets the current size of the string. + ///\return The current size of the string. + //************************************************************************* + size_type length() const + { + return current_size; + } + + //************************************************************************* + /// Checks the 'empty' state of the string. + ///\return true if empty. + //************************************************************************* + bool empty() const + { + return (current_size == 0); + } + + //************************************************************************* + /// Checks the 'full' state of the string. + ///\return true if full. + //************************************************************************* + bool full() const + { + return current_size == CAPACITY; + } + + //************************************************************************* + /// Returns the capacity of the string. + ///\return The capacity of the string. + //************************************************************************* + size_type capacity() const + { + return CAPACITY; + } + + //************************************************************************* + /// Returns the maximum possible size of the string. + ///\return The maximum size of the string. + //************************************************************************* + size_type max_size() const + { + return CAPACITY; + } + + //************************************************************************* + /// Returns the remaining capacity. + ///\return The remaining capacity. + //************************************************************************* + size_type available() const + { + return max_size() - size(); + } + +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + //************************************************************************* + /// Returns whether the string was truncated by the last operation. + /// Deprecated. Use is_truncated() + ///\return Whether the string was truncated by the last operation. + //************************************************************************* + ETL_DEPRECATED + bool truncated() const + { + return flags.test(); + } + + //************************************************************************* + /// Returns whether the string was truncated by the last operation. + ///\return Whether the string was truncated by the last operation. + //************************************************************************* + bool is_truncated() const + { + return flags.test(); + } + + //************************************************************************* + /// Clears the 'truncated' flag. + //************************************************************************* + void clear_truncated() + { + flags.set(); + } +#endif + +#if ETL_STRING_CLEAR_AFTER_USE_ENABLED + //************************************************************************* + /// Sets the 'secure' flag to the requested state. + //************************************************************************* + void set_secure() + { + flags.set(); + } + + //************************************************************************* + /// Gets the 'secure' state flag. + //************************************************************************* + bool is_secure() const + { + return flags.test(); + } +#endif + + protected: + + //************************************************************************* + /// Constructor. + //************************************************************************* + string_base(size_type max_size_) + : current_size(0) + , CAPACITY(max_size_) + { + } + +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + //************************************************************************* + /// Sets the 'truncated' flag. + //************************************************************************* + void set_truncated(bool status) + { + flags.set(status); + } +#endif + + //************************************************************************* + /// Destructor. + //************************************************************************* + ~string_base() + { + } + + static const uint_least8_t IS_TRUNCATED = etl::bit<0>::value; + static const uint_least8_t CLEAR_AFTER_USE = etl::bit<1>::value; + + size_type current_size; ///< The current number of elements in the string. + const size_type CAPACITY; ///< The maximum number of elements in the string. + +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED || ETL_STRING_CLEAR_AFTER_USE_ENABLED + etl::flags flags; +#endif + }; + + //*************************************************************************** + /// The base class for specifically sized strings. + /// Can be used as a reference type for all strings containing a specific type. + ///\ingroup string + //*************************************************************************** + template + class ibasic_string : public etl::string_base + { + public: + + typedef ibasic_string interface_type; + + typedef T value_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 ETL_OR_STD::reverse_iterator reverse_iterator; + typedef ETL_OR_STD::reverse_iterator const_reverse_iterator; + + typedef typename etl::iterator_traits::difference_type difference_type; + + //********************************************************************* + /// Returns an iterator to the beginning of the string. + ///\return An iterator to the beginning of the string. + //********************************************************************* + iterator begin() + { + return &p_buffer[0]; + } + + //********************************************************************* + /// Returns a const_iterator to the beginning of the string. + ///\return A const iterator to the beginning of the string. + //********************************************************************* + const_iterator begin() const + { + return &p_buffer[0]; + } + + //********************************************************************* + /// Returns an iterator to the end of the string. + ///\return An iterator to the end of the string. + //********************************************************************* + iterator end() + { + return &p_buffer[current_size]; + } + + //********************************************************************* + /// Returns a const_iterator to the end of the string. + ///\return A const iterator to the end of the string. + //********************************************************************* + const_iterator end() const + { + return &p_buffer[current_size]; + } + + //********************************************************************* + /// Returns a const_iterator to the beginning of the string. + ///\return A const iterator to the beginning of the string. + //********************************************************************* + const_iterator cbegin() const + { + return &p_buffer[0]; + } + + //********************************************************************* + /// Returns a const_iterator to the end of the string. + ///\return A const iterator to the end of the string. + //********************************************************************* + const_iterator cend() const + { + return &p_buffer[current_size]; + } + + //********************************************************************* + /// Returns an reverse iterator to the reverse beginning of the string. + ///\return Iterator to the reverse beginning of the string. + //********************************************************************* + reverse_iterator rbegin() + { + return reverse_iterator(end()); + } + + //********************************************************************* + /// Returns a const reverse iterator to the reverse beginning of the string. + ///\return Const iterator to the reverse beginning of the string. + //********************************************************************* + const_reverse_iterator rbegin() const + { + return const_reverse_iterator(end()); + } + + //********************************************************************* + /// Returns a reverse iterator to the end + 1 of the string. + ///\return Reverse iterator to the end + 1 of the string. + //********************************************************************* + reverse_iterator rend() + { + return reverse_iterator(begin()); + } + + //********************************************************************* + /// Returns a const reverse iterator to the end + 1 of the string. + ///\return Const reverse iterator to the end + 1 of the string. + //********************************************************************* + const_reverse_iterator rend() const + { + return const_reverse_iterator(begin()); + } + + //********************************************************************* + /// Returns a const reverse iterator to the reverse beginning of the string. + ///\return Const reverse iterator to the reverse beginning of the string. + //********************************************************************* + const_reverse_iterator crbegin() const + { + return const_reverse_iterator(cend()); + } + + //********************************************************************* + /// Returns a const reverse iterator to the end + 1 of the string. + ///\return Const reverse iterator to the end + 1 of the string. + //********************************************************************* + const_reverse_iterator crend() const + { + return const_reverse_iterator(cbegin()); + } + + //********************************************************************* + /// Resizes the string. + /// If asserts or exceptions are enabled and the new size is larger than the + ///\param new_size The new size. + //********************************************************************* + void resize(size_type new_size) + { + resize(new_size, 0); + } + + //********************************************************************* + /// Resizes the string. + ///\param new_size The new size. + ///\param value The value to fill new elements with. Default = default constructed value. + //********************************************************************* + void resize(size_type new_size, T value) + { + if (new_size > CAPACITY) + { +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + set_truncated(true); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation)); +#endif +#endif + } + + new_size = etl::min(new_size, CAPACITY); + + // Size up? + if (new_size > current_size) + { + etl::fill(p_buffer + current_size, p_buffer + new_size, value); + } + + current_size = new_size; + p_buffer[new_size] = 0; + cleanup(); + } + + //********************************************************************* + /// Returns a reference to the value at index 'i' + ///\param i The index. + ///\return A reference to the value at index 'i' + //********************************************************************* + reference operator [](size_type i) + { + return p_buffer[i]; + } + + //********************************************************************* + /// Returns a const reference to the value at index 'i' + ///\param i The index. + ///\return A const reference to the value at index 'i' + //********************************************************************* + const_reference operator [](size_type i) const + { + return p_buffer[i]; + } + + //********************************************************************* + /// Returns a reference to the value at index 'i' + /// If asserts or exceptions are enabled, emits an etl::string_out_of_bounds if the index is out of range. + ///\param i The index. + ///\return A reference to the value at index 'i' + //********************************************************************* + reference at(size_type i) + { + ETL_ASSERT(i < size(), ETL_ERROR(string_out_of_bounds)); + return p_buffer[i]; + } + + //********************************************************************* + /// Returns a const reference to the value at index 'i' + /// If asserts or exceptions are enabled, emits an etl::string_out_of_bounds if the index is out of range. + ///\param i The index. + ///\return A const reference to the value at index 'i' + //********************************************************************* + const_reference at(size_type i) const + { + ETL_ASSERT(i < size(), ETL_ERROR(string_out_of_bounds)); + return p_buffer[i]; + } + + //********************************************************************* + /// Returns a reference to the first element. + ///\return A reference to the first element. + //********************************************************************* + reference front() + { + return p_buffer[0]; + } + + //********************************************************************* + /// Returns a const reference to the first element. + ///\return A const reference to the first element. + //********************************************************************* + const_reference front() const + { + return p_buffer[0]; + } + + //********************************************************************* + /// Returns a reference to the last element. + ///\return A reference to the last element. + //********************************************************************* + reference back() + { + return p_buffer[current_size - 1]; + } + + //********************************************************************* + /// Returns a const reference to the last element. + ///\return A const reference to the last element. + //********************************************************************* + const_reference back() const + { + return p_buffer[current_size - 1]; + } + + //********************************************************************* + /// Returns a pointer to the beginning of the string data. + ///\return A pointer to the beginning of the string data. + //********************************************************************* + pointer data() + { + return p_buffer; + } + + //********************************************************************* + /// Returns a const pointer to the beginning of the string data. + ///\return A const pointer to the beginning of the string data. + //********************************************************************* + const_pointer data() const + { + return p_buffer; + } + + //********************************************************************* + /// Assigns values to the string. + /// Truncates if the string does not have enough free space. + ///\param other The other string. + //********************************************************************* + void assign(const etl::ibasic_string& other) + { + assign(other.begin(), other.end()); + +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + if (other.is_truncated()) + { + set_truncated(true); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation)); +#endif + } +#endif + +#if ETL_STRING_CLEAR_AFTER_USE_ENABLED + if (other.is_secure()) + { + set_secure(); + } +#endif + + cleanup(); + } + + //********************************************************************* + /// Assigns values to the string. + /// Truncates if the string does not have enough free space. + ///\param other The other string. + ///\param subposition The position to start from. + ///\param sublength The length to copy. + //********************************************************************* + void assign(const etl::ibasic_string& other, size_type subposition, size_type sublength) + { + if (sublength == npos) + { + sublength = other.size() - subposition; + } + + ETL_ASSERT(subposition <= other.size(), ETL_ERROR(string_out_of_bounds)); + + assign(other.begin() + subposition, sublength); + +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + if (other.is_truncated()) + { + this->set_truncated(true); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation)); +#endif + } +#endif + +#if ETL_STRING_CLEAR_AFTER_USE_ENABLED + if (other.is_secure()) + { + set_secure(); + } +#endif + } + + //********************************************************************* + /// Assigns values to the string. + /// Truncates if the string does not have enough free space. + ///\param other The other string. + //********************************************************************* + void assign(const_pointer other) + { + initialise(); + + while ((*other != 0) && (current_size < CAPACITY)) + { + p_buffer[current_size++] = *other++; + } + +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + set_truncated(*other != 0); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ASSERT(flags.test() == false, ETL_ERROR(string_truncation)) +#endif +#endif + + p_buffer[current_size] = 0; + } + + //********************************************************************* + /// Assigns values to the string. + /// Truncates if the string does not have enough free space. + ///\param other The other string. + ///\param length The length to copy. + //********************************************************************* + void assign(const_pointer other, size_type length_) + { + initialise(); + +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + set_truncated(length_ > CAPACITY); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ASSERT(flags.test() == false, ETL_ERROR(string_truncation)) +#endif +#endif + + length_ = etl::min(length_, CAPACITY); + + etl::copy_n(other, length_, begin()); + + current_size = length_; + p_buffer[current_size] = 0; + } + + //********************************************************************* + /// Assigns values to the string. + /// If asserts or exceptions are enabled, emits string_iterator if the iterators are reversed. + /// Truncates if the string does not have enough free space. + ///\param first The iterator to the first element. + ///\param last The iterator to the last element + 1. + //********************************************************************* + template + void assign(TIterator first, TIterator last) + { +#if defined(ETL_DEBUG) + difference_type d = etl::distance(first, last); + ETL_ASSERT(d >= 0, ETL_ERROR(string_iterator)); +#endif + + initialise(); + + while ((first != last) && (current_size != CAPACITY)) + { + p_buffer[current_size++] = *first++; + } + + p_buffer[current_size] = 0; + +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + set_truncated(first != last); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ASSERT(flags.test() == false, ETL_ERROR(string_truncation)) +#endif +#endif + } + + //********************************************************************* + /// Assigns values to the string. + /// Truncates if the string does not have enough free space. + ///\param n The number of elements to add. + ///\param value The value to insert for each element. + //********************************************************************* + void assign(size_type n, T value) + { + initialise(); + +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + set_truncated(n > CAPACITY); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ASSERT(flags.test() == false, ETL_ERROR(string_truncation)) +#endif +#endif + + n = etl::min(n, CAPACITY); + + etl::fill_n(begin(), n, value); + current_size = n; + p_buffer[current_size] = 0; + } + + //************************************************************************* + /// Clears the string. + //************************************************************************* + void clear() + { + initialise(); + } + + //********************************************************************* + /// Inserts a value at the end of the string. + /// Sets 'truncated' if the string is already full. + ///\param value The value to add. + //********************************************************************* + void push_back(T value) + { + if (current_size != CAPACITY) + { + p_buffer[current_size++] = value; + p_buffer[current_size] = 0; + } + else + { +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + set_truncated(true); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation)); +#endif +#endif + } + } + + //************************************************************************* + /// Removes an element from the end of the string. + /// Does nothing if the string is empty. + //************************************************************************* + void pop_back() + { + if (current_size != 0) + { + p_buffer[--current_size] = 0; + } + } + + //********************************************************************* + /// Appends to the string. + ///\param str The string to append. + //********************************************************************* + ibasic_string& append(const ibasic_string& str) + { + insert(end(), str.begin(), str.end()); + +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + if (str.is_truncated()) + { + set_truncated(true); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation)); +#endif + } +#endif + + return *this; + } + + //********************************************************************* + /// Appends to the string. + ///\param str The string to append. + ///\param subposition The position in str. + ///\param sublength The number of characters. + //********************************************************************* + ibasic_string& append(const ibasic_string& str, size_type subposition, size_type sublength = npos) + { + ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds)); + + insert(size(), str, subposition, sublength); + + return *this; + } + + //********************************************************************* + /// Appends to the string. + ///\param str The string to append. + //********************************************************************* + ibasic_string& append(const T* str) + { + insert(size(), str); + return *this; + } + + //********************************************************************* + /// Appends to the string. + ///\param str The string to append. + ///\param n The number of characters. + //********************************************************************* + ibasic_string& append(const T* str, size_type n) + { + insert(size(), str, n); + return *this; + } + + //********************************************************************* + /// Appends to the string. + ///\param n The number of characters. + ///\param c The character. + //********************************************************************* + ibasic_string& append(size_type n, T c) + { + insert(size(), n, c); + return *this; + } + + //********************************************************************* + /// Appends to the string. + ///\param first The first of the characters to append. + ///\param last The last + 1 character to add. + //********************************************************************* + template + ibasic_string& append(TIterator first, TIterator last) + { + insert(end(), first, last); + return *this; + } + + //********************************************************************* + /// Inserts a value to the string. + ///\param position The position to insert before. + ///\param value The value to insert. + //********************************************************************* + iterator insert(const_iterator position, T value) + { + // Quick hack, as iterators are pointers. + iterator insert_position = const_cast(position); + + if (current_size < CAPACITY) + { + // Not full yet. + if (position != end()) + { + // Insert in the middle. + ++current_size; + etl::copy_backward(insert_position, end() - 1, end()); + *insert_position = value; + } + else + { + // Insert at the end. + *insert_position = value; + ++current_size; + } + } + else + { + // Already full. + if (position != end()) + { + // Insert in the middle. + etl::copy_backward(insert_position, end() - 1, end()); + *insert_position = value; + } + +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + set_truncated(true); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation)); +#endif +#endif + } + + p_buffer[current_size] = 0; + + return insert_position; + } + + //********************************************************************* + /// Inserts 'n' values to the string. + ///\param position The position to insert before. + ///\param n The number of elements to add. + ///\param value The value to insert. + //********************************************************************* + void insert(const_iterator position, size_type n, T value) + { + if (n == 0) + { + return; + } + + // Quick hack, as iterators are pointers. + iterator insert_position = const_cast(position); + const size_type start = etl::distance(cbegin(), position); + + // No effect. + if (start >= CAPACITY) + { +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + set_truncated(true); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation)); +#endif +#endif + return; + } + + // Fills the string to the end? + if ((start + n) >= CAPACITY) + { + if ((current_size + n) > CAPACITY) + { +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + set_truncated(true); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation)); +#endif +#endif + } + + current_size = CAPACITY; + etl::fill(insert_position, end(), value); + } + else + { + // Lets do some shifting. + const size_type shift_amount = n; + const size_type to_position = start + shift_amount; + const size_type remaining_characters = current_size - start; + const size_type max_shift_characters = CAPACITY - start - shift_amount; + const size_type characters_to_shift = etl::min(max_shift_characters, remaining_characters); + + // Will the string truncate? + if ((start + shift_amount + remaining_characters) > CAPACITY) + { + current_size = CAPACITY; + +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + set_truncated(true); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation)); +#endif +#endif + } + else + { + current_size += shift_amount; + } + + etl::copy_backward(insert_position, insert_position + characters_to_shift, begin() + to_position + characters_to_shift); + etl::fill(insert_position, insert_position + shift_amount, value); + } + + p_buffer[current_size] = 0; + } + + //********************************************************************* + /// Inserts a range of values to the string. + /// If asserts or exceptions are enabled, emits string_full if the string does not have enough free space. + ///\param position The position to insert before. + ///\param first The first element to add. + ///\param last The last + 1 element to add. + //********************************************************************* + template + void insert(iterator position, TIterator first, TIterator last) + { + if (first == last) + { + return; + } + + const size_type start = etl::distance(begin(), position); + const size_type n = etl::distance(first, last); + + // No effect. + if (start >= CAPACITY) + { +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + set_truncated(true); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation)); +#endif +#endif + return; + } + + // Fills the string to the end? + if ((start + n) >= CAPACITY) + { + if (((current_size + n) > CAPACITY)) + { +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + set_truncated(true); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation)); +#endif +#endif + } + + current_size = CAPACITY; + + while (position != end()) + { + *position++ = *first++; + } + } + else + { + // Lets do some shifting. + const size_type shift_amount = n; + const size_type to_position = start + shift_amount; + const size_type remaining_characters = current_size - start; + const size_type max_shift_characters = CAPACITY - start - shift_amount; + const size_type characters_to_shift = etl::min(max_shift_characters, remaining_characters); + + // Will the string truncate? + if ((start + shift_amount + remaining_characters) > CAPACITY) + { + current_size = CAPACITY; + +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + set_truncated(true); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation)); +#endif +#endif + } + else + { + current_size += shift_amount; + } + + etl::copy_backward(position, position + characters_to_shift, begin() + to_position + characters_to_shift); + + while (first != last) + { + *position++ = *first++; + } + } + + p_buffer[current_size] = 0; + } + + //********************************************************************* + /// Inserts a string at the specified position. + ///\param position The position to insert before. + ///\param str The string to insert. + //********************************************************************* + etl::ibasic_string& insert(size_type position, const etl::ibasic_string& str) + { + ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); + + insert(begin() + position, str.cbegin(), str.cend()); + +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + if (str.is_truncated()) + { + set_truncated(true); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation)); +#endif + } +#endif + + return *this; + } + + //********************************************************************* + /// Inserts a string at the specified position from subposition for sublength. + ///\param position The position to insert before. + ///\param str The string to insert. + ///\param subposition The subposition to start from. + ///\param sublength The number of characters to insert. + //********************************************************************* + etl::ibasic_string& insert(size_type position, const etl::ibasic_string& str, size_type subposition, size_type sublength) + { + ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); + ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds)); + + if ((sublength == npos) || (subposition + sublength > str.size())) + { + sublength = str.size() - subposition; + } + + insert(begin() + position, str.cbegin() + subposition, str.cbegin() + subposition + sublength); + +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + if (str.is_truncated()) + { + set_truncated(true); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation)); +#endif + } +#endif + + return *this; + } + + //********************************************************************* + /// Inserts a string at the specified position from pointer. + ///\param position The position to insert before. + ///\param s The string to insert. + //********************************************************************* + etl::ibasic_string& insert(size_type position, const_pointer s) + { + ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); + + insert(begin() + position, s, s + etl::strlen(s)); + return *this; + } + + //********************************************************************* + /// Inserts a string at the specified position from pointer for n characters. + ///\param position The position to insert before. + ///\param s The string to insert. + ///\param n The number of characters to insert. + //********************************************************************* + etl::ibasic_string& insert(size_type position, const_pointer s, size_type n) + { + ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); + + insert(begin() + position, s, s + n); + return *this; + } + + //********************************************************************* + /// Insert n characters of c at position. + ///\param position The position to insert before. + ///\param n The number of characters to insert. + ///\param c The character to insert. + //********************************************************************* + etl::ibasic_string& insert(size_type position, size_type n, value_type c) + { + ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); + + insert(begin() + position, n, c); + return *this; + } + + //********************************************************************* + /// Erases a sequence. + ///\param position Position to start from. + ///\param length Number of characters. + ///\return A refernce to this string. + //********************************************************************* + etl::ibasic_string& erase(size_type position, size_type length_ = npos) + { + // Limit the length. + length_ = etl::min(length_, size() - position); + + erase(begin() + position, begin() + position + length_); + + return *this; + } + + //********************************************************************* + /// Erases an element. + ///\param i_element Iterator to the element. + ///\return An iterator pointing to the element that followed the erased element. + //********************************************************************* + iterator erase(iterator i_element) + { + etl::copy(i_element + 1, end(), i_element); + p_buffer[--current_size] = 0; + + return i_element; + } + + //********************************************************************* + /// Erases a range of elements. + /// The range includes all the elements between first and last, including the + /// element pointed by first, but not the one pointed by last. + ///\param first Iterator to the first element. + ///\param last Iterator to the last element. + ///\return An iterator pointing to the element that followed the erased element. + //********************************************************************* + iterator erase(iterator first, iterator last) + { + if (first == last) + { + return first; + } + + etl::copy(last, end(), first); + size_type n_delete = etl::distance(first, last); + + current_size -= n_delete; + p_buffer[current_size] = 0; + cleanup(); + + return first; + } + + //********************************************************************* + /// Return a pointer to a C string. + //********************************************************************* + const_pointer c_str() const + { + return p_buffer; + } + + //********************************************************************* + /// Copies a portion of a string. + ///\param s Pointer to the string to copy. + ///\param len The number of characters to copy. + ///\param pos The position to start copying from. + //********************************************************************* + size_type copy(pointer s, size_type len, size_type pos = 0) + { + if ((pos + len > size())) + { +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + set_truncated(true); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation)); +#endif +#endif + } + + size_type endpos = etl::min(pos + len, size()); + + for (size_type i = pos; i < endpos; ++i) + { + *s++ = p_buffer[i]; + } + + return endpos - pos; + } + + //********************************************************************* + /// Find content within the string + ///\param str The content to find + ///\param pos The position to start searching from. + //********************************************************************* + size_type find(const ibasic_string& str, size_type pos = 0) const + { + if ((pos + str.size()) > size()) + { + return npos; + } + + const_iterator iposition = etl::search(begin() + pos, end(), str.begin(), str.end()); + + if (iposition == end()) + { + return npos; + } + else + { + return etl::distance(begin(), iposition); + } + } + + //********************************************************************* + /// Find content within the string + ///\param s Pointer to the content to find + ///\param pos The position to start searching from. + //********************************************************************* + size_type find(const_pointer s, size_type pos = 0) const + { +#if defined(ETL_DEBUG) + if ((pos + etl::strlen(s)) > size()) + { + return npos; + } +#endif + + const_iterator iposition = etl::search(begin() + pos, end(), s, s + etl::strlen(s)); + + if (iposition == end()) + { + return npos; + } + else + { + return etl::distance(begin(), iposition); + } + } + + //********************************************************************* + /// Find content within the string + ///\param s Pointer to the content to find + ///\param pos The position to start searching from. + ///\param n The number of characters to search for. + //********************************************************************* + size_type find(const_pointer s, size_type pos, size_type n) const + { +#if defined(ETL_DEBUG) + if ((pos + etl::strlen(s) - n) > size()) + { + return npos; + } +#endif + + const_iterator iposition = etl::search(begin() + pos, end(), s, s + n); + + if (iposition == end()) + { + return npos; + } + else + { + return etl::distance(begin(), iposition); + } + } + + //********************************************************************* + /// Find character within the string + ///\param c The character to find. + ///\param position The position to start searching from. + //********************************************************************* + size_type find(T c, size_type position = 0) const + { + const_iterator i = etl::find(begin() + position, end(), c); + + if (i != end()) + { + return etl::distance(begin(), i); + } + else + { + return npos; + } + } + + //********************************************************************* + /// Find content within the string + ///\param str The content to find + ///\param pos The position to start searching from. + //********************************************************************* + size_type rfind(const ibasic_string& str, size_type position = npos) const + { + if ((str.size()) > size()) + { + return npos; + } + + if (position >= size()) + { + position = size(); + } + + position = size() - position; + + const_reverse_iterator iposition = etl::search(rbegin() + position, rend(), str.rbegin(), str.rend()); + + if (iposition == rend()) + { + return npos; + } + else + { + return size() - str.size() - etl::distance(rbegin(), iposition); + } + } + + //********************************************************************* + /// Find content within the string + ///\param str The content to find + ///\param pos The position to start searching from. + //********************************************************************* + size_type rfind(const_pointer s, size_type position = npos) const + { + size_type len = etl::strlen(s); + + if (len > size()) + { + return npos; + } + + if (position >= size()) + { + position = size(); + } + + position = size() - position; + + const_reverse_iterator srbegin(s + len); + const_reverse_iterator srend(s); + + const_reverse_iterator iposition = etl::search(rbegin() + position, rend(), srbegin, srend); + + if (iposition == rend()) + { + return npos; + } + else + { + return size() - len - etl::distance(rbegin(), iposition); + } + } + + //********************************************************************* + /// Find content within the string + ///\param str The content to find + ///\param pos The position to start searching from. + //********************************************************************* + size_type rfind(const_pointer s, size_type position, size_type length_) const + { + if (length_ > size()) + { + return npos; + } + + if (position >= size()) + { + position = size(); + } + + position = size() - position; + + const_reverse_iterator srbegin(s + length_); + const_reverse_iterator srend(s); + + const_reverse_iterator iposition = etl::search(rbegin() + position, rend(), srbegin, srend); + + if (iposition == rend()) + { + return npos; + } + else + { + return size() - length_ - etl::distance(rbegin(), iposition); + } + } + + //********************************************************************* + /// Find character within the string + ///\param c The character to find + ///\param pos The position to start searching from. + //********************************************************************* + size_type rfind(T c, size_type position = npos) const + { + if (position >= size()) + { + position = size(); + } + + position = size() - position; + + const_reverse_iterator i = etl::find(rbegin() + position, rend(), c); + + if (i != rend()) + { + return size() - etl::distance(rbegin(), i) - 1; + } + else + { + return npos; + } + } + + //********************************************************************* + /// Replace 'length' characters from 'position' with 'str'. + ///\param position The position to start from. + ///\param length The number of characters to replace. + ///\param str The string to replace it with. + //********************************************************************* + ibasic_string& replace(size_type position, size_type length_, const ibasic_string& str) + { + ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); + + // Limit the length. + length_ = etl::min(length_, size() - position); + + // Erase the bit we want to replace. + erase(position, length_); + + // Insert the new stuff. + insert(position, str); + + return *this; + } + + //********************************************************************* + /// Replace characters from 'first' to one before 'last' with 'str'. + ///\param first The position to start from. + ///\param last The one after the position to end at. + ///\param str The string to replace it with. + //********************************************************************* + ibasic_string& replace(const_iterator first, const_iterator last, const ibasic_string& str) + { + // Quick hack, as iterators are pointers. + iterator first_ = const_cast(first); + iterator last_ = const_cast(last); + + // Erase the bit we want to replace. + erase(first_, last_); + + // Insert the new stuff. + insert(first_, str.begin(), str.end()); + +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + if (str.is_truncated()) + { + set_truncated(true); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation)); +#endif + } +#endif + + return *this; + } + + //********************************************************************* + /// Replace characters from 'position' of 'length' with 'str' from 'subpsotion' of 'sublength'. + //********************************************************************* + ibasic_string& replace(size_type position, size_type length_, const ibasic_string& str, size_type subposition, size_type sublength) + { + ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); + ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds)); + + // Limit the lengths. + length_ = etl::min(length_, size() - position); + sublength = etl::min(sublength, str.size() - subposition); + + // Erase the bit we want to replace. + erase(position, length_); + + // Insert the new stuff. + insert(position, str, subposition, sublength); + +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + if (str.is_truncated()) + { + set_truncated(true); + +#if defined(ETL_STRING_TRUNCATION_IS_ERROR) + ETL_ALWAYS_ASSERT(ETL_ERROR(string_truncation)); +#endif + } +#endif + + return *this; + } + + //********************************************************************* + /// Replace characters from 'position' of 'length' with pointed to string. + //********************************************************************* + ibasic_string& replace(size_type position, size_type length_, const_pointer s) + { + ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); + + // Limit the length. + length_ = etl::min(length_, size() - position); + + // Erase the bit we want to replace. + erase(position, length_); + + // Insert the new stuff. + insert(position, s, etl::strlen(s)); + + return *this; + } + + //********************************************************************* + /// Replace characters from 'first' 'last' with pointed to string. + //********************************************************************* + ibasic_string& replace(const_iterator first, const_iterator last, const_pointer s) + { + // Quick hack, as iterators are pointers. + iterator first_ = const_cast(first); + iterator last_ = const_cast(last); + + // Erase the bit we want to replace. + erase(first_, last_); + + // Insert the new stuff. + insert(first_, s, s + etl::strlen(s)); + + return *this; + } + + //********************************************************************* + /// Replace characters from 'position' of 'length' with 'n' characters from pointed to string. + //********************************************************************* + ibasic_string& replace(size_type position, size_type length_, const_pointer s, size_type n) + { + ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); + + // Limit the length. + length_ = etl::min(length_, size() - position); + + // Erase the bit we want to replace. + erase(position, length_); + + // Insert the new stuff. + insert(position, s, n); + + return *this; + } + + //********************************************************************* + /// Replace characters from 'first' to 'last' with 'n' characters from pointed to string. + //********************************************************************* + ibasic_string& replace(const_iterator first, const_iterator last, const_pointer s, size_type n) + { + // Quick hack, as iterators are pointers. + iterator first_ = const_cast(first); + iterator last_ = const_cast(last); + + // Erase the bit we want to replace. + erase(first_, last_); + + // Insert the new stuff. + insert(first_, s, s + n); + + return *this; + } + + //********************************************************************* + /// Replace characters from 'position' of 'length' with 'n' copies of 'c'. + //********************************************************************* + ibasic_string& replace(size_type position, size_type length_, size_type n, value_type c) + { + ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); + + // Limit the length. + length_ = etl::min(length_, size() - position); + + // Erase the bit we want to replace. + erase(position, length_); + + // Insert the new stuff. + insert(position, n, c); + + return *this; + } + + //********************************************************************* + /// Replace characters from 'first' of 'last' with 'n' copies of 'c'. + //********************************************************************* + ibasic_string& replace(const_iterator first, const_iterator last, size_type n, value_type c) + { + // Quick hack, as iterators are pointers. + iterator first_ = const_cast(first); + iterator last_ = const_cast(last); + + // Erase the bit we want to replace. + erase(first_, last_); + + // Insert the new stuff. + insert(first_, n, c); + + return *this; + } + + //********************************************************************* + /// Replace characters from 'first' of 'last' with characters from 'first_replace' to 'last_replace'. + //********************************************************************* + template + ibasic_string& replace(const_iterator first, const_iterator last, TIterator first_replace, TIterator last_replace) + { + // Quick hack, as iterators are pointers. + iterator first_ = const_cast(first); + iterator last_ = const_cast(last); + + // Erase the bit we want to replace. + erase(first_, last_); + + // Insert the new stuff. + insert(first_, first_replace, last_replace); + + return *this; + } + + //************************************************************************* + /// Compare with string. + //************************************************************************* + int compare(const ibasic_string& str) const + { + return compare(p_buffer, + p_buffer + size(), + str.p_buffer, + str.p_buffer + str.size()); + } + + //************************************************************************* + /// Compare position / length with string. + //************************************************************************* + int compare(size_type position, size_type length_, const ibasic_string& str) const + { + ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); + + // Limit the length. + length_ = etl::min(length_, size() - position); + + return compare(p_buffer + position, + p_buffer + position + length_, + str.p_buffer, + str.p_buffer + str.size()); + } + + //************************************************************************* + /// Compare position / length with string / subposition / sublength. + //************************************************************************* + int compare(size_type position, size_type length_, const ibasic_string& str, size_type subposition, size_type sublength) const + { + ETL_ASSERT(position <= size(), ETL_ERROR(string_out_of_bounds)); + ETL_ASSERT(subposition <= str.size(), ETL_ERROR(string_out_of_bounds)); + + // Limit the lengths. + length_ = etl::min(length_, size() - position); + sublength = etl::min(sublength, str.size() - subposition); + + return compare(p_buffer + position, + p_buffer + position + length_, + str.p_buffer + subposition, + str.p_buffer + subposition + sublength); + } + + //************************************************************************* + /// Compare with C string + //************************************************************************* + int compare(const value_type* s) const + { + return compare(p_buffer, + p_buffer + size(), + s, + s + etl::strlen(s)); + } + + //************************************************************************* + /// Compare position / length with C string. + //************************************************************************* + int compare(size_type position, size_type length_, const_pointer s) const + { + return compare(p_buffer + position, + p_buffer + position + length_, + s, + s + etl::strlen(s)); + } + + //************************************************************************* + /// Compare position / length with C string / n. + //************************************************************************* + int compare(size_type position, size_type length_, const_pointer s, size_type n) const + { + return compare(p_buffer + position, + p_buffer + position + length_, + s, + s + n); + } + + //********************************************************************* + /// Find first of any of content within the string + ///\param str The content to find + ///\param pos The position to start searching from. + //********************************************************************* + size_type find_first_of(const ibasic_string& str, size_type position = 0) const + { + return find_first_of(str.c_str(), position, str.size()); + } + + //********************************************************************* + /// Find first of any of content within the string + ///\param s Pointer to the content to find + ///\param pos The position to start searching from. + //********************************************************************* + size_type find_first_of(const_pointer s, size_type position = 0) const + { + return find_first_of(s, position, etl::strlen(s)); + } + + //********************************************************************* + /// Find first of any of content within the string + ///\param s Pointer to the content to find + ///\param pos The position to start searching from. + ///\param n The number of characters to search for. + //********************************************************************* + size_type find_first_of(const_pointer s, size_type position, size_type n) const + { + if (position < size()) + { + for (size_type i = position; i < size(); ++i) + { + for (size_type j = 0; j < n; ++j) + { + if (p_buffer[i] == s[j]) + { + return i; + } + } + } + } + + return npos; + } + + //********************************************************************* + /// Find first of character within the string + ///\param c The character to find + ///\param pos The position to start searching from. + //********************************************************************* + size_type find_first_of(value_type c, size_type position = 0) const + { + if (position < size()) + { + for (size_type i = position; i < size(); ++i) + { + if (p_buffer[i] == c) + { + return i; + } + } + } + + return npos; + } + + //********************************************************************* + /// Find last of any of content within the string + ///\param str The content to find + ///\param pos The position to start searching from. + //********************************************************************* + size_type find_last_of(const ibasic_string& str, size_type position = npos) const + { + return find_last_of(str.c_str(), position, str.size()); + } + + //********************************************************************* + /// Find last of any of content within the string + ///\param s Pointer to the content to find + ///\param pos The position to start searching from. + //********************************************************************* + size_type find_last_of(const_pointer s, size_type position = npos) const + { + return find_last_of(s, position, etl::strlen(s)); + } + + //********************************************************************* + /// Find last of any of content within the string + ///\param s Pointer to the content to find + ///\param pos The position to start searching from. + ///\param n The number of characters to search for. + //********************************************************************* + size_type find_last_of(const_pointer s, size_type position, size_type n) const + { + if (empty()) + { + return npos; + } + + position = etl::min(position, size() - 1); + + const_reverse_iterator it = rbegin() + size() - position - 1; + + while (it != rend()) + { + for (size_type j = 0; j < n; ++j) + { + if (p_buffer[position] == s[j]) + { + return position; + } + } + + ++it; + --position; + } + + return npos; + } + + //********************************************************************* + /// Find last of character within the string + ///\param c The character to find + ///\param pos The position to start searching from. + //********************************************************************* + size_type find_last_of(value_type c, size_type position = npos) const + { + if (empty()) + { + return npos; + } + + position = etl::min(position, size() - 1); + + const_reverse_iterator it = rbegin() + size() - position - 1; + + while (it != rend()) + { + if (p_buffer[position] == c) + { + return position; + } + + ++it; + --position; + } + + return npos; + } + + //********************************************************************* + /// Find first not of any of content within the string + ///\param str The content to find + ///\param pos The position to start searching from. + //********************************************************************* + size_type find_first_not_of(const ibasic_string& str, size_type position = 0) const + { + return find_first_not_of(str.c_str(), position, str.size()); + } + + //********************************************************************* + /// Find first not of any of content within the string + ///\param s Pointer to the content to not find + ///\param pos The position to start searching from. + //********************************************************************* + size_type find_first_not_of(const_pointer s, size_type position = 0) const + { + return find_first_not_of(s, position, etl::strlen(s)); + } + + //********************************************************************* + /// Find first not of any of content within the string + ///\param s Pointer to the content to not find + ///\param pos The position to start searching from. + ///\param n The number of characters to search for. + //********************************************************************* + size_type find_first_not_of(const_pointer s, size_type position, size_type n) const + { + if (position < size()) + { + for (size_type i = position; i < size(); ++i) + { + bool found = false; + + for (size_type j = 0; j < n; ++j) + { + if (p_buffer[i] == s[j]) + { + found = true; + } + } + + if (!found) + { + return i; + } + } + } + + return npos; + } + + //********************************************************************* + /// Find first not of character within the string + ///\param c The character to not find + ///\param pos The position to start searching from. + //********************************************************************* + size_type find_first_not_of(value_type c, size_type position = 0) const + { + if (position < size()) + { + for (size_type i = position; i < size(); ++i) + { + if (p_buffer[i] != c) + { + return i; + } + } + } + + return npos; + } + + //********************************************************************* + /// Find last not of any of content within the string + ///\param str The content to find + ///\param pos The position to start searching from. + //********************************************************************* + size_type find_last_not_of(const ibasic_string& str, size_type position = npos) const + { + return find_last_not_of(str.c_str(), position, str.size()); + } + + //********************************************************************* + /// Find last not of any of content within the string + ///\param s The pointer to the content to find + ///\param pos The position to start searching from. + //********************************************************************* + size_type find_last_not_of(const_pointer s, size_type position = npos) const + { + return find_last_not_of(s, position, etl::strlen(s)); + } + + //********************************************************************* + /// Find last not of any of content within the string + ///\param s The pointer to the content to find + ///\param pos The position to start searching from. + ///\param n The number of characters to use. + //********************************************************************* + size_type find_last_not_of(const_pointer s, size_type position, size_type n) const + { + if (empty()) + { + return npos; + } + + position = etl::min(position, size() - 1); + + const_reverse_iterator it = rbegin() + size() - position - 1; + + while (it != rend()) + { + bool found = false; + + for (size_type j = 0; j < n; ++j) + { + if (p_buffer[position] == s[j]) + { + found = true; + } + } + + if (!found) + { + return position; + } + + ++it; + --position; + } + + return npos; + } + + //********************************************************************* + // + //********************************************************************* + size_type find_last_not_of(value_type c, size_type position = npos) const + { + if (empty()) + { + return npos; + } + + position = etl::min(position, size() - 1); + + const_reverse_iterator it = rbegin() + size() - position - 1; + + while (it != rend()) + { + if (p_buffer[position] != c) + { + return position; + } + + ++it; + --position; + } + + return npos; + } + + //************************************************************************* + /// Assignment operator. + //************************************************************************* + ibasic_string& operator = (const ibasic_string& rhs) + { + if (&rhs != this) + { + assign(rhs); + } + + return *this; + } + + //************************************************************************* + /// Assignment operator. + //************************************************************************* + ibasic_string& operator = (const_pointer rhs) + { + assign(rhs); + + return *this; + } + + //************************************************************************* + /// += operator. + //************************************************************************* + ibasic_string& operator += (const ibasic_string& rhs) + { + append(rhs); + + return *this; + } + + //************************************************************************* + /// += operator. + //************************************************************************* + ibasic_string& operator += (const_pointer rhs) + { + append(rhs); + + return *this; + } + + //************************************************************************* + /// += operator. + //************************************************************************* + ibasic_string& operator += (T rhs) + { + append(size_type(1), rhs); + + return *this; + } + +#ifdef ETL_ISTRING_REPAIR_ENABLE + //************************************************************************* + /// Fix the internal pointers after a low level memory copy. + //************************************************************************* + virtual void repair() = 0; +#endif + + protected: + + //********************************************************************* + /// Constructor. + //********************************************************************* + ibasic_string(T* p_buffer_, size_type MAX_SIZE_) + : string_base(MAX_SIZE_), + p_buffer(p_buffer_) + { + } + + //********************************************************************* + /// Initialise the string. + //********************************************************************* + void initialise() + { + current_size = 0; + cleanup(); + p_buffer[0] = 0; +#if ETL_STRING_TRUNCATION_CHECKS_ENABLED + set_truncated(false); +#endif + } + + //************************************************************************* + /// Fix the internal pointers after a low level memory copy. + //************************************************************************* + void repair_buffer(T* p_buffer_) + { + p_buffer = p_buffer_; + } + + private: + + //************************************************************************* + /// Compare helper function + //************************************************************************* + int compare(const_pointer first1, const_pointer last1, const_pointer first2, const_pointer last2) const + { + while ((first1 != last1) && (first2 != last2)) + { + if (*first1 < *first2) + { + // Compared character is lower. + return -1; + } + else if (*first1 > *first2) + { + // Compared character is higher. + return 1; + } + + ++first1; + ++first2; + } + + // We reached the end of one or both of the strings. + if ((first1 == last1) && (first2 == last2)) + { + // Same length. + return 0; + } + else if (first1 == last1) + { + // Compared string is shorter. + return -1; + } + else + { + // Compared string is longer. + return 1; + } + } + + //************************************************************************* + /// Clear the unused trailing portion of the string. + //************************************************************************* + void cleanup() + { +#if ETL_STRING_CLEAR_AFTER_USE_ENABLED + if (is_secure()) + { + etl::memory_clear_range(&p_buffer[current_size], &p_buffer[CAPACITY]); + } +#endif + } + + //************************************************************************* + /// Disable copy construction. + //************************************************************************* + ibasic_string(const ibasic_string&); + + //************************************************************************* + /// Pointer to the string's buffer. + //************************************************************************* + T* p_buffer; + + //************************************************************************* + /// Destructor. + //************************************************************************* +#if defined(ETL_POLYMORPHIC_STRINGS) || defined(ETL_POLYMORPHIC_CONTAINERS) + public: + virtual +#else + protected: +#endif + ~ibasic_string() + { +#if ETL_STRING_CLEAR_AFTER_USE_ENABLED + if (is_secure()) + { + initialise(); + } +#endif + } + }; + + //*************************************************************************** + /// Equal operator. + ///\param lhs Reference to the first string. + ///\param rhs Reference to the second string. + ///\return true if the arrays are equal, otherwise false + ///\ingroup string + //*************************************************************************** + template + bool operator ==(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) + { + return (lhs.size() == rhs.size()) && etl::equal(lhs.begin(), lhs.end(), rhs.begin()); + } + + //*************************************************************************** + /// Equal operator. + ///\param lhs Reference to the first string. + ///\param rhs Reference to the second string. + ///\return true if the arrays are equal, otherwise false + ///\ingroup string + //*************************************************************************** + template + bool operator ==(const etl::ibasic_string& lhs, const T* rhs) + { + return (lhs.size() == etl::strlen(rhs)) && etl::equal(lhs.begin(), lhs.end(), rhs); + } + + //*************************************************************************** + /// Equal operator. + ///\param lhs Reference to the first string. + ///\param rhs Reference to the second string. + ///\return true if the arrays are equal, otherwise false + ///\ingroup string + //*************************************************************************** + template + bool operator ==(const T* lhs, const etl::ibasic_string& rhs) + { + return (rhs.size() == etl::strlen(lhs)) && etl::equal(rhs.begin(), rhs.end(), lhs); + } + + + //*************************************************************************** + /// Not equal operator. + ///\param lhs Reference to the first string. + ///\param rhs Reference to the second string. + ///\return true if the arrays are not equal, otherwise false + ///\ingroup string + //*************************************************************************** + template + bool operator !=(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) + { + return !(lhs == rhs); + } + + //*************************************************************************** + /// Not equal operator. + ///\param lhs Reference to the first string. + ///\param rhs Reference to the second string. + ///\return true if the arrays are not equal, otherwise false + ///\ingroup string + //*************************************************************************** + template + bool operator !=(const etl::ibasic_string& lhs, const T* rhs) + { + return !(lhs == rhs); + } + + //*************************************************************************** + /// Not equal operator. + ///\param lhs Reference to the first string. + ///\param rhs Reference to the second string. + ///\return true if the arrays are not equal, otherwise false + ///\ingroup string + //*************************************************************************** + template + bool operator !=(const T* lhs, const etl::ibasic_string& rhs) + { + return !(lhs == rhs); + } + + //*************************************************************************** + /// Less than operator. + ///\param lhs Reference to the first string. + ///\param rhs Reference to the second string. + ///\return true if the first string is lexicographically less than the second, otherwise false + ///\ingroup string + //*************************************************************************** + template + bool operator <(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) + { + return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); + } + + //*************************************************************************** + /// Less than operator. + ///\param lhs Reference to the first string. + ///\param rhs Reference to the second string. + ///\return true if the first string is lexicographically less than the second, otherwise false + ///\ingroup string + //*************************************************************************** + template + bool operator <(const etl::ibasic_string& lhs, const T* rhs) + { + return etl::lexicographical_compare(lhs.begin(), lhs.end(), rhs, rhs + etl::strlen(rhs)); + } + + //*************************************************************************** + /// Less than operator. + ///\param lhs Reference to the first string. + ///\param rhs Reference to the second string. + ///\return true if the first string is lexicographically less than the second, otherwise false + ///\ingroup string + //*************************************************************************** + template + bool operator <(const T* lhs, const etl::ibasic_string& rhs) + { + return etl::lexicographical_compare(lhs, lhs + etl::strlen(lhs), rhs.begin(), rhs.end()); + } + + + //*************************************************************************** + /// Greater than operator. + ///\param lhs Reference to the first string. + ///\param rhs Reference to the second string. + ///\return true if the first string is lexicographically greater than the second, otherwise false + ///\ingroup string + //*************************************************************************** + template + bool operator >(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) + { + return (rhs < lhs); + } + + //*************************************************************************** + /// Greater than operator. + ///\param lhs Reference to the first string. + ///\param rhs Reference to the second string. + ///\return true if the first string is lexicographically greater than the second, otherwise false + ///\ingroup string + //*************************************************************************** + template + bool operator >(const etl::ibasic_string& lhs, const T* rhs) + { + return (rhs < lhs); + } + + //*************************************************************************** + /// Greater than operator. + ///\param lhs Reference to the first string. + ///\param rhs Reference to the second string. + ///\return true if the first string is lexicographically greater than the second, otherwise false + ///\ingroup string + //*************************************************************************** + template + bool operator >(const T* lhs, const etl::ibasic_string& rhs) + { + return (rhs < lhs); + } + + + //*************************************************************************** + /// Less than or equal operator. + ///\param lhs Reference to the first string. + ///\param rhs Reference to the second string. + ///\return true if the first string is lexicographically less than or equal to the second, otherwise false + ///\ingroup string + //*************************************************************************** + template + bool operator <=(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) + { + return !(lhs > rhs); + } + + //*************************************************************************** + /// Less than or equal operator. + ///\param lhs Reference to the first string. + ///\param rhs Reference to the second string. + ///\return true if the first string is lexicographically less than or equal to the second, otherwise false + ///\ingroup string + //*************************************************************************** + template + bool operator <=(const etl::ibasic_string& lhs, const T* rhs) + { + return !(lhs > rhs); + } + + //*************************************************************************** + /// Less than or equal operator. + ///\param lhs Reference to the first string. + ///\param rhs Reference to the second string. + ///\return true if the first string is lexicographically less than or equal to the second, otherwise false + ///\ingroup string + //*************************************************************************** + template + bool operator <=(const T* lhs, const etl::ibasic_string& rhs) + { + return !(lhs > rhs); + } + + + //*************************************************************************** + /// Greater than or equal operator. + ///\param lhs Reference to the first string. + ///\param rhs Reference to the second string. + ///\return true if the first string is lexicographically greater than or equal to the second, otherwise false + ///\ingroup string + //*************************************************************************** + template + bool operator >=(const etl::ibasic_string& lhs, const etl::ibasic_string& rhs) + { + return !(lhs < rhs); + } + + //*************************************************************************** + /// Greater than or equal operator. + ///\param lhs Reference to the first string. + ///\param rhs Reference to the second string. + ///\return true if the first string is lexicographically greater than or equal to the second, otherwise false + ///\ingroup string + //*************************************************************************** + template + bool operator >=(const etl::ibasic_string& lhs, const T* rhs) + { + return !(lhs < rhs); + } + + //*************************************************************************** + /// Greater than or equal operator. + ///\param lhs Reference to the first string. + ///\param rhs Reference to the second string. + ///\return true if the first string is lexicographically greater than or equal to the second, otherwise false + ///\ingroup string + //*************************************************************************** + template + bool operator >=(const T* lhs, const etl::ibasic_string& rhs) + { + return !(lhs < rhs); + } +} + +#include "private/minmax_pop.h" + +#ifdef ETL_COMPILER_GCC +#pragma GCC diagnostic pop +#endif + +#undef ETL_FILE + +#endif diff --git a/src/etl/basic_string_stream.h b/src/etl/basic_string_stream.h new file mode 100644 index 0000000..511913e --- /dev/null +++ b/src/etl/basic_string_stream.h @@ -0,0 +1,269 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2020 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_BASIC_STRING_STREAM_INCLUDED +#define ETL_BASIC_STRING_STREAM_INCLUDED + +///\ingroup string + +#include "platform.h" + +namespace etl +{ + template + class basic_string_stream + { + public: + + typedef TFormat format_spec_type; + typedef TIString istring_type; + typedef typename TIString::value_type value_type; + typedef typename TIString::const_pointer const_pointer; + + //************************************************************************* + /// Construct from text. + //************************************************************************* + explicit basic_string_stream(TIString& text_) + : text(text_) + { + } + + //************************************************************************* + /// Construct from text and format spec. + //************************************************************************* + basic_string_stream(TIString& text_, const TFormat& spec_) + : text(text_) + , spec(spec_) + { + } + + //************************************************************************* + /// Set the format spec. + //************************************************************************* + void set_format(const TFormat& spec_) + { + spec = spec_; + } + + //************************************************************************* + /// Get a const reference to the format spec. + //************************************************************************* + const TFormat& get_format() const + { + return spec; + } + + //************************************************************************* + /// Get a reference to the current string. + //************************************************************************* + TIString& str() + { + return text; + } + + //************************************************************************* + /// Get a const reference to the current string. + //************************************************************************* + const TIString& str() const + { + return text; + } + + //************************************************************************* + /// Resets the stream to the supplied string. + //************************************************************************* + void str(const value_type* p) + { + text.assign(p); + } + + //************************************************************************* + /// Resets the stream to the supplied string. + //************************************************************************* + void str(const TIString& is) + { + text.assign(is); + } + + //************************************************************************* + /// Stream operators. + //************************************************************************* + + //********************************* + /// TFormat + //********************************* + friend basic_string_stream& operator <<(basic_string_stream& ss, const TFormat& spec) + { + ss.spec = spec; + return ss; + } + + //********************************* + /// etl::base_spec from etl::setbase, etl::bin, etl::oct, etl::dec & etl::hex stream manipulators + //********************************* + friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::base_spec spec) + { + ss.spec.base(spec.base); + return ss; + } + + //********************************* + /// etl::width_spec from etl::setw stream manipulator + //********************************* + friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::width_spec spec) + { + ss.spec.width(spec.width); + return ss; + } + + //********************************* + /// etl::fill_spec from etl::setfill stream manipulator + //********************************* + template + friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::fill_spec spec) + { + ss.spec.fill(spec.fill); + return ss; + } + + //********************************* + /// etl::precision_spec from etl::setprecision stream manipulator + //********************************* + friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::precision_spec spec) + { + ss.spec.precision(spec.precision); + return ss; + } + + //********************************* + /// etl::boolalpha_spec from etl::boolalpha & etl::noboolalpha stream manipulators + //********************************* + friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::boolalpha_spec spec) + { + ss.spec.boolalpha(spec.boolalpha); + return ss; + } + + //********************************* + /// etl::uppercase_spec from etl::uppercase & etl::nouppercase stream manipulators + //********************************* + friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::uppercase_spec spec) + { + ss.spec.upper_case(spec.upper_case); + return ss; + } + + //********************************* + /// etl::showbase_spec from etl::showbase & etl::noshowbase stream manipulators + //********************************* + friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::showbase_spec spec) + { + ss.spec.show_base(spec.show_base); + return ss; + } + + //********************************* + /// etl::left_spec from etl::left stream manipulator + //********************************* + friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::left_spec spec) + { + ss.spec.left(); + return ss; + } + + //********************************* + /// etl::right_spec from etl::left stream manipulator + //********************************* + friend basic_string_stream& operator <<(basic_string_stream& ss, etl::private_basic_format_spec::right_spec spec) + { + ss.spec.right(); + return ss; + } + + //********************************* + /// From a string view + //********************************* + friend basic_string_stream& operator <<(basic_string_stream& ss, TStringView view) + { + etl::to_string(view, ss.text, ss.spec, true); + return ss; + } + + //********************************* + /// From a const pointer to a string + //********************************* + friend basic_string_stream& operator <<(basic_string_stream& ss, const_pointer p) + { + TStringView view(p); + ss << view; + return ss; + } + + //********************************* + /// From a string interface + //********************************* + friend basic_string_stream& operator <<(basic_string_stream& ss, const TIString& text) + { + etl::to_string(text, ss.text, ss.spec, true); + return ss; + } + + //********************************* + /// From a string + //********************************* + template