Merge branch 'development' into deque_check_index

This commit is contained in:
John Wellbelove 2026-10-12 11:47:14 +02:00 committed by GitHub
commit bd3eea8dde
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
69 changed files with 7206 additions and 1571 deletions

View File

@ -36,8 +36,12 @@ concurrency:
jobs:
build-windows-msvc-stl:
name: Windows - STL
name: Windows - STL - C++${{ matrix.cxx_standard }}
runs-on: [windows-2022]
strategy:
fail-fast: false
matrix:
cxx_standard: [14, 17, 20]
steps:
- name: Checkout
@ -50,7 +54,7 @@ jobs:
- name: Build
run: |
cmake -G "Visual Studio 17 2022" -AWin32 -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./
cmake -G "Visual Studio 17 2022" -AWin32 -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=${{ matrix.cxx_standard }} ./
MSBuild.exe -version
MSBuild.exe .\etl.sln
@ -58,8 +62,12 @@ jobs:
run: test/Debug/etl_tests.exe -v
build-windows-msvc-no-stl:
name: Windows - No STL
name: Windows - No STL - C++${{ matrix.cxx_standard }}
runs-on: [windows-2022]
strategy:
fail-fast: false
matrix:
cxx_standard: [14, 17, 20]
steps:
- name: Checkout
uses: actions/checkout@v6.0.3
@ -71,7 +79,7 @@ jobs:
- name: Build
run: |
cmake -G "Visual Studio 17 2022" -AWin32 -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=17 ./
cmake -G "Visual Studio 17 2022" -AWin32 -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=OFF -DETL_CXX_STANDARD=${{ matrix.cxx_standard }} ./
MSBuild.exe -version
MSBuild.exe .\etl.sln
@ -79,8 +87,12 @@ jobs:
run: test/Debug/etl_tests.exe -v
build-windows-msvc-stl-force-cpp03:
name: Windows - STL - Force C++03
name: Windows - STL - Force C++03 - C++${{ matrix.cxx_standard }}
runs-on: [windows-2022]
strategy:
fail-fast: false
matrix:
cxx_standard: [14, 17, 20]
steps:
- name: Checkout
@ -93,7 +105,7 @@ jobs:
- name: Build
run: |
cmake -G "Visual Studio 17 2022" -AWin32 -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=17 ./
cmake -G "Visual Studio 17 2022" -AWin32 -DBUILD_TESTS=ON -DNO_STL=OFF -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=${{ matrix.cxx_standard }} ./
MSBuild.exe -version
MSBuild.exe .\etl.sln
@ -101,8 +113,12 @@ jobs:
run: test/Debug/etl_tests.exe -v
build-windows-msvc-no-stl-force-cpp03:
name: Windows - No STL - Force C++03
name: Windows - No STL - Force C++03 - C++${{ matrix.cxx_standard }}
runs-on: [windows-2022]
strategy:
fail-fast: false
matrix:
cxx_standard: [14, 17, 20]
steps:
- name: Checkout
@ -115,7 +131,7 @@ jobs:
- name: Build
run: |
cmake -G "Visual Studio 17 2022" -AWin32 -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=17 ./
cmake -G "Visual Studio 17 2022" -AWin32 -DBUILD_TESTS=ON -DNO_STL=ON -DETL_USE_TYPE_TRAITS_BUILTINS=OFF -DETL_USER_DEFINED_TYPE_TRAITS=OFF -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=ON -DETL_CXX_STANDARD=${{ matrix.cxx_standard }} ./
MSBuild.exe -version
MSBuild.exe .\etl.sln

1
.gitignore vendored
View File

@ -423,3 +423,4 @@ include/etl/iterator.h~RFfd5eda.TMP
test/vs2022/Build
docs/Messaging
test/vs2026/Build
test/include

View File

@ -118,9 +118,9 @@ CRC calculations (8, 16, 32 & 64-bit)
Checksums and hash functions
- Variants (type-safe unions)
- Extensive template support utilities
- Robust Error Handling: Configurable error checking using asserts, exceptions, error handlers, or no checks; user’s choice.
- Robust Error Handling: Configurable error checking using asserts, exceptions, error handlers, or no checks; user's choice.
- Thoroughly Tested:
Over 10,000 unit tests
Over **14,000** tests
Tested with Visual Studio 2022, GCC 12, and Clang 14
Continuous integration via GitHub Actions.
- Readable and Well-Documented: Clean, maintainable source code with clear documentation.
@ -128,6 +128,7 @@ Continuous integration via GitHub Actions.
- Archived: A snapshot of the ETL is preserved in the Arctic Code Vault for long-term digital preservation.
## Support the ETL
Maintaining the ETL can take a lot of man-hours of work, but unfortunately it doesn't pay the bills. When I have to take on paying work, the ETL gets a lot less attention. So if you have found the library is an important component in your work and you would like to help out, then please consider by supporting the project.
---

306
docs/maths/math.md Normal file
View File

@ -0,0 +1,306 @@
---
title: "math"
---
{{< callout type="info">}}
Header: `math.h`
From: `20.50.0`
{{< /callout >}}
Various mathematical utilities
## is_nan
```cpp
template <typename T>
ETL_CONSTEXPR bool is_nan(T value)
```
**Returns**
`true` if `value` is `NAN` (Not A Number).
Always returns `false` if `T` is an integral.
## is_infinity
```cpp
template <typename T>
ETL_CONSTEXPR bool is_infinity(T value)
```
**Returns**
`true` if `value` is infinity.
Always returns `false` if `T` is an integral.
## is_zero
```cpp
template <typename T>
ETL_CONSTEXPR bool is_zero(T value)
```
**Returns**
`true` if `value` is Zero.
## is_exactly_zero
```cpp
template <typename T>
ETL_CONSTEXPR bool is_exactly_equal(T value1, T value2)
```
**Returns**
`true` if `value1` is equal to `value2`.
## floor
Defined in the `etl::math` namespace.
---
```cpp
ETL_NODISCARD
float floor(float value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::floorf` in `<math.h>`.
**Returns**
`::floorf(value)`
---
```cpp
ETL_NODISCARD
double floor(double value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::floor` in `<math.h>`.
**Returns**
`::floor(value)`
---
```cpp
ETL_NODISCARD
long double floor(long double value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::floorl` in `<math.h>`.
**Returns**
If `ETL_NO_LONG_DOUBLE_MATH` is defined then returns
`::floor` with casts to `double`.
otherwise
`::floorl(value)`
## ceil
Defined in the `etl::math` namespace.
---
```cpp
ETL_NODISCARD
float ceil(float value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::ceilf` in `<math.h>`.
**Returns**
`::ceilf(value)`
---
```cpp
ETL_NODISCARD
double ceil(double value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::ceil` in `<math.h>`.
**Returns**
`::ceil(value)`
---
```cpp
ETL_NODISCARD
long double ceil(long double value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::ceill` in `<math.h>`.
**Returns**
If `ETL_NO_LONG_DOUBLE_MATH` is defined then returns
`::ceil` with casts to `double`.
otherwise
`::ceill(value)`
## log10
Defined in the `etl::math` namespace.
---
```cpp
ETL_NODISCARD
float log10(float value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::log10f` in `<math.h>`.
**Returns**
`::log10f(value)`
---
```cpp
ETL_NODISCARD
double log10(double value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::log10` in `<math.h>`.
**Returns**
`::log10(value)`
---
```cpp
ETL_NODISCARD
long double log10(long double value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::log10l` in `<math.h>`.
**Returns**
If `ETL_NO_LONG_DOUBLE_MATH` is defined then returns
`::log10` with casts to `double`.
otherwise
`::log10l(value)`
## round
Defined in the `etl::math` namespace.
---
```cpp
ETL_NODISCARD
float round(float value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::roundf` in `<math.h>`.
**Returns**
`::roundf(value)`
---
```cpp
ETL_NODISCARD
double round(double value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::round` in `<math.h>`.
**Returns**
`::round(value)`
---
```cpp
ETL_NODISCARD
long double round(long double value) ETL_NOEXCEPT
```
**Description**
A wrapper around `::roundl` in `<math.h>`.
**Returns**
If `ETL_NO_LONG_DOUBLE_MATH` is defined then returns
`::round` with casts to `double`.
otherwise
`::roundl(value)`
## pow
Defined in the `etl::math` namespace.
---
```cpp
ETL_NODISCARD
float pow(float base, float exponent) ETL_NOEXCEPT
```
**Description**
A wrapper around `::powf` in `<math.h>`.
**Returns**
`::powf(base, exponent)`
---
```cpp
ETL_NODISCARD
double pow(double base, double exponent) ETL_NOEXCEPT
```
**Description**
A wrapper around `::pow` in `<math.h>`.
**Returns**
`::pow(base, exponent)`
---
```cpp
ETL_NODISCARD
long double pow(long double base, long double exponent) ETL_NOEXCEPT
```
**Description**
A wrapper around `::powl` in `<math.h>`.
**Returns**
If `ETL_NO_LONG_DOUBLE_MATH` is defined then returns
`::pow` with casts to `double`.
otherwise
`::powl(base, intpart)`
## modf
Defined in the `etl::math` namespace.
---
```cpp
ETL_NODISCARD
float modf(float value, float* intpart) ETL_NOEXCEPT
```
**Description**
A wrapper around `::modff` in `<math.h>`.
**Returns**
`::modff(value, intpart)`
---
```cpp
ETL_NODISCARD
double modf(double value, double* intpart) ETL_NOEXCEPT
```
**Description**
A wrapper around `::modf` in `<math.h>`.
**Returns**
`::modf(value, intpart)`
---
```cpp
ETL_NODISCARD
long double modf(long double value, long double* intpart) ETL_NOEXCEPT
```
**Description**
A wrapper around `::modfl` in `<math.h>`.
**Returns**
If `ETL_NO_LONG_DOUBLE_MATH` is defined then returns
`::modf` with casts to `double`.
otherwise
`::modfl(value, intpart)`

View File

@ -166,6 +166,50 @@ Constructs with the supplied value.
---
```cpp
unaligned_type(const void* address)
```
**Description**
Constructs from the `Size` bytes at the address.
From: `20.39.5`
---
```cpp
unaligned_type(const void* address, size_t buffer_size)
```
**Description**
Constructs from the `Size` bytes at the address.
`buffer_size` must be greater than or equal to `Size`. This is a precondition,
checked by `ETL_ASSERT`. If checks are disabled then a smaller buffer size
results in a read beyond the end of the buffer.
From: `20.39.5`
---
```cpp
ETL_CONSTEXPR14 unaligned_type(const unsigned char* address)
```
**Description**
Constructs from the `Size` bytes at the address.
Unlike the `const void*` overload, this requires no `reinterpret_cast` and so
may be used in a constexpr context.
From: `20.48.1`
---
```cpp
ETL_CONSTEXPR14 unaligned_type(const unsigned char* address, size_t buffer_size)
```
**Description**
Constructs from the `Size` bytes at the address.
`buffer_size` must be greater than or equal to `Size`. This is a precondition,
checked by `ETL_ASSERT`. If checks are disabled then a smaller buffer size
results in a read beyond the end of the buffer.
From: `20.48.1`
---
```cpp
template <int Endian_Other>
unaligned_type(const unaligned_type<T, Endian_Other>& other)
@ -176,10 +220,11 @@ The endianness is converted, if necessary.
## Member types
```cpp
using pointer = char*;
using const_pointer = const char*;
using iterator = char*;
using const_iterator = const char*;
using storage_type = unsigned char;
using pointer = unsigned char*;
using const_pointer = const unsigned char*;
using iterator = unsigned char*;
using const_iterator = const unsigned char*;
using reverse_iterator = etl::reverse_iterator<iterator>;
using const_reverse_iterator = etl::reverse_iterator<const_iterator>;
```
@ -306,7 +351,7 @@ Const reverse iterator to the end of the storage.
---
```cpp
char& operator[](int i)
storage_type& operator[](int i)
```
**Description**
Index operator.
@ -314,7 +359,7 @@ Index operator.
---
```cpp
ETL_CONSTEXPR14 const char& operator[](int i) const
ETL_CONSTEXPR14 const storage_type& operator[](int i) const
```
**Description**
Const index operator.
@ -345,6 +390,15 @@ Gets the value.
---
```cpp
static ETL_CONSTEXPR14 T value_from(const_pointer address)
```
**Description**
Gets the value of the `Size` bytes at the address.
Unlike construction from an address, the bytes are not copied to storage first.
---
```cpp
template <int Endian_Other>
ETL_CONSTEXPR14 unaligned_type& operator =(const unaligned_type<T, Endian_Other>& other)
@ -405,3 +459,317 @@ ETL_CONSTEXPR14 bool operator !=(T lhs, const unaligned_type& rhs)
**Description**
Inequality operator.
Removed: `20.39.3`
---
# Arbitrary width integers
{{< callout type="info">}}
From: `20.50.0`
{{< /callout >}}
`etl::unaligned_type` is templated on a fundamental type, so it can only store
integers whose width is that of a standard integer type. For protocols that use
odd widths, such as 24 or 48 bit integers, the following types are templated on
the **number of bytes of storage** instead.
```cpp
template <size_t Size_, int Endian_>
class unaligned_uint_type
template <size_t Size_, int Endian_>
class unaligned_int_type
```
Where `Size_` is the number of bytes of storage and `Endian_` is
`etl::endian::big` or `etl::endian::little`.
`unaligned_uint_type` stores an unsigned integer.
`unaligned_int_type` stores a signed, two's complement integer, which is sign
extended when read.
The value is interfaced to via `value_type`: the smallest standard integer type
that can hold `Size_` bytes. For example, `unaligned_uint_type<3U, ...>` has a
`value_type` of `uint32_t`.
Values that do not fit in `Size_` bytes are truncated, in the same way as a
narrowing `static_cast`.
Marked as `packed` for MSVC, GCC and Clang.
## Constants
`int Endian`
&emsp;The endianness of the type.
`size_t Size`
&emsp;The size, in bytes, of the type.
`value_type Min_Value`
&emsp;The lowest value that may be stored.
`value_type Max_Value`
&emsp;The highest value that may be stored.
## Predefined types
The 40, 48 and 56 bit types are only defined if `ETL_USING_64BIT_TYPES`.
The host order types are only defined if `ETL_HAS_CONSTEXPR_ENDIANNESS`.
### Little Endian
```cpp
le_uint24_t
le_int24_t
le_uint40_t ETL_USING_64BIT_TYPES
le_int40_t ETL_USING_64BIT_TYPES
le_uint48_t ETL_USING_64BIT_TYPES
le_int48_t ETL_USING_64BIT_TYPES
le_uint56_t ETL_USING_64BIT_TYPES
le_int56_t ETL_USING_64BIT_TYPES
```
### Big Endian
```cpp
be_uint24_t
be_int24_t
be_uint40_t ETL_USING_64BIT_TYPES
be_int40_t ETL_USING_64BIT_TYPES
be_uint48_t ETL_USING_64BIT_TYPES
be_int48_t ETL_USING_64BIT_TYPES
be_uint56_t ETL_USING_64BIT_TYPES
be_int56_t ETL_USING_64BIT_TYPES
```
### Network Order
Synonyms for Big Endian.
```cpp
using net_uint24_t = be_uint24_t
using net_int24_t = be_int24_t
using net_uint40_t = be_uint40_t
using net_int40_t = be_int40_t
using net_uint48_t = be_uint48_t
using net_int48_t = be_int48_t
using net_uint56_t = be_uint56_t
using net_int56_t = be_int56_t
```
### Host order
```cpp
host_uint24_t
host_int24_t
host_uint40_t
host_int40_t
host_uint48_t
host_int48_t
host_uint56_t
host_int56_t
```
## Constructors
```cpp
unaligned_uint_type()
unaligned_int_type()
```
**Description**
Constructs an uninitialised object.
---
```cpp
ETL_CONSTEXPR14 unaligned_uint_type(value_type value)
ETL_CONSTEXPR14 unaligned_int_type(value_type value)
```
**Description**
Constructs with the supplied value.
Values that do not fit in `Size` bytes are truncated.
---
```cpp
unaligned_uint_type(const void* address)
unaligned_int_type(const void* address)
```
**Description**
Constructs from the `Size` bytes at the address.
---
```cpp
unaligned_uint_type(const void* address, size_t buffer_size)
unaligned_int_type(const void* address, size_t buffer_size)
```
**Description**
Constructs from the `Size` bytes at the address.
`buffer_size` must be greater than or equal to `Size`. This is a precondition,
checked by `ETL_ASSERT`. If checks are disabled then a smaller buffer size
results in a read beyond the end of the buffer.
---
```cpp
ETL_CONSTEXPR14 unaligned_uint_type(const unsigned char* address)
ETL_CONSTEXPR14 unaligned_int_type(const unsigned char* address)
```
**Description**
Constructs from the `Size` bytes at the address.
Unlike the `const void*` overload, this requires no `reinterpret_cast` and so
may be used in a constexpr context.
---
```cpp
ETL_CONSTEXPR14 unaligned_uint_type(const unsigned char* address, size_t buffer_size)
ETL_CONSTEXPR14 unaligned_int_type(const unsigned char* address, size_t buffer_size)
```
**Description**
Constructs from the `Size` bytes at the address.
`buffer_size` must be greater than or equal to `Size`. This is a precondition,
checked by `ETL_ASSERT`.
---
```cpp
template <int Endian_Other>
unaligned_uint_type(const unaligned_uint_type<Size, Endian_Other>& other)
```
**Description**
Constructs from another type of the same size.
The endianness is converted, if necessary.
## Member functions
The storage interface (`data()`, `size()`, the iterators and `operator[]`) is
the same as that of `etl::unaligned_type`.
```cpp
ETL_CONSTEXPR14 unaligned_uint_type& operator =(value_type value)
```
**Description**
Assignment operator.
---
```cpp
ETL_CONSTEXPR14 operator value_type() const
```
**Description**
Conversion operator.
For `unaligned_int_type` the stored value is sign extended.
---
```cpp
ETL_CONSTEXPR14 value_type value() const
```
**Description**
Gets the value.
For `unaligned_int_type` the stored value is sign extended.
---
```cpp
static ETL_CONSTEXPR14 value_type value_from(const_pointer address)
```
**Description**
Gets the value of the `Size` bytes at the address.
Unlike construction from an address, the bytes are not copied to storage first.
---
```cpp
template <int Endian_Other>
ETL_CONSTEXPR14 unaligned_uint_type& operator =(const unaligned_uint_type<Size, Endian_Other>& other)
```
**Description**
Assignment operator from other endianness.
---
# Arbitrary width integers with an external buffer
{{< callout type="info">}}
From: `20.50.0`
{{< /callout >}}
```cpp
template <size_t Size_, int Endian_>
class unaligned_uint_type_ext
template <size_t Size_, int Endian_>
class unaligned_int_type_ext
```
These are the equivalents of `unaligned_uint_type` and `unaligned_int_type`
that do not own their storage, but reference an externally supplied buffer.
They have the same `value_type`, constants and value interface.
The default constructor is deleted: the storage must always be supplied.
### Predefined types
As for the internal storage versions, but with an `_ext_t` suffix.
```cpp
le_uint24_ext_t be_uint24_ext_t net_uint24_ext_t host_uint24_ext_t
le_int24_ext_t be_int24_ext_t net_int24_ext_t host_int24_ext_t
le_uint40_ext_t be_uint40_ext_t net_uint40_ext_t host_uint40_ext_t
le_int40_ext_t be_int40_ext_t net_int40_ext_t host_int40_ext_t
le_uint48_ext_t be_uint48_ext_t net_uint48_ext_t host_uint48_ext_t
le_int48_ext_t be_int48_ext_t net_int48_ext_t host_int48_ext_t
le_uint56_ext_t be_uint56_ext_t net_uint56_ext_t host_uint56_ext_t
le_int56_ext_t be_int56_ext_t net_int56_ext_t host_int56_ext_t
```
## Constructors
```cpp
unaligned_uint_type_ext() ETL_DELETE
```
**Description**
Deleted. The storage must always be supplied.
---
```cpp
unaligned_uint_type_ext(pointer storage)
```
**Description**
Constructs, referencing the supplied storage.
The storage is not modified.
---
```cpp
unaligned_uint_type_ext(value_type value, pointer storage)
```
**Description**
Constructs, referencing the supplied storage, and writes the value to it.
---
```cpp
template <int Endian_Other>
unaligned_uint_type_ext(const unaligned_uint_type_ext<Size, Endian_Other>& other, pointer storage)
```
**Description**
Constructs, referencing the supplied storage, and copies the value of `other`
to it, converting the endianness if necessary.
**Note**
The storage of `other` must either be the same storage as that supplied, or
completely separate. Partially overlapping storage is undefined behaviour.
## Member functions
```cpp
void set_storage(pointer storage)
```
**Description**
Sets the storage for the type.
The storage is not modified.
---
```cpp
template <int Endian_Other>
unaligned_uint_type_ext& operator =(const unaligned_uint_type_ext<Size, Endian_Other>& other)
```
**Description**
Assignment operator from other endianness.
**Note**
The storage of `other` must either be the same storage as this object's, or
completely separate. Partially overlapping storage is undefined behaviour.

View File

@ -26,7 +26,8 @@ including the header to override automatic detection.
When `ETL_HAS_FLOATING_POINT_CLAMPED_VALUE` is `0`, `T` must be an integral
type. When it is `1`, `float`, `double`, and `long double` may also be used with
runtime bounds.
runtime bounds. `clamped_value_range<T>` and `referenced_clamped_value<T>` are
available in C++11 and later.
```cpp
// C++11 and later
@ -48,6 +49,20 @@ etl::clamped_value<float, -1.5f, 2.5f> float_ct(0.5f);
#endif
```
In C++11 and later, multiple values can share one immutable runtime range:
```cpp
const etl::clamped_value_range<float> range(-1.5f, 2.5f);
etl::referenced_clamped_value<float> value1(range, 0.5f);
etl::referenced_clamped_value<float> value2(range, 1.5f);
```
`referenced_clamped_value<T>` stores an
`etl::reference_wrapper<const clamped_value_range<T>>`. The range must outlive
every value that refers to it. Construction from a temporary range is deleted.
Copying or swapping a referenced value also copies or swaps its range reference.
## Types
`difference_type` is the signed counterpart of `T` for integral values. For
@ -55,6 +70,9 @@ floating-point values, `difference_type` is `T`, allowing fractional steps.
`limits_type` and `difference_limits_type` provide the corresponding
`etl::numeric_limits` specializations.
`referenced_clamped_value<T>` also defines `range_type` as
`clamped_value_range<T>`.
## Constructors
```cpp
@ -76,6 +94,23 @@ runtime-bound specialization. Supplying `Min` and `Max` selects fixed
compile-time bounds. NaN bounds and initial values are rejected. Infinite
bounds and values are permitted.
### Referenced ranges
```cpp
clamped_value_range<T> range(min, max);
referenced_clamped_value<T> value(range);
referenced_clamped_value<T> value(range, initial);
```
The one-argument value constructor initializes to `range.min()`. The
two-argument form clamps `initial` to the shared range. A range is immutable
after construction, so every referring value observes stable bounds. A
default-constructed range uses the full representable range of `T`.
`referenced_clamped_value<T>` is non-owning. The referenced range must outlive
the value and any copies of it. The constructors taking `range_type&&` are
deleted to prevent direct construction from a temporary range.
## Modifiers
```cpp
@ -93,6 +128,10 @@ counterpart of `T` as its step type. For floating-point values, the step type
is `T` and may be fractional. Steps saturate in constant time at the minimum
or maximum rather than wrapping. NaN steps are rejected.
`referenced_clamped_value<T>` supports `set(T)`, `to_min()`, `to_max()`, and
`advance(difference_type)`. It does not provide `set(min, max)` because its
range is immutable and shared.
Positive steps move toward `max`; negative steps move toward `min`. Infinite
steps saturate at a finite bound. Infinite values and bounds remain valid.
@ -122,6 +161,14 @@ ETL_NODISCARD T max() const noexcept;
Gets the current value and its bounds. Both compile-time and runtime
specializations provide these accessors as const-qualified member functions.
`referenced_clamped_value<T>` additionally provides:
```cpp
ETL_NODISCARD const range_type& range() const noexcept;
```
This returns the exact `clamped_value_range<T>` object referenced by the value.
## Operators
```cpp
@ -143,6 +190,8 @@ floating-point values, assignment and compound-assignment reject NaN.
Prefix increment and decrement return a reference to the updated object.
Postfix increment and decrement return a copy of the value before it was
updated. All four operations move by one and saturate at the applicable bound.
`referenced_clamped_value<T>` provides the same conversion, assignment,
increment, decrement, and compound-assignment operators.
## Operations
@ -153,6 +202,10 @@ ETL_CONSTEXPR14 void swap(clamped_value& lhs, clamped_value& rhs);
Swaps clamped values. Runtime values also swap their bounds.
Swapping two `referenced_clamped_value<T>` objects swaps both their current
values and range references. Copy construction and copy assignment preserve
the source's range identity; they do not copy the range itself.
Equality, inequality, and relational comparisons are provided. Comparisons
against arithmetic values use the implicit conversion to `T`. Equality
compares the current values; runtime bounds do not affect equality. Runtime
@ -169,3 +222,124 @@ assignments, and steps also trigger an ETL assertion. Depending on the ETL
error-handler configuration, an assertion may throw `etl::exception`, invoke a
configured handler, or terminate. Operations that validate input are only
`noexcept` when exceptions are disabled.
The same validation applies when constructing `clamped_value_range<T>` and
when assigning or advancing a `referenced_clamped_value<T>`.
## Shared Referenced Ranges
`clamped_value_range<T>` and `referenced_clamped_value<T>` are available in
C++11 and later. They let independent values share immutable runtime bounds.
### `clamped_value_range<T>`
```cpp
template <typename T>
class clamped_value_range;
```
#### Constructors
```cpp
clamped_value_range();
clamped_value_range(T min, T max);
```
The default constructor uses the full representable range of `T`. The
two-argument constructor stores immutable bounds and rejects reversed or NaN
bounds.
#### Accessors
```cpp
ETL_NODISCARD T min() const noexcept;
ETL_NODISCARD T max() const noexcept;
```
### `referenced_clamped_value<T>`
```cpp
template <typename T>
class referenced_clamped_value;
```
The class stores a current value and an
`etl::reference_wrapper<const clamped_value_range<T>>`. It does not own the
range, which must outlive the value and all copies of it.
Member types are `range_type`, `difference_type`, `limits_type`, and
`difference_limits_type`, with the same numeric meanings as `clamped_value<T>`.
#### Constructors
```cpp
explicit referenced_clamped_value(const range_type& range);
referenced_clamped_value(const range_type& range, T initial);
referenced_clamped_value(const referenced_clamped_value& other);
referenced_clamped_value(range_type&&) = delete;
referenced_clamped_value(range_type&&, T) = delete;
```
The one-argument constructor initializes to `range.min()`. The two-argument
constructor clamps `initial`. Temporary ranges are rejected to prevent an
immediately dangling reference. Copy construction preserves the source value
and range identity.
#### Modifiers
```cpp
void set(T value);
void to_min() noexcept;
void to_max() noexcept;
void advance(difference_type n);
```
These operations mirror `clamped_value<T>`. There is no `set(min, max)` because
the referenced range is immutable and shared.
#### Accessors
```cpp
ETL_NODISCARD T get() const noexcept;
ETL_NODISCARD T min() const noexcept;
ETL_NODISCARD T max() const noexcept;
ETL_NODISCARD const range_type& range() const noexcept;
ETL_NODISCARD operator T() const noexcept;
```
`range()` returns the exact range object held by reference.
#### Operators
```cpp
referenced_clamped_value& operator=(const referenced_clamped_value& other) & noexcept;
referenced_clamped_value& operator=(T value) &;
referenced_clamped_value& operator++() & noexcept;
referenced_clamped_value operator++(int) noexcept;
referenced_clamped_value& operator--() & noexcept;
referenced_clamped_value operator--(int) noexcept;
referenced_clamped_value& operator+=(difference_type n) &;
referenced_clamped_value& operator-=(difference_type n) &;
```
Copy assignment copies both the current value and range reference. Arithmetic
and value assignment clamp to the referenced bounds. Comparisons compare only
current values, not range identity or bounds.
#### Swap
```cpp
void swap(referenced_clamped_value& other) noexcept;
void swap(referenced_clamped_value& lhs,
referenced_clamped_value& rhs) noexcept;
```
Swap exchanges both current values and range references, keeping each value
associated with its original bounds.
#### Errors
Invalid or NaN range bounds trigger an ETL assertion. NaN initial values,
assignments, and steps are also rejected. Infinite values follow the same
behavior as `clamped_value<T>`.

View File

@ -7,23 +7,32 @@ title: "compare"
Since: `TBC`
{{< /callout >}}
A helper class that defines `<=`, `>`, `>=` in terms of `etl::less` or a user supplied compare type.
A helper for deriving comparison operations from a strict weak ordering.
`etl::compare<T, TLess>` exposes boolean predicates and a three-state comparison result.
`etl::three_way_compare` returns `-1`, `0`, or `1` using the same comparison policy.
```cpp
template <typename T, typename TLess = etl::less<T> >
struct compare
```
```cpp
template <typename T, typename TLess = etl::less<T> >
ETL_CONSTEXPR14 int three_way_compare(const T& lhs, const T& rhs)
```
## Types
```cpp
first_argument_type;
second_argument_type;
result_type;
cmp_result;
```
`cmp_result` has the values `Less`, `Equal`, and `Greater`.
## Members
```cpp
static result_type lt(first_argument_type lhs, second_argument_type rhs)
static bool lt(first_argument_type lhs, second_argument_type rhs)
```
**Return**
`true` if `lhs < rhs`, otherwise `false`.
@ -31,7 +40,7 @@ static result_type lt(first_argument_type lhs, second_argument_type rhs)
---
```cpp
static result_type lte(first_argument_type lhs, second_argument_type rhs)
static bool lte(first_argument_type lhs, second_argument_type rhs)
```
**Return**
`true` if `lhs <= rhs`, otherwise `false`.
@ -39,7 +48,7 @@ static result_type lte(first_argument_type lhs, second_argument_type rhs)
---
```cpp
static result_type gt(first_argument_type lhs, second_argument_type rhs)
static bool gt(first_argument_type lhs, second_argument_type rhs)
```
**Return**
`true` if `lhs > rhs`, otherwise `false`.
@ -47,14 +56,74 @@ static result_type gt(first_argument_type lhs, second_argument_type rhs)
---
```cpp
static result_type gte(first_argument_type lhs, second_argument_type rhs)
static bool gte(first_argument_type lhs, second_argument_type rhs)
```
**Return**
`true` if `lhs >= rhs`, otherwise `false`.
---
```cpp
static bool eq(first_argument_type lhs, second_argument_type rhs)
```
**Return**
`true` if `lhs == rhs`, otherwise `false`.
---
```cpp
static bool ne(first_argument_type lhs, second_argument_type rhs)
```
**Return**
`true` if `lhs != rhs`, otherwise `false`.
---
```cpp
static cmp_result cmp(first_argument_type lhs, second_argument_type rhs)
```
**Return**
`Less`, `Equal`, or `Greater`.
## Three-way comparison
`etl::three_way_compare(lhs, rhs)` returns the same ordering as `compare<T, TLess>::cmp(lhs, rhs)`,
but as an `int` with the values `-1`, `0`, or `1`.
## C++20 comparison categories
When compiling as C++20, `compare.h` makes the comparison categories available in the `etl`
namespace, so ETL and user code can name them regardless of the STL configuration.
```cpp
class strong_ordering;
class weak_ordering;
class partial_ordering;
```
* When the STL is available these are aliases for `std::strong_ordering`, `std::weak_ordering`
and `std::partial_ordering`.
* When the STL is not available, `compare.h` provides its own minimal implementations that
follow the standard semantics: the named values `less`, `equivalent`, `greater`
(plus `equal` for `strong_ordering` and `unordered` for `partial_ordering`), comparison
against the literal `0` only, and the implicit conversions
`strong_ordering` &rarr; `weak_ordering` &rarr; `partial_ordering`.
An `unordered` result compares `false` against `0` for all of `<`, `<=`, `==`, `>=` and `>`.
```cpp
ETL_CONSTEXPR strong_ordering make_strong_ordering(int value) ETL_NOEXCEPT;
ETL_CONSTEXPR weak_ordering make_weak_ordering(int value) ETL_NOEXCEPT;
ETL_CONSTEXPR partial_ordering make_partial_ordering(int value) ETL_NOEXCEPT;
```
These helpers convert a three-way comparison result, such as the one returned by
`etl::three_way_compare`, into a comparison category. Negative values map to `less`, positive
values to `greater`, and zero to `equal`/`equivalent`. `unordered` cannot be expressed as an
integer result, so use `etl::partial_ordering::unordered` directly for that case.
## Example 1
```cpp
using std::less
struct Test
{
int a;
@ -84,6 +153,11 @@ bool operator >=(const Test& lhs, const Test& rhs)
{
return Compare::gte(lhs, rhs);
}
int operator <=>(const Test& lhs, const Test& rhs)
{
return etl::three_way_compare(lhs, rhs);
}
```
## Example 2
@ -124,6 +198,11 @@ bool operator >=(const Test& lhs, const Test& rhs)
{
return Compare::gte(lhs, rhs);
}
int operator <=>(const Test& lhs, const Test& rhs)
{
return etl::three_way_compare<Test, LessThan>(lhs, rhs);
}
```
## Example 3
@ -158,3 +237,13 @@ bool operator >=(const Test& lhs, const Test& rhs)
return Test::gte(lhs, rhs);
}
```
## Example 4
C++20, with or without the STL.
```cpp
etl::strong_ordering operator <=>(const Test& lhs, const Test& rhs)
{
return etl::make_strong_ordering(etl::three_way_compare(lhs, rhs));
}
```

View File

@ -15,6 +15,9 @@ Supports compile time and runtime variants.
template <typename T, const T First = 0, const T Last = 0>
class cyclic_value
```
Static asserts if `Last` < `First`.
**Example**
```cpp
etl::cyclic_value<int, 2, 7> value_ct; // Compile time. Fixed range of 2 to 7 inclusive.
@ -24,126 +27,183 @@ value_rt.set(3, 8);
```
## Constructor
### Run time limits
```cpp
cyclic_value<int> value;
cyclic_value<T>() noexcept;
```
Creates a runtime cyclic value of type int with default constructed initial defined limits.
Constructs a cyclic value of type `T` with an initial value of `first`.
`constexpr` from C++11.
---
```cpp
cyclic_value<int, N, M> value;
cyclic_value<T>(T first, T last);
```
Creates a compile time cyclic value of type int with fixed limits of N and M.
Constructs a *run time* cyclic value of type `T` with limits of `first` and `last` and an initial value of `first`.
Asserts an `etl::cyclic_value_reversed_limits` if `last` < `first`.
`constexpr` from C++11.
---
**Example**
```cpp
cyclic_value<int> value(N, M);
cyclic_value<T>(T first, T last, T initial);
```
Creates a runtime cyclic value of type int with initial defined limits of N and M.
Constructs a cyclic value of type `T` with limits of `first` and `last` and an initial value of `initial`.
`initial` will be clamped to be in the range `(first, last)`.
Asserts an `etl::cyclic_value_reversed_limits` if `last` < `first`.
`constexpr` from C++11.
### Compile time limits
```cpp
cyclic_value<T, First, Last>() noexcept;
```
Constructs a cyclic value of type `T` default constructed with an initial value of `First`.
`constexpr` from C++11.
---
```cpp
cyclic_value<T, First, Last>(T initial) noexcept;
```
Constructs a cyclic value of type `T` constructed with an `initial`.
`initial` will be clamped to be in the range `(First, Last)`.
`constexpr` from C++11.
## Modifiers
```cpp
cyclic_value& operator ++();
cyclic_value& operator ++(int);
cyclic_value& operator ++() noexcept;
cyclic_value& operator ++(int) noexcept;
```
Increments the value. If the value is at the last value then is set to the first.
Increments the value. If the value is at the last value then is set to the first.
`constexpr` from C++14.
---
```cpp
cyclic_value& operator --();
cyclic_value& operator --(int);
cyclic_value& operator --() noexcept;
cyclic_value& operator --(int) noexcept;
```
Decrements the value. If the value is at the first value then is set to the last.
Decrements the value. If the value is at the first value then is set to the last.
`constexpr` from C++14.
---
```cpp
void advance(int n);
template <typename TStep>
void advance(TStep n) noexcept;
```
Advances the value by the specified amount, wrapping if necessary.
Advances the value by the specified amount, wrapping if necessary.
`constexpr` from C++14.
---
```cpp
template <typename TStep>
cyclic_value& operator +=(TStep n) noexcept;
```
Advances the value by the specified amount, wrapping if necessary.
`constexpr` from C++14.
---
```cpp
template <typename TStep>
cyclic_value& operator -=(TStep n) noexcept;
```
Decrements the value by the specified amount, wrapping if necessary.
`constexpr` from C++14.
## Access
```cpp
T get() const;
```
Gets the current value
Gets the current value.
`constexpr` from C++11.
---
```cpp
T first() const;
T first() const noexcept;
```
Sets the current value to the first value
Gets the first value.
`constexpr` from C++11.
---
```cpp
T last() const;
T last() const noexcept;
```
Sets the current value to the last value
Gets the last value.
`constexpr` from C++11.
---
```cpp
void set(T first, T last);
void set(T first, T last) noexcept;
```
Sets the new first and last values. Sets the current value to first.
Sets the new *run time* `first` and `last` values. Sets the current value to `first`.
Asserts an `etl::cyclic_value_reversed_limits` if `last` < `first`.
`constexpr` from C++14.
---
```cpp
void set(T value);
void set(T value) noexcept;
```
Sets the current value.
Sets the current value.
`constexpr` from C++14.
---
```cpp
void to_first();
void to_first() noexcept;
```
Sets the current value to the first value
Sets the current value to the first value.
`constexpr` from C++14.
---
```cpp
void to_last();
void to_last() noexcept;
```
Sets the current value to the last value
Sets the current value to the last value.
`constexpr` from C++14.
## Operations
```cpp
void swap(cyclic_value<T, FIRST, LAST>& other);
void swap(cyclic_value<T, FIRST, LAST>& other) noexcept;
```
Swaps with another cyclic value.
Swaps with another cyclic value.
`constexpr` from C++14.
---
```cpp
void swap(cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs);
```
Swaps with another cyclic value.
## Operators
```cpp
operator T();
operator const T() const;
operator T() noexcept;
operator const T() const noexcept;
```
Conversion operators to `T`.
Conversion operators to `T`.
`constexpr` from C++11.
---
```cpp
cyclic_value& operator =(T t);
cyclic_value& operator =(T t) noexcept;
```
Sets the current value to `t`.
Sets the current value to `t`.
`constexpr` from C++14.
## Non-member functions
```cpp
template <typename T, const T FIRST, const T LAST>
void swap(cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs)
void swap(cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept
```
Swaps two cyclic values.
@ -151,14 +211,63 @@ Swaps two cyclic values.
```cpp
template <typename T, const T FIRST, const T LAST>
bool operator == (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs)
bool operator == (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept
```
Checks equality of two cyclic values.
Checks equality of two cyclic values.
`constexpr` from C++11.
{{< callout type="warning">}}
After version `20.49.0` equality is judged only by the current value.
Previously the first and last limits were also considered.
<= 20.49.0
`etl::cyclic_value<2, 7>(3) != etl::cyclic_value<2, 6>(3)`
&gt; 20.49.0
`etl::cyclic_value<2, 7>(3) == etl::cyclic_value<2, 6>(3)`
{{< /callout >}}
---
```cpp
template <typename T, const T FIRST, const T LAST>
bool operator != (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs)
bool operator != (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept
```
Checks inequality of two cyclic values.
Checks inequality of two cyclic values.
`constexpr` from C++11.
---
```cpp
template <typename T, const T FIRST, const T LAST>
bool operator < (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept
```
Checks if the current value of `lhs` is less than the current value of `rhs`.
`constexpr` from C++11.
---
```cpp
template <typename T, const T FIRST, const T LAST>
bool operator <= (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept
```
Checks if the current value of `lhs` is less than or equal the current value of `rhs`.
`constexpr` from C++11.
---
```cpp
template <typename T, const T FIRST, const T LAST>
bool operator > (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept
```
Checks if the current value of `lhs` is greater than the current value of `rhs`.
`constexpr` from C++11.
---
```cpp
template <typename T, const T FIRST, const T LAST>
bool operator >= (cyclic_value<T, FIRST, LAST>& lhs, cyclic_value<T, FIRST, LAST>& rhs) noexcept
```
Checks if the current value of `lhs` is greater than or equal the current value of `rhs`.
`constexpr` from C++11.

View File

@ -137,7 +137,7 @@ namespace etl
/// Returns a reference to the value at index 'i'.
///\param i The index of the element to access.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR14 reference operator[](size_t i) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_INDEX_OPERATOR)
ETL_NODISCARD ETL_CONSTEXPR14 reference operator[](size_t i) ETL_NOEXCEPT_EXPR(ETL_NOT_CHECKING_INDEX_OPERATOR)
{
ETL_ASSERT_CHECK_INDEX_OPERATOR(i < SIZE, ETL_ERROR(array_out_of_range));
@ -149,7 +149,7 @@ namespace etl
/// Returns a const reference to the value at index 'i'.
///\param i The index of the element to access.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR const_reference operator[](size_t i) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_INDEX_OPERATOR)
ETL_NODISCARD ETL_CONSTEXPR const_reference operator[](size_t i) const ETL_NOEXCEPT_EXPR(ETL_NOT_CHECKING_INDEX_OPERATOR)
{
// Throwing from c++11 constexpr requires special syntax
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_INDEX_OPERATOR

View File

@ -518,7 +518,7 @@ namespace etl
/// If asserts or exceptions are enabled, throws an etl::array_view_bounds
/// if the index is out of bounds.
//*************************************************************************
reference operator[](const size_t i) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_INDEX_OPERATOR)
reference operator[](const size_t i) ETL_NOEXCEPT_EXPR(ETL_NOT_CHECKING_INDEX_OPERATOR)
{
ETL_ASSERT_CHECK_INDEX_OPERATOR(i < size(), ETL_ERROR(array_view_bounds));
@ -531,7 +531,7 @@ namespace etl
/// If asserts or exceptions are enabled, throws an etl::array_view_bounds
/// if the index is out of bounds.
//*************************************************************************
const_reference operator[](const size_t i) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_INDEX_OPERATOR)
const_reference operator[](const size_t i) const ETL_NOEXCEPT_EXPR(ETL_NOT_CHECKING_INDEX_OPERATOR)
{
ETL_ASSERT_CHECK_INDEX_OPERATOR(i < size(), ETL_ERROR(array_view_bounds));

View File

@ -271,7 +271,7 @@ namespace etl
/// If asserts or exceptions are enabled, throws an
/// etl::array_wrapper_bounds if the index is out of bounds.
//*************************************************************************
reference operator[](size_t i) ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_INDEX_OPERATOR)
reference operator[](size_t i) ETL_NOEXCEPT_EXPR(ETL_NOT_CHECKING_INDEX_OPERATOR)
{
ETL_ASSERT_CHECK_INDEX_OPERATOR(i < SIZE, ETL_ERROR(etl::array_wrapper_bounds));
return ARRAY_[i];
@ -282,7 +282,7 @@ namespace etl
/// If asserts or exceptions are enabled, throws an
/// etl::array_wrapper_bounds if the index is out of bounds.
//*************************************************************************
ETL_CONSTEXPR const_reference operator[](size_t i) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_INDEX_OPERATOR)
ETL_CONSTEXPR const_reference operator[](size_t i) const ETL_NOEXCEPT_EXPR(ETL_NOT_CHECKING_INDEX_OPERATOR)
{
// Throwing from c++11 constexpr requires special syntax
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_INDEX_OPERATOR

View File

@ -411,6 +411,16 @@ namespace etl
return false;
}
//*******************************************
/// Returns true if an attempt was ever made to insert a timer into the
/// active list when it was already there. Such an insert is rejected, as
/// it would create a circular reference in the list.
//*******************************************
bool duplicate_insert_detected() const
{
return active_list.duplicate_insert_detected();
}
//*******************************************
/// Check if there is an active timer.
//*******************************************
@ -630,6 +640,7 @@ namespace etl
: head(etl::timer::id::NO_TIMER)
, tail(etl::timer::id::NO_TIMER)
, ptimers(ptimers_)
, duplicate_insert(false)
{
}
@ -639,6 +650,15 @@ namespace etl
return head == etl::timer::id::NO_TIMER;
}
//*******************************
/// Returns true if an attempt was ever made to insert a timer that was
/// already in the list.
//*******************************
bool duplicate_insert_detected() const
{
return duplicate_insert;
}
//*******************************
// Inserts the timer at the correct delta position
//*******************************
@ -646,6 +666,16 @@ namespace etl
{
timer_data& timer = ptimers[id_];
// A timer is in this list exactly when it is the head or has a previous
// link, as remove() clears both links. Inserting one that is already
// here would link it to itself and create a circular reference, so
// record the attempt and abandon the insert to keep the list intact.
if ((head == id_) || (timer.previous != etl::timer::id::NO_TIMER))
{
duplicate_insert = true;
return;
}
if (head == etl::timer::id::NO_TIMER)
{
// No entries yet.
@ -788,6 +818,10 @@ namespace etl
etl::timer::id::type tail;
timer_data* const ptimers;
// Set if an attempt was ever made to insert a timer that was already
// in the list.
bool duplicate_insert;
};
// The array of timer data structures.

View File

@ -174,12 +174,9 @@ namespace etl
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
if (timer.callback.is_valid())
{
// Call the delegate callback.
timer.callback();
}
// The timer is reinserted before the callback is called, so that
// a callback that restarts the timer replaces this entry instead
// of the timer being inserted into the active list twice.
if (timer.repeating)
{
// Reinsert the timer.
@ -188,6 +185,11 @@ namespace etl
insert_callback.call_if(timer.id);
}
if (timer.callback.is_valid())
{
timer.callback();
}
has_active = !active_list.empty();
}
@ -301,6 +303,16 @@ namespace etl
return false;
}
//*******************************************
/// Returns true if an attempt was ever made to insert a timer into the
/// active list when it was already there. Such an insert is rejected, as
/// it would create a circular reference in the list.
//*******************************************
bool duplicate_insert_detected() const
{
return active_list.duplicate_insert_detected();
}
//*******************************************
/// Check if there is an active timer.
//*******************************************
@ -486,6 +498,7 @@ namespace etl
: head(etl::timer::id::NO_TIMER)
, tail(etl::timer::id::NO_TIMER)
, ptimers(ptimers_)
, duplicate_insert(false)
{
}
@ -495,6 +508,15 @@ namespace etl
return head == etl::timer::id::NO_TIMER;
}
//*******************************
/// Returns true if an attempt was ever made to insert a timer that was
/// already in the list.
//*******************************
bool duplicate_insert_detected() const
{
return duplicate_insert;
}
//*******************************
// Inserts the timer at the correct delta position
//*******************************
@ -502,6 +524,16 @@ namespace etl
{
timer_data& timer = ptimers[id_];
// A timer is in this list exactly when it is the head or has a previous
// link, as remove() clears both links. Inserting one that is already
// here would link it to itself and create a circular reference, so
// record the attempt and abandon the insert to keep the list intact.
if ((head == id_) || (timer.previous != etl::timer::id::NO_TIMER))
{
duplicate_insert = true;
return;
}
if (head == etl::timer::id::NO_TIMER)
{
// No entries yet.
@ -644,6 +676,10 @@ namespace etl
etl::timer::id::type tail;
timer_data* const ptimers;
// Set if an attempt was ever made to insert a timer that was already
// in the list.
bool duplicate_insert;
};
// The array of timer data structures.

View File

@ -178,11 +178,9 @@ namespace etl
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
if (timer.callback.is_valid())
{
timer.callback();
}
// The timer is reinserted before the callback is called, so that
// a callback that restarts the timer replaces this entry instead
// of the timer being inserted into the active list twice.
if (timer.repeating)
{
// Reinsert the timer.
@ -191,6 +189,11 @@ namespace etl
insert_callback.call_if(timer.id);
}
if (timer.callback.is_valid())
{
timer.callback();
}
has_active = !active_list.empty();
}
@ -305,6 +308,16 @@ namespace etl
return false;
}
//*******************************************
/// Returns true if an attempt was ever made to insert a timer into the
/// active list when it was already there. Such an insert is rejected, as
/// it would create a circular reference in the list.
//*******************************************
bool duplicate_insert_detected() const
{
return active_list.duplicate_insert_detected();
}
//*******************************************
/// Check if there is an active timer.
//*******************************************
@ -487,6 +500,7 @@ namespace etl
: head(etl::timer::id::NO_TIMER)
, tail(etl::timer::id::NO_TIMER)
, ptimers(ptimers_)
, duplicate_insert(false)
{
}
@ -496,6 +510,15 @@ namespace etl
return head == etl::timer::id::NO_TIMER;
}
//*******************************
/// Returns true if an attempt was ever made to insert a timer that was
/// already in the list.
//*******************************
bool duplicate_insert_detected() const
{
return duplicate_insert;
}
//*******************************
// Inserts the timer at the correct delta position
//*******************************
@ -503,6 +526,16 @@ namespace etl
{
timer_data& timer = ptimers[id_];
// A timer is in this list exactly when it is the head or has a previous
// link, as remove() clears both links. Inserting one that is already
// here would link it to itself and create a circular reference, so
// record the attempt and abandon the insert to keep the list intact.
if ((head == id_) || (timer.previous != etl::timer::id::NO_TIMER))
{
duplicate_insert = true;
return;
}
if (head == etl::timer::id::NO_TIMER)
{
// No entries yet.
@ -645,6 +678,10 @@ namespace etl
etl::timer::id::type tail;
timer_data* const ptimers;
// Set if an attempt was ever made to insert a timer that was already
// in the list.
bool duplicate_insert;
};
// The array of timer data structures.

View File

@ -264,6 +264,16 @@ namespace etl
unlock = unlock_;
}
//*******************************************
/// Returns true if an attempt was ever made to insert a timer into the
/// active list when it was already there. Such an insert is rejected, as
/// it would create a circular reference in the list.
//*******************************************
bool duplicate_insert_detected() const
{
return active_list.duplicate_insert_detected();
}
//*******************************************
/// Check if there is an active timer.
//*******************************************
@ -460,6 +470,7 @@ namespace etl
: head(etl::timer::id::NO_TIMER)
, tail(etl::timer::id::NO_TIMER)
, ptimers(ptimers_)
, duplicate_insert(false)
{
}
@ -469,6 +480,15 @@ namespace etl
return head == etl::timer::id::NO_TIMER;
}
//*******************************
/// Returns true if an attempt was ever made to insert a timer that was
/// already in the list.
//*******************************
bool duplicate_insert_detected() const
{
return duplicate_insert;
}
//*******************************
// Inserts the timer at the correct delta position
//*******************************
@ -476,6 +496,16 @@ namespace etl
{
timer_data& timer = ptimers[id_];
// A timer is in this list exactly when it is the head or has a previous
// link, as remove() clears both links. Inserting one that is already
// here would link it to itself and create a circular reference, so
// record the attempt and abandon the insert to keep the list intact.
if ((head == id_) || (timer.previous != etl::timer::id::NO_TIMER))
{
duplicate_insert = true;
return;
}
if (head == etl::timer::id::NO_TIMER)
{
// No entries yet.
@ -618,6 +648,10 @@ namespace etl
etl::timer::id::type tail;
timer_data* const ptimers;
// Set if an attempt was ever made to insert a timer that was already
// in the list.
bool duplicate_insert;
};
//*******************************************
@ -716,11 +750,9 @@ namespace etl
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
if (timer.callback.is_valid())
{
timer.callback();
}
// The timer is reinserted before the callback is called, so that
// a callback that restarts the timer replaces this entry instead
// of the timer being inserted into the active list twice.
if (timer.repeating)
{
// Reinsert the timer.
@ -729,6 +761,11 @@ namespace etl
insert_callback.call_if(timer.id);
}
if (timer.callback.is_valid())
{
timer.callback();
}
has_active = !active_list.empty();
}

View File

@ -37,6 +37,7 @@ SOFTWARE.
#if ETL_USING_CPP11
#include "compare.h"
#include "hash.h"
#include "integral_limits.h"
#include "type_traits.h"

View File

@ -35,6 +35,7 @@ SOFTWARE.
#include "absolute.h"
#include "algorithm.h"
#include "error_handler.h"
#include "functional.h"
#include "limits.h"
#include "math.h"
#include "static_assert.h"
@ -978,6 +979,400 @@ namespace etl
T min_value;
T max_value;
};
#if ETL_USING_CPP11
//***************************************************************************
/// An immutable pair of runtime limits that may be shared by multiple
/// referenced_clamped_value objects.
///@tparam T An integral type, or a floating-point type when
/// ETL_HAS_FLOATING_POINT_CLAMPED_VALUE is `1`.
///\ingroup clamped_value
//***************************************************************************
template <typename T>
class clamped_value_range
{
public:
typedef typename private_clamped_value::traits<T>::limits_type limits_type;
//*************************************************************************
/// Constructs the full representable range of T.
//*************************************************************************
ETL_CONSTEXPR14 clamped_value_range()
: min_value(limits_type::lowest())
, max_value(limits_type::max())
{
}
//*************************************************************************
/// Constructs a range with the supplied limits.
/// Reversed bounds and NaN bounds are rejected.
///\param min_ The minimum value.
///\param max_ The maximum value.
//*************************************************************************
ETL_CONSTEXPR14 clamped_value_range(T min_, T max_)
: min_value(min_)
, max_value(max_)
{
private_clamped_value::validate(min_);
private_clamped_value::validate(max_);
ETL_ASSERT(min_ <= max_, ETL_ERROR_GENERIC("clamped_value_range: invalid range"));
}
//*************************************************************************
/// Gets the minimum value.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR T min() const ETL_NOEXCEPT
{
return min_value;
}
//*************************************************************************
/// Gets the maximum value.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR T max() const ETL_NOEXCEPT
{
return max_value;
}
private:
const T min_value;
const T max_value;
};
//***************************************************************************
/// Provides a value clamped to a shared immutable runtime range.
/// The referenced range must outlive this object.
///@tparam T An integral type, or a floating-point type when
/// ETL_HAS_FLOATING_POINT_CLAMPED_VALUE is `1`.
///\ingroup clamped_value
//***************************************************************************
template <typename T>
class referenced_clamped_value
{
public:
/// The referenced range type.
typedef clamped_value_range<T> range_type;
/// The type used to advance or subtract from the stored value.
typedef typename private_clamped_value::traits<T>::difference_type difference_type;
/// Numeric limits for the stored value type.
typedef typename private_clamped_value::traits<T>::limits_type limits_type;
/// Numeric limits for difference_type.
typedef typename private_clamped_value::traits<T>::difference_limits_type difference_limits_type;
//*************************************************************************
/// Constructs a value initialized to the minimum of the referenced range.
///\param range_ The range to reference. It must outlive this object.
//*************************************************************************
explicit referenced_clamped_value(const range_type& range_)
: value(range_.min())
, value_range(etl::cref(range_))
{
}
//*************************************************************************
/// Constructs a value clamped to the referenced range.
///\param range_ The range to reference. It must outlive this object.
///\param initial The initial value.
//*************************************************************************
referenced_clamped_value(const range_type& range_, T initial)
: value(private_clamped_value::validated_clamp(initial, range_.min(), range_.max()))
, value_range(etl::cref(range_))
{
}
//*************************************************************************
/// Prevents construction with a temporary range.
//*************************************************************************
referenced_clamped_value(range_type&&) = delete;
referenced_clamped_value(range_type&&, T) = delete;
//*************************************************************************
/// Copies the value and its range reference.
///\param other The value to copy.
//*************************************************************************
referenced_clamped_value(const referenced_clamped_value& other) ETL_NOEXCEPT
: value(other.value)
, value_range(other.value_range)
{
}
//*************************************************************************
/// Copy assignment. Copies the value and its range reference.
///\param other The value and range reference to copy.
///\return A reference to this value.
//*************************************************************************
referenced_clamped_value& operator=(const referenced_clamped_value& other) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
if (this != &other)
{
value = other.value;
value_range = other.value_range;
}
return *this;
}
//*************************************************************************
/// Sets the value and clamps it to the referenced range.
///\param value_ The value to assign.
//*************************************************************************
void set(T value_)
{
value = private_clamped_value::validated_clamp(value_, min(), max());
}
//*************************************************************************
/// Resets the value to the minimum of the referenced range.
//*************************************************************************
void to_min() ETL_NOEXCEPT
{
value = min();
}
//*************************************************************************
/// Resets the value to the maximum of the referenced range.
//*************************************************************************
void to_max() ETL_NOEXCEPT
{
value = max();
}
//*************************************************************************
/// Advances the value and saturates it at the referenced bounds.
///\param n The difference to add.
//*************************************************************************
void advance(difference_type n)
{
private_clamped_value::validate(n);
value = private_clamped_value::advance(value, min(), max(), n);
}
//*************************************************************************
/// Converts to the underlying value type.
///\return The current value.
//*************************************************************************
ETL_NODISCARD operator T() const ETL_NOEXCEPT
{
return value;
}
//*************************************************************************
/// Advances by one and saturates at the maximum.
///\return A reference to this value.
//*************************************************************************
referenced_clamped_value& operator++() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
value = private_clamped_value::advance(value, min(), max(), difference_type(1));
return *this;
}
//*************************************************************************
/// Advances by one and returns the previous value.
///\return The value before incrementing.
//*************************************************************************
referenced_clamped_value operator++(int) ETL_NOEXCEPT
{
referenced_clamped_value temp(*this);
++(*this);
return temp;
}
//*************************************************************************
/// Subtracts one and saturates at the minimum.
///\return A reference to this value.
//*************************************************************************
referenced_clamped_value& operator--() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
value = private_clamped_value::advance(value, min(), max(), difference_type(-1));
return *this;
}
//*************************************************************************
/// Subtracts one and returns the previous value.
///\return The value before decrementing.
//*************************************************************************
referenced_clamped_value operator--(int) ETL_NOEXCEPT
{
referenced_clamped_value temp(*this);
--(*this);
return temp;
}
//*************************************************************************
/// Assigns a value and clamps it to the referenced range.
///\param value_ The value to assign.
///\return A reference to this value.
//*************************************************************************
referenced_clamped_value& operator=(T value_) ETL_LVALUE_REF_QUALIFIER
{
set(value_);
return *this;
}
//*************************************************************************
/// Adds a difference and clamps to the referenced range.
///\param n The difference to add.
///\return A reference to this value.
//*************************************************************************
referenced_clamped_value& operator+=(difference_type n) ETL_LVALUE_REF_QUALIFIER
{
advance(n);
return *this;
}
//*************************************************************************
/// Subtracts a difference and clamps to the referenced range.
///\param n The difference to subtract.
///\return A reference to this value.
//*************************************************************************
referenced_clamped_value& operator-=(difference_type n) ETL_LVALUE_REF_QUALIFIER
{
private_clamped_value::validate(n);
value = private_clamped_value::subtract(value, min(), max(), n);
return *this;
}
//*************************************************************************
/// Gets the current value.
///\return The current value.
//*************************************************************************
ETL_NODISCARD
T get() const ETL_NOEXCEPT
{
return value;
}
//*************************************************************************
/// Gets the minimum of the referenced range.
///\return The minimum value.
//*************************************************************************
ETL_NODISCARD
T min() const ETL_NOEXCEPT
{
return value_range.get().min();
}
//*************************************************************************
/// Gets the maximum of the referenced range.
///\return The maximum value.
//*************************************************************************
ETL_NODISCARD
T max() const ETL_NOEXCEPT
{
return value_range.get().max();
}
//*************************************************************************
/// Gets the referenced range.
///\return The referenced range.
//*************************************************************************
ETL_NODISCARD
const range_type& range() const ETL_NOEXCEPT
{
return value_range.get();
}
//*************************************************************************
/// Swaps the values and range references.
///\param other The value to swap with.
//*************************************************************************
void swap(referenced_clamped_value& other) ETL_NOEXCEPT
{
using ETL_OR_STD::swap;
swap(value, other.value);
swap(value_range, other.value_range);
}
//*************************************************************************
/// Swaps the values and range references.
///\param lhs The first value.
///\param rhs The second value.
//*************************************************************************
friend void swap(referenced_clamped_value& lhs, referenced_clamped_value& rhs) ETL_NOEXCEPT
{
lhs.swap(rhs);
}
//*************************************************************************
/// Compares current values for equality.
///\param lhs The left-hand value.
///\param rhs The right-hand value.
///\return `true` if the current values are equal.
//*************************************************************************
friend bool operator==(const referenced_clamped_value& lhs, const referenced_clamped_value& rhs) ETL_NOEXCEPT
{
#include "private/diagnostic_float_equal_push.h"
return lhs.value == rhs.value;
#include "private/diagnostic_pop.h"
}
//*************************************************************************
/// Compares current values for inequality.
///\param lhs The left-hand value.
///\param rhs The right-hand value.
///\return `true` if the current values differ.
//*************************************************************************
friend bool operator!=(const referenced_clamped_value& lhs, const referenced_clamped_value& rhs) ETL_NOEXCEPT
{
return !(lhs == rhs);
}
//*************************************************************************
/// Compares current values using less-than.
///\param lhs The left-hand value.
///\param rhs The right-hand value.
///\return `true` if lhs is less than rhs.
//*************************************************************************
friend bool operator<(const referenced_clamped_value& lhs, const referenced_clamped_value& rhs) ETL_NOEXCEPT
{
return lhs.value < rhs.value;
}
//*************************************************************************
/// Compares current values using less-than-or-equal.
///\param lhs The left-hand value.
///\param rhs The right-hand value.
///\return `true` if lhs is less than or equal to rhs.
//*************************************************************************
friend bool operator<=(const referenced_clamped_value& lhs, const referenced_clamped_value& rhs) ETL_NOEXCEPT
{
return !(rhs < lhs);
}
//*************************************************************************
/// Compares current values using greater-than.
///\param lhs The left-hand value.
///\param rhs The right-hand value.
///\return `true` if lhs is greater than rhs.
//*************************************************************************
friend bool operator>(const referenced_clamped_value& lhs, const referenced_clamped_value& rhs) ETL_NOEXCEPT
{
return rhs < lhs;
}
//*************************************************************************
/// Compares current values using greater-than-or-equal.
///\param lhs The left-hand value.
///\param rhs The right-hand value.
///\return `true` if lhs is greater than or equal to rhs.
//*************************************************************************
friend bool operator>=(const referenced_clamped_value& lhs, const referenced_clamped_value& rhs) ETL_NOEXCEPT
{
return !(lhs < rhs);
}
private:
T value;
etl::reference_wrapper<const range_type> value_range;
};
#endif
} // namespace etl
#endif

View File

@ -35,6 +35,10 @@ SOFTWARE.
#include "functional.h"
#include "parameter_type.h"
#if ETL_USING_CPP20 && ETL_USING_STL
#include <compare>
#endif
//*****************************************************************************
///\defgroup compare compare
/// Comparisons only using less than operator
@ -42,6 +46,295 @@ SOFTWARE.
//*****************************************************************************
namespace etl
{
#if ETL_USING_CPP20
#if ETL_USING_STL
//***************************************************************************
/// The STL supplies the C++20 comparison categories, so simply expose them
/// through the etl namespace. This allows ETL code and user code to refer to
/// etl::strong_ordering (etc.) regardless of the STL configuration.
//***************************************************************************
using std::partial_ordering;
using std::strong_ordering;
using std::weak_ordering;
#else
namespace private_compare
{
//*************************************************************************
/// A type that can only be constructed from the literal 0.
/// Used to constrain the comparison-category operators to comparisons
/// against the literal 0, as required by the standard.
//*************************************************************************
struct only_literal_zero
{
ETL_CONSTEXPR only_literal_zero(only_literal_zero*) ETL_NOEXCEPT {}
};
typedef signed char ordering_value_type;
inline constexpr ordering_value_type ordering_less = -1;
inline constexpr ordering_value_type ordering_equivalent = 0;
inline constexpr ordering_value_type ordering_greater = 1;
inline constexpr ordering_value_type ordering_unordered = 2;
} // namespace private_compare
//***************************************************************************
/// Minimal partial-ordering category for C++20 three-way comparisons when the
/// STL is unavailable.
/// Unlike the other categories this one has an 'unordered' state, for which
/// every comparison against 0 is false.
//***************************************************************************
class partial_ordering
{
public:
static const partial_ordering less;
static const partial_ordering equivalent;
static const partial_ordering greater;
static const partial_ordering unordered;
friend ETL_CONSTEXPR bool operator==(partial_ordering lhs, partial_ordering rhs) ETL_NOEXCEPT = default;
friend ETL_CONSTEXPR bool operator==(partial_ordering v, private_compare::only_literal_zero) ETL_NOEXCEPT
{
return v.value == private_compare::ordering_equivalent;
}
friend ETL_CONSTEXPR bool operator<(partial_ordering v, private_compare::only_literal_zero) ETL_NOEXCEPT
{
return v.value == private_compare::ordering_less;
}
friend ETL_CONSTEXPR bool operator>(partial_ordering v, private_compare::only_literal_zero) ETL_NOEXCEPT
{
return v.value == private_compare::ordering_greater;
}
friend ETL_CONSTEXPR bool operator<=(partial_ordering v, private_compare::only_literal_zero) ETL_NOEXCEPT
{
return (v.value == private_compare::ordering_less) || (v.value == private_compare::ordering_equivalent);
}
friend ETL_CONSTEXPR bool operator>=(partial_ordering v, private_compare::only_literal_zero) ETL_NOEXCEPT
{
return (v.value == private_compare::ordering_greater) || (v.value == private_compare::ordering_equivalent);
}
friend ETL_CONSTEXPR bool operator<(private_compare::only_literal_zero, partial_ordering v) ETL_NOEXCEPT
{
return v > 0;
}
friend ETL_CONSTEXPR bool operator>(private_compare::only_literal_zero, partial_ordering v) ETL_NOEXCEPT
{
return v < 0;
}
friend ETL_CONSTEXPR bool operator<=(private_compare::only_literal_zero, partial_ordering v) ETL_NOEXCEPT
{
return v >= 0;
}
friend ETL_CONSTEXPR bool operator>=(private_compare::only_literal_zero, partial_ordering v) ETL_NOEXCEPT
{
return v <= 0;
}
private:
explicit ETL_CONSTEXPR partial_ordering(private_compare::ordering_value_type value_) ETL_NOEXCEPT
: value(value_)
{
}
friend class weak_ordering;
friend class strong_ordering;
private_compare::ordering_value_type value;
};
inline constexpr partial_ordering partial_ordering::less(private_compare::ordering_less);
inline constexpr partial_ordering partial_ordering::equivalent(private_compare::ordering_equivalent);
inline constexpr partial_ordering partial_ordering::greater(private_compare::ordering_greater);
inline constexpr partial_ordering partial_ordering::unordered(private_compare::ordering_unordered);
//***************************************************************************
/// Minimal weak-ordering category for C++20 three-way comparisons when the
/// STL is unavailable.
//***************************************************************************
class weak_ordering
{
public:
static const weak_ordering less;
static const weak_ordering equivalent;
static const weak_ordering greater;
ETL_CONSTEXPR operator partial_ordering() const ETL_NOEXCEPT
{
return partial_ordering(value);
}
friend ETL_CONSTEXPR bool operator==(weak_ordering lhs, weak_ordering rhs) ETL_NOEXCEPT = default;
friend ETL_CONSTEXPR bool operator==(weak_ordering v, private_compare::only_literal_zero) ETL_NOEXCEPT
{
return v.value == private_compare::ordering_equivalent;
}
friend ETL_CONSTEXPR bool operator<(weak_ordering v, private_compare::only_literal_zero) ETL_NOEXCEPT
{
return v.value < private_compare::ordering_equivalent;
}
friend ETL_CONSTEXPR bool operator>(weak_ordering v, private_compare::only_literal_zero) ETL_NOEXCEPT
{
return v.value > private_compare::ordering_equivalent;
}
friend ETL_CONSTEXPR bool operator<=(weak_ordering v, private_compare::only_literal_zero) ETL_NOEXCEPT
{
return v.value <= private_compare::ordering_equivalent;
}
friend ETL_CONSTEXPR bool operator>=(weak_ordering v, private_compare::only_literal_zero) ETL_NOEXCEPT
{
return v.value >= private_compare::ordering_equivalent;
}
friend ETL_CONSTEXPR bool operator<(private_compare::only_literal_zero, weak_ordering v) ETL_NOEXCEPT
{
return v > 0;
}
friend ETL_CONSTEXPR bool operator>(private_compare::only_literal_zero, weak_ordering v) ETL_NOEXCEPT
{
return v < 0;
}
friend ETL_CONSTEXPR bool operator<=(private_compare::only_literal_zero, weak_ordering v) ETL_NOEXCEPT
{
return v >= 0;
}
friend ETL_CONSTEXPR bool operator>=(private_compare::only_literal_zero, weak_ordering v) ETL_NOEXCEPT
{
return v <= 0;
}
private:
explicit ETL_CONSTEXPR weak_ordering(private_compare::ordering_value_type value_) ETL_NOEXCEPT
: value(value_)
{
}
friend class strong_ordering;
private_compare::ordering_value_type value;
};
inline constexpr weak_ordering weak_ordering::less(private_compare::ordering_less);
inline constexpr weak_ordering weak_ordering::equivalent(private_compare::ordering_equivalent);
inline constexpr weak_ordering weak_ordering::greater(private_compare::ordering_greater);
//***************************************************************************
/// Minimal strong-ordering category for C++20 three-way comparisons when the
/// STL is unavailable.
//***************************************************************************
class strong_ordering
{
public:
static const strong_ordering less;
static const strong_ordering equal;
static const strong_ordering equivalent;
static const strong_ordering greater;
ETL_CONSTEXPR operator partial_ordering() const ETL_NOEXCEPT
{
return partial_ordering(value);
}
ETL_CONSTEXPR operator weak_ordering() const ETL_NOEXCEPT
{
return weak_ordering(value);
}
friend ETL_CONSTEXPR bool operator==(strong_ordering lhs, strong_ordering rhs) ETL_NOEXCEPT = default;
friend ETL_CONSTEXPR bool operator==(strong_ordering v, private_compare::only_literal_zero) ETL_NOEXCEPT
{
return v.value == private_compare::ordering_equivalent;
}
friend ETL_CONSTEXPR bool operator<(strong_ordering v, private_compare::only_literal_zero) ETL_NOEXCEPT
{
return v.value < private_compare::ordering_equivalent;
}
friend ETL_CONSTEXPR bool operator>(strong_ordering v, private_compare::only_literal_zero) ETL_NOEXCEPT
{
return v.value > private_compare::ordering_equivalent;
}
friend ETL_CONSTEXPR bool operator<=(strong_ordering v, private_compare::only_literal_zero) ETL_NOEXCEPT
{
return v.value <= private_compare::ordering_equivalent;
}
friend ETL_CONSTEXPR bool operator>=(strong_ordering v, private_compare::only_literal_zero) ETL_NOEXCEPT
{
return v.value >= private_compare::ordering_equivalent;
}
friend ETL_CONSTEXPR bool operator<(private_compare::only_literal_zero, strong_ordering v) ETL_NOEXCEPT
{
return v > 0;
}
friend ETL_CONSTEXPR bool operator>(private_compare::only_literal_zero, strong_ordering v) ETL_NOEXCEPT
{
return v < 0;
}
friend ETL_CONSTEXPR bool operator<=(private_compare::only_literal_zero, strong_ordering v) ETL_NOEXCEPT
{
return v >= 0;
}
friend ETL_CONSTEXPR bool operator>=(private_compare::only_literal_zero, strong_ordering v) ETL_NOEXCEPT
{
return v <= 0;
}
private:
explicit ETL_CONSTEXPR strong_ordering(private_compare::ordering_value_type value_) ETL_NOEXCEPT
: value(value_)
{
}
private_compare::ordering_value_type value;
};
inline constexpr strong_ordering strong_ordering::less(private_compare::ordering_less);
inline constexpr strong_ordering strong_ordering::equal(private_compare::ordering_equivalent);
inline constexpr strong_ordering strong_ordering::equivalent(private_compare::ordering_equivalent);
inline constexpr strong_ordering strong_ordering::greater(private_compare::ordering_greater);
#endif
//***************************************************************************
/// Converts a three-way comparison result to an etl::strong_ordering.
/// Negative values map to 'less', positive values to 'greater' and zero to
/// 'equal'.
//***************************************************************************
ETL_NODISCARD ETL_CONSTEXPR inline etl::strong_ordering make_strong_ordering(int value) ETL_NOEXCEPT
{
return (value < 0) ? etl::strong_ordering::less : (value > 0) ? etl::strong_ordering::greater : etl::strong_ordering::equal;
}
//***************************************************************************
/// Converts a three-way comparison result to an etl::weak_ordering.
/// Negative values map to 'less', positive values to 'greater' and zero to
/// 'equivalent'.
//***************************************************************************
ETL_NODISCARD ETL_CONSTEXPR inline etl::weak_ordering make_weak_ordering(int value) ETL_NOEXCEPT
{
return (value < 0) ? etl::weak_ordering::less : (value > 0) ? etl::weak_ordering::greater : etl::weak_ordering::equivalent;
}
//***************************************************************************
/// Converts a three-way comparison result to an etl::partial_ordering.
/// Negative values map to 'less', positive values to 'greater' and zero to
/// 'equivalent'.
/// Note that 'unordered' cannot be expressed by an integer comparison result,
/// so use etl::partial_ordering::unordered directly for that case.
//***************************************************************************
ETL_NODISCARD ETL_CONSTEXPR inline etl::partial_ordering make_partial_ordering(int value) ETL_NOEXCEPT
{
return (value < 0) ? etl::partial_ordering::less : (value > 0) ? etl::partial_ordering::greater : etl::partial_ordering::equivalent;
}
#endif
//***************************************************************************
/// Defines <=, >, >=, ==, !=, <=> in terms of <
/// Default implementation of TLess is etl::less
@ -105,7 +398,7 @@ namespace etl
#endif
ETL_CONSTEXPR14 int three_way_compare(const T& lhs, const T& rhs)
{
return etl::compare<T>::cmp(lhs, rhs);
return etl::compare<T, TLess>::cmp(lhs, rhs);
}
} // namespace etl

View File

@ -38,10 +38,198 @@ SOFTWARE.
#include "platform.h"
#include "algorithm.h"
#include "exception.h"
#include "integral_limits.h"
#include "largest.h"
#include "negative.h"
#include "static_assert.h"
#include "type_traits.h"
namespace etl
{
namespace private_cyclic_value
{
template <typename T>
struct traits
{
typedef typename etl::make_unsigned<T>::type unsigned_type;
};
//*************************************************************************
/// Increments a value and wraps it at the supplied limits.
///\param value The current value.
///\param min_value The minimum value.
///\param max_value The maximum value.
///\return The new value.
//*************************************************************************
template <typename T>
ETL_NODISCARD ETL_CONSTEXPR14 T increment(T value, T min_value, T max_value) ETL_NOEXCEPT
{
return value == max_value ? min_value : static_cast<T>(etl::to_unsigned(value) + 1U);
}
//*************************************************************************
/// Decrements a value and wraps it at the supplied limits.
///\param value The current value.
///\param min_value The minimum value.
///\param max_value The maximum value.
///\return The new value.
//*************************************************************************
template <typename T>
ETL_NODISCARD ETL_CONSTEXPR14 T decrement(T value, T min_value, T max_value) ETL_NOEXCEPT
{
return value == min_value ? max_value : static_cast<T>(etl::to_unsigned(value) - 1U);
}
//*************************************************************************
/// Advances a value and wraps it at the supplied limits.
/// Called for the case where the range is not the full width of the type.
///\param value The current value.
///\param min_value The minimum value.
///\param max_value The maximum value.
///\param step The number of steps.
///\param subtract True if the value is to be decremented, false if it is to be incremented.
///\return The advanced value.
//*************************************************************************
template <typename T>
ETL_NODISCARD ETL_CONSTEXPR14 T advance(T value, T min_value, T max_value, typename traits<T>::unsigned_type step, bool subtract) ETL_NOEXCEPT
{
typedef typename traits<T>::unsigned_type unsigned_type;
switch (step)
{
case 0:
{
return value;
}
case 1:
{
return subtract ? decrement(value, min_value, max_value) : increment(value, min_value, max_value);
}
default:
{
if (subtract)
{
unsigned_type distance_to_first = static_cast<unsigned_type>(etl::to_unsigned(value) - etl::to_unsigned(min_value));
if (step <= distance_to_first)
{
// Room to subtract the step.
value = static_cast<T>(etl::to_unsigned(value) - step);
}
else
{
// Step would roll over.
step -= distance_to_first + 1U;
value = static_cast<T>(etl::to_unsigned(max_value) - step);
}
}
else
{
unsigned_type distance_to_last = static_cast<unsigned_type>(etl::to_unsigned(max_value) - etl::to_unsigned(value));
if (step <= distance_to_last)
{
// Room to add the step.
value = static_cast<T>(etl::to_unsigned(value) + step);
}
else
{
// Step would roll over.
step -= distance_to_last + 1U;
value = static_cast<T>(etl::to_unsigned(min_value) + step);
}
}
return value;
}
}
}
//*************************************************************************
/// Advances a value and wraps it at the supplied limits.
/// Called for the case where the range is the full width of the type.
///\param value The current value.
///\param step The number of steps.
///\param subtract True if the value is to be decremented, false if it is to be incremented.
///\return The advanced value.
//*************************************************************************
template <typename T>
ETL_NODISCARD ETL_CONSTEXPR14 T advance(T value, typename traits<T>::unsigned_type step, bool subtract) ETL_NOEXCEPT
{
if (subtract)
{
value = static_cast<T>(etl::to_unsigned(value) - step);
}
else
{
value = static_cast<T>(etl::to_unsigned(value) + step);
}
return value;
}
//*************************************************************************
// Provides information about a range.
// Ensures that Last - First + 1 is only calculated for when the range is not the full width of the type, to avoid overflow errors.
//*************************************************************************
template <typename T, T First, T Last, bool Full_Range = ((First == etl::integral_limits<T>::min) && (Last == etl::integral_limits<T>::max))>
struct range_traits;
//*************************************************************************
// Specialisation for when the range is the full width of the type.
template <typename T, T First, T Last>
struct range_traits<T, First, Last, true>
{
typedef typename traits<T>::unsigned_type unsigned_type;
static const bool is_full_range = true;
static const unsigned_type value = 0; // Unused, but required for template specialisation.
};
//*************************************************************************
// Specialisation for when the range is not the full width of the type.
template <typename T, T First, T Last>
struct range_traits<T, First, Last, false>
{
typedef typename traits<T>::unsigned_type unsigned_type;
static const bool is_full_range = false;
static const unsigned_type value = static_cast<unsigned_type>(static_cast<unsigned_type>(Last) - static_cast<unsigned_type>(First)) + 1U;
};
// Out-of-class definitions (required pre-C++17 for ODR-use of static const members).
template <typename T, T First, T Last>
ETL_CONSTANT bool range_traits<T, First, Last, true>::is_full_range;
template <typename T, T First, T Last>
ETL_CONSTANT typename range_traits<T, First, Last, true>::unsigned_type range_traits<T, First, Last, true>::value;
template <typename T, T First, T Last>
ETL_CONSTANT bool range_traits<T, First, Last, false>::is_full_range;
template <typename T, T First, T Last>
ETL_CONSTANT typename range_traits<T, First, Last, false>::unsigned_type range_traits<T, First, Last, false>::value;
} // namespace private_cyclic_value
struct cyclic_value_exception : etl::exception
{
cyclic_value_exception(string_type reason_, string_type file_, numeric_type line_)
: etl::exception(reason_, file_, line_)
{
}
};
struct cyclic_value_reversed_limits : cyclic_value_exception
{
cyclic_value_reversed_limits(string_type file_, numeric_type line_)
: cyclic_value_exception(ETL_ERROR_TEXT("cyclic_value_exception:reversed limits", ETL_CYCLIC_VALUE_FILE_ID"A"), file_, line_)
{
}
};
//***************************************************************************
/// Provides a value that cycles between two limits.
//***************************************************************************
@ -59,13 +247,20 @@ namespace etl
template <typename T, T First, T Last>
class cyclic_value<T, First, Last, false>
{
private:
typedef typename private_cyclic_value::traits<T>::unsigned_type unsigned_type;
public:
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "T must be an integral type");
ETL_STATIC_ASSERT(First <= Last, "First is not <= Last");
//*************************************************************************
/// Default constructor.
/// The initial value is set to the first value.
//*************************************************************************
ETL_CONSTEXPR cyclic_value()
ETL_CONSTEXPR cyclic_value() ETL_NOEXCEPT
: value(First)
{
}
@ -75,15 +270,15 @@ namespace etl
/// Set to an initial value.
/// Clamped to the range.
//*************************************************************************
ETL_CONSTEXPR14 explicit cyclic_value(T initial)
ETL_CONSTEXPR explicit cyclic_value(T initial) ETL_NOEXCEPT
: value(etl::clamp(initial, First, Last))
{
set(initial);
}
//*************************************************************************
/// Copy constructor.
//*************************************************************************
ETL_CONSTEXPR cyclic_value(const cyclic_value<T, First, Last>& other)
ETL_CONSTEXPR cyclic_value(const cyclic_value<T, First, Last>& other) ETL_NOEXCEPT
: value(other.value)
{
}
@ -91,19 +286,48 @@ namespace etl
//*************************************************************************
/// Assignment operator.
//*************************************************************************
ETL_CONSTEXPR14 cyclic_value& operator=(const cyclic_value<T, First, Last>& other)
ETL_CONSTEXPR14 cyclic_value& operator=(const cyclic_value<T, First, Last>& other) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
value = other.value;
return *this;
}
//*************************************************************************
/// Adds a number of steps and clamps to the range.
///\param n The number of steps.
///\return A reference to this value.
//*************************************************************************
template <typename TStep>
ETL_CONSTEXPR14 cyclic_value& operator+=(TStep n) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
ETL_STATIC_ASSERT(etl::is_integral<TStep>::value, "TStep must be an integral type");
advance(n);
return *this;
}
//*************************************************************************
/// Subtracts a number of steps and clamps to the range.
///\param n The number of steps.
///\return A reference to this value.
//*************************************************************************
template <typename TStep>
ETL_CONSTEXPR14 cyclic_value& operator-=(TStep n) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
ETL_STATIC_ASSERT(etl::is_integral<TStep>::value, "TStep must be an integral type");
do_advance(n, !etl::is_negative(n));
return *this;
}
//*************************************************************************
/// Sets the value.
/// Truncates to the First/Last range.
///\param value The value.
//*************************************************************************
ETL_CONSTEXPR14 void set(T value_)
ETL_CONSTEXPR14 void set(T value_) ETL_NOEXCEPT
{
value = etl::clamp(value_, First, Last);
}
@ -111,7 +335,7 @@ namespace etl
//*************************************************************************
/// Resets the value to the first in the range.
//*************************************************************************
ETL_CONSTEXPR14 void to_first()
ETL_CONSTEXPR14 void to_first() ETL_NOEXCEPT
{
value = First;
}
@ -119,7 +343,7 @@ namespace etl
//*************************************************************************
/// Resets the value to the last in the range.
//*************************************************************************
ETL_CONSTEXPR14 void to_last()
ETL_CONSTEXPR14 void to_last() ETL_NOEXCEPT
{
value = Last;
}
@ -128,30 +352,13 @@ namespace etl
/// Advances to value by a number of steps.
///\param n The number of steps to advance.
//*************************************************************************
ETL_CONSTEXPR14 void advance(int n)
template <typename TStep>
ETL_CONSTEXPR14 T advance(TStep n) ETL_NOEXCEPT
{
if (n > 0)
{
for (int i = 0; i < n; ++i)
{
operator++();
}
}
else
{
for (int i = 0; i < -n; ++i)
{
operator--();
}
}
}
ETL_STATIC_ASSERT(etl::is_integral<TStep>::value, "TStep must be an integral type");
do_advance(n, etl::is_negative(n));
//*************************************************************************
/// Conversion operator.
/// \return The value of the underlying type.
//*************************************************************************
ETL_CONSTEXPR14 operator T()
{
return value;
}
@ -159,7 +366,7 @@ namespace etl
/// Const conversion operator.
/// \return The value of the underlying type.
//*************************************************************************
ETL_CONSTEXPR operator const T() const
ETL_CONSTEXPR operator T() const ETL_NOEXCEPT
{
return value;
}
@ -167,16 +374,9 @@ namespace etl
//*************************************************************************
/// ++ operator.
//*************************************************************************
ETL_CONSTEXPR14 cyclic_value& operator++()
ETL_CONSTEXPR14 cyclic_value& operator++() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
if (value >= Last) ETL_UNLIKELY
{
value = First;
}
else
{
++value;
}
value = private_cyclic_value::increment(value, First, Last);
return *this;
}
@ -184,7 +384,7 @@ namespace etl
//*************************************************************************
/// ++ operator.
//*************************************************************************
ETL_CONSTEXPR14 cyclic_value operator++(int)
ETL_CONSTEXPR14 cyclic_value operator++(int) ETL_NOEXCEPT
{
cyclic_value temp(*this);
@ -196,16 +396,9 @@ namespace etl
//*************************************************************************
/// -- operator.
//*************************************************************************
ETL_CONSTEXPR14 cyclic_value& operator--()
ETL_CONSTEXPR14 cyclic_value& operator--() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
if (value <= First) ETL_UNLIKELY
{
value = Last;
}
else
{
--value;
}
value = private_cyclic_value::decrement(value, First, Last);
return *this;
}
@ -213,7 +406,7 @@ namespace etl
//*************************************************************************
/// -- operator.
//*************************************************************************
ETL_CONSTEXPR14 cyclic_value operator--(int)
ETL_CONSTEXPR14 cyclic_value operator--(int) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
cyclic_value temp(*this);
@ -225,7 +418,7 @@ namespace etl
//*************************************************************************
/// = operator.
//*************************************************************************
ETL_CONSTEXPR14 cyclic_value& operator=(T t)
ETL_CONSTEXPR14 cyclic_value& operator=(T t) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
set(t);
return *this;
@ -234,8 +427,8 @@ namespace etl
//*************************************************************************
/// = operator.
//*************************************************************************
template <const T FIRST2, const T LAST2>
ETL_CONSTEXPR14 cyclic_value& operator=(const cyclic_value<T, FIRST2, LAST2>& other)
template <T FIRST2, T LAST2>
ETL_CONSTEXPR14 cyclic_value& operator=(const cyclic_value<T, FIRST2, LAST2>& other) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
set(other.get());
return *this;
@ -244,7 +437,7 @@ namespace etl
//*************************************************************************
/// Gets the value.
//*************************************************************************
ETL_CONSTEXPR T get() const
ETL_CONSTEXPR T get() const ETL_NOEXCEPT
{
return value;
}
@ -252,7 +445,7 @@ namespace etl
//*************************************************************************
/// Gets the first value.
//*************************************************************************
static ETL_CONSTEXPR T first()
static ETL_CONSTEXPR T first() ETL_NOEXCEPT
{
return First;
}
@ -260,7 +453,7 @@ namespace etl
//*************************************************************************
/// Gets the last value.
//*************************************************************************
static ETL_CONSTEXPR T last()
static ETL_CONSTEXPR T last() ETL_NOEXCEPT
{
return Last;
}
@ -268,39 +461,39 @@ namespace etl
//*************************************************************************
/// Swaps the values.
//*************************************************************************
void swap(cyclic_value<T, First, Last>& other)
ETL_CONSTEXPR14 void swap(cyclic_value<T, First, Last>& other) ETL_NOEXCEPT
{
using ETL_OR_STD::swap; // Allow ADL
swap(value, other.value);
}
//*************************************************************************
/// Swaps the values.
//*************************************************************************
friend void swap(cyclic_value<T, First, Last>& lhs, cyclic_value<T, First, Last>& rhs)
{
lhs.swap(rhs);
}
//*************************************************************************
/// Operator ==.
//*************************************************************************
friend ETL_CONSTEXPR bool operator==(const cyclic_value<T, First, Last>& lhs, const cyclic_value<T, First, Last>& rhs)
{
return lhs.value == rhs.value;
}
//*************************************************************************
/// Operator !=.
//*************************************************************************
friend ETL_CONSTEXPR bool operator!=(const cyclic_value<T, First, Last>& lhs, const cyclic_value<T, First, Last>& rhs)
{
return !(lhs == rhs);
}
private:
//*************************************************************************
template <typename TStep>
ETL_CONSTEXPR14 void do_advance(TStep n, bool subtract) ETL_NOEXCEPT
{
ETL_STATIC_ASSERT(etl::is_integral<TStep>::value, "TStep must be an integral type");
typedef private_cyclic_value::range_traits<T, First, Last> range_info;
// Are the limits the full width of the type? If so, we can do a simpler calculation.
if ETL_IF_CONSTEXPR (range_info::is_full_range)
{
unsigned_type step = static_cast<unsigned_type>(etl::absolute_unsigned(n));
value = private_cyclic_value::advance(value, step, subtract);
}
else
{
unsigned_type range = range_info::value;
unsigned_type step = static_cast<unsigned_type>(etl::absolute_unsigned(n) % range);
value = private_cyclic_value::advance(value, First, Last, step, subtract);
}
}
T value; ///< The current value.
};
@ -315,14 +508,20 @@ namespace etl
template <typename T, T First, T Last>
class cyclic_value<T, First, Last, true>
{
private:
typedef typename private_cyclic_value::traits<T>::unsigned_type unsigned_type;
public:
ETL_STATIC_ASSERT(etl::is_integral<T>::value, "T must be an integral type");
//*************************************************************************
/// Constructor.
/// Sets 'first' and 'last' to the template parameter values.
/// Sets 'first' and 'last' to the template parameter values which will be zero.
/// The initial value is set to the first value.
//*************************************************************************
ETL_CONSTEXPR cyclic_value()
ETL_CONSTEXPR cyclic_value() ETL_NOEXCEPT
: value(First)
, first_value(First)
, last_value(Last)
@ -335,11 +534,12 @@ namespace etl
///\param first The first value in the range.
///\param last The last value in the range.
//*************************************************************************
ETL_CONSTEXPR cyclic_value(T first_, T last_)
ETL_CONSTEXPR14 cyclic_value(T first_, T last_)
: value(first_)
, first_value(first_)
, last_value(last_)
{
ETL_ASSERT(first_ <= last_, ETL_ERROR(cyclic_value_reversed_limits));
}
//*************************************************************************
@ -350,16 +550,17 @@ namespace etl
///\param last The last value in the range.
//*************************************************************************
ETL_CONSTEXPR14 cyclic_value(T first_, T last_, T initial)
: first_value(first_)
: value(etl::clamp(initial, first_, last_))
, first_value(first_)
, last_value(last_)
{
set(initial);
ETL_ASSERT(first_ <= last_, ETL_ERROR(cyclic_value_reversed_limits));
}
//*************************************************************************
/// Copy constructor.
//*************************************************************************
ETL_CONSTEXPR cyclic_value(const cyclic_value& other)
ETL_CONSTEXPR cyclic_value(const cyclic_value& other) ETL_NOEXCEPT
: value(other.value)
, first_value(other.first_value)
, last_value(other.last_value)
@ -374,6 +575,8 @@ namespace etl
//*************************************************************************
ETL_CONSTEXPR14 void set(T first_, T last_)
{
ETL_ASSERT(first_ <= last_, ETL_ERROR(cyclic_value_reversed_limits));
first_value = first_;
last_value = last_;
value = first_;
@ -383,7 +586,7 @@ namespace etl
/// Sets the value.
///\param value The value.
//*************************************************************************
ETL_CONSTEXPR14 void set(T value_)
ETL_CONSTEXPR14 void set(T value_) ETL_NOEXCEPT
{
value = etl::clamp(value_, first_value, last_value);
}
@ -391,7 +594,7 @@ namespace etl
//*************************************************************************
/// Resets the value to the first in the range.
//*************************************************************************
ETL_CONSTEXPR14 void to_first()
ETL_CONSTEXPR14 void to_first() ETL_NOEXCEPT
{
value = first_value;
}
@ -399,7 +602,7 @@ namespace etl
//*************************************************************************
/// Resets the value to the last in the range.
//*************************************************************************
ETL_CONSTEXPR14 void to_last()
ETL_CONSTEXPR14 void to_last() ETL_NOEXCEPT
{
value = last_value;
}
@ -408,30 +611,13 @@ namespace etl
/// Advances to value by a number of steps.
///\param n The number of steps to advance.
//*************************************************************************
ETL_CONSTEXPR14 void advance(int n)
template <typename TStep>
ETL_CONSTEXPR14 T advance(TStep n) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
if (n > 0)
{
for (int i = 0; i < n; ++i)
{
operator++();
}
}
else
{
for (int i = 0; i < -n; ++i)
{
operator--();
}
}
}
ETL_STATIC_ASSERT(etl::is_integral<TStep>::value, "TStep must be an integral type");
do_advance(n, etl::is_negative(n));
//*************************************************************************
/// Conversion operator.
/// \return The value of the underlying type.
//*************************************************************************
ETL_CONSTEXPR14 operator T()
{
return value;
}
@ -439,7 +625,7 @@ namespace etl
/// Const conversion operator.
/// \return The value of the underlying type.
//*************************************************************************
ETL_CONSTEXPR operator const T() const
ETL_CONSTEXPR operator T() const ETL_NOEXCEPT
{
return value;
}
@ -447,16 +633,9 @@ namespace etl
//*************************************************************************
/// ++ operator.
//*************************************************************************
ETL_CONSTEXPR14 cyclic_value& operator++()
ETL_CONSTEXPR14 cyclic_value& operator++() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
if (value >= last_value)
{
value = first_value;
}
else
{
++value;
}
value = private_cyclic_value::increment(value, first_value, last_value);
return *this;
}
@ -464,7 +643,7 @@ namespace etl
//*************************************************************************
/// ++ operator.
//*************************************************************************
ETL_CONSTEXPR14 cyclic_value operator++(int)
ETL_CONSTEXPR14 cyclic_value operator++(int) ETL_NOEXCEPT
{
cyclic_value temp(*this);
@ -476,16 +655,9 @@ namespace etl
//*************************************************************************
/// -- operator.
//*************************************************************************
ETL_CONSTEXPR14 cyclic_value& operator--()
ETL_CONSTEXPR14 cyclic_value& operator--() ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
if (value <= first_value)
{
value = last_value;
}
else
{
--value;
}
value = private_cyclic_value::decrement(value, first_value, last_value);
return *this;
}
@ -493,7 +665,7 @@ namespace etl
//*************************************************************************
/// -- operator.
//*************************************************************************
ETL_CONSTEXPR14 cyclic_value operator--(int)
ETL_CONSTEXPR14 cyclic_value operator--(int) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
cyclic_value temp(*this);
@ -505,7 +677,7 @@ namespace etl
//*************************************************************************
/// = operator.
//*************************************************************************
ETL_CONSTEXPR14 cyclic_value& operator=(T t)
ETL_CONSTEXPR14 cyclic_value& operator=(T t) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
set(t);
return *this;
@ -514,7 +686,7 @@ namespace etl
//*************************************************************************
/// = operator.
//*************************************************************************
ETL_CONSTEXPR14 cyclic_value& operator=(const cyclic_value& other)
ETL_CONSTEXPR14 cyclic_value& operator=(const cyclic_value& other) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
value = other.value;
first_value = other.first_value;
@ -522,10 +694,39 @@ namespace etl
return *this;
}
//*************************************************************************
/// Adds a number of steps and clamps to the range.
///\param n The number of steps.
///\return A reference to this value.
//*************************************************************************
template <typename TStep>
ETL_CONSTEXPR14 cyclic_value& operator+=(TStep n) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
ETL_STATIC_ASSERT(etl::is_integral<TStep>::value, "TStep must be an integral type");
advance(n);
return *this;
}
//*************************************************************************
/// Subtracts a number of steps and clamps to the range.
///\param n The number of steps.
///\return A reference to this value.
//*************************************************************************
template <typename TStep>
ETL_CONSTEXPR14 cyclic_value& operator-=(TStep n) ETL_LVALUE_REF_QUALIFIER ETL_NOEXCEPT
{
ETL_STATIC_ASSERT(etl::is_integral<TStep>::value, "TStep must be an integral type");
do_advance(n, !etl::is_negative(n));
return *this;
}
//*************************************************************************
/// Gets the value.
//*************************************************************************
ETL_CONSTEXPR T get() const
ETL_CONSTEXPR T get() const ETL_NOEXCEPT
{
return value;
}
@ -533,7 +734,7 @@ namespace etl
//*************************************************************************
/// Gets the first value.
//*************************************************************************
ETL_CONSTEXPR T first() const
ETL_CONSTEXPR T first() const ETL_NOEXCEPT
{
return first_value;
}
@ -541,7 +742,7 @@ namespace etl
//*************************************************************************
/// Gets the last value.
//*************************************************************************
ETL_CONSTEXPR T last() const
ETL_CONSTEXPR T last() const ETL_NOEXCEPT
{
return last_value;
}
@ -549,7 +750,7 @@ namespace etl
//*************************************************************************
/// Swaps the values.
//*************************************************************************
void swap(cyclic_value<T, First, Last>& other)
ETL_CONSTEXPR14 void swap(cyclic_value<T, First, Last>& other) ETL_NOEXCEPT
{
using ETL_OR_STD::swap; // Allow ADL
@ -558,36 +759,117 @@ namespace etl
swap(value, other.value);
}
//*************************************************************************
/// Swaps the values.
//*************************************************************************
friend void swap(cyclic_value<T, First, Last>& lhs, cyclic_value<T, First, Last>& rhs)
{
lhs.swap(rhs);
}
//*************************************************************************
/// Operator ==.
//*************************************************************************
friend ETL_CONSTEXPR bool operator==(const cyclic_value<T, First, Last>& lhs, const cyclic_value<T, First, Last>& rhs)
{
return (lhs.value == rhs.value) && (lhs.first_value == rhs.first_value) && (lhs.last_value == rhs.last_value);
}
//*************************************************************************
/// Operator !=.
//*************************************************************************
friend ETL_CONSTEXPR bool operator!=(const cyclic_value<T, First, Last>& lhs, const cyclic_value<T, First, Last>& rhs)
{
return !(lhs == rhs);
}
private:
//*************************************************************************
template <typename TStep>
ETL_CONSTEXPR14 void do_advance(TStep n, bool subtract) ETL_NOEXCEPT
{
ETL_STATIC_ASSERT(etl::is_integral<TStep>::value, "TStep must be an integral type");
const bool Is_Full_Range = (first_value == etl::integral_limits<T>::min) && (last_value == etl::integral_limits<T>::max);
// Are the limits the full width of the type? If so, we can do a simpler calculation.
if (Is_Full_Range)
{
unsigned_type step = static_cast<unsigned_type>(etl::absolute_unsigned(n));
value = private_cyclic_value::advance(value, step, subtract);
}
else
{
unsigned_type range = static_cast<unsigned_type>(etl::to_unsigned(last_value) - etl::to_unsigned(first_value)) + 1U;
unsigned_type step = static_cast<unsigned_type>(etl::absolute_unsigned(n) % range);
value = private_cyclic_value::advance(value, first_value, last_value, step, subtract);
}
}
T value; ///< The current value.
T first_value; ///< The first value in the range.
T last_value; ///< The last value in the range.
};
//*************************************************************************
/// Swaps the values.
//*************************************************************************
template <typename T, T First, T Last>
ETL_CONSTEXPR14 void swap(etl::cyclic_value<T, First, Last>& lhs, etl::cyclic_value<T, First, Last>& rhs) ETL_NOEXCEPT
{
lhs.swap(rhs);
}
} // namespace etl
//*************************************************************************
/// Operator ==
///\param lhs The left-hand operand.
///\param rhs The right-hand operand.
///\return `true` if lhs == rhs.
//*************************************************************************
template <typename T, T First, T Last>
ETL_CONSTEXPR bool operator==(const etl::cyclic_value<T, First, Last>& lhs, const etl::cyclic_value<T, First, Last>& rhs) ETL_NOEXCEPT
{
return (lhs.get() == rhs.get());
}
//*************************************************************************
/// Operator !=
///\param lhs The left-hand operand.
///\param rhs The right-hand operand.
///\return `true` if lhs != rhs.
//*************************************************************************
template <typename T, T First, T Last>
ETL_CONSTEXPR bool operator!=(const etl::cyclic_value<T, First, Last>& lhs, const etl::cyclic_value<T, First, Last>& rhs) ETL_NOEXCEPT
{
return !(lhs == rhs);
}
//*************************************************************************
/// Operator <
///\param lhs The left-hand operand.
///\param rhs The right-hand operand.
///\return `true` if lhs is less than rhs.
//*************************************************************************
template <typename T, T First, T Last>
ETL_CONSTEXPR bool operator<(const etl::cyclic_value<T, First, Last>& lhs, const etl::cyclic_value<T, First, Last>& rhs) ETL_NOEXCEPT
{
return lhs.get() < rhs.get();
}
//*************************************************************************
/// Operator <=
///\param lhs The left-hand operand.
///\param rhs The right-hand operand.
///\return `true` if lhs is less than or equal to rhs.
//*************************************************************************
template <typename T, T First, T Last>
ETL_CONSTEXPR bool operator<=(const etl::cyclic_value<T, First, Last>& lhs, const etl::cyclic_value<T, First, Last>& rhs) ETL_NOEXCEPT
{
return !(rhs < lhs);
}
//*************************************************************************
/// Operator >
///\param lhs The left-hand operand.
///\param rhs The right-hand operand.
///\return `true` if lhs is greater than rhs.
//*************************************************************************
template <typename T, T First, T Last>
ETL_CONSTEXPR bool operator>(const etl::cyclic_value<T, First, Last>& lhs, const etl::cyclic_value<T, First, Last>& rhs) ETL_NOEXCEPT
{
return rhs < lhs;
}
//*************************************************************************
/// Operator >=
///\param lhs The left-hand operand.
///\param rhs The right-hand operand.
///\return `true` if lhs is greater than or equal to rhs.
//*************************************************************************
template <typename T, T First, T Last>
ETL_CONSTEXPR bool operator>=(const etl::cyclic_value<T, First, Last>& lhs, const etl::cyclic_value<T, First, Last>& rhs) ETL_NOEXCEPT
{
return !(lhs < rhs);
}
#endif

View File

@ -367,7 +367,6 @@ namespace etl
{ \
etl::error_handler::error((e)); \
throw((e)); \
return; \
} \
} while (false) // If the condition fails, calls the error handler then
// throws an exception.
@ -377,7 +376,6 @@ namespace etl
{ \
etl::error_handler::error((e)); \
throw((e)); \
return (v); \
} \
} while (false) // If the condition fails, calls the error handler then
// throws an exception.
@ -391,13 +389,11 @@ namespace etl
do { \
etl::error_handler::error((e)); \
throw((e)); \
return; \
} while (false) // Calls the error handler then throws an exception.
#define ETL_ASSERT_FAIL_AND_RETURN_VALUE(e, v) \
do { \
etl::error_handler::error((e)); \
throw((e)); \
return (v); \
} while (false) // Calls the error handler then throws an exception.
#else
#define ETL_ASSERT(b, e) \

View File

@ -112,4 +112,5 @@ SOFTWARE.
#define ETL_FORMAT_FILE_ID "79"
#define ETL_INPLACE_FUNCTION_FILE_ID "80"
#define ETL_INTRUSIVE_AVL_TREE_FILE_ID "81"
#define ETL_CYCLIC_VALUE_FILE_ID "82"
#endif

View File

@ -47,10 +47,6 @@ SOFTWARE.
#include "variant.h"
#include "visitor.h"
#if ETL_USING_FORMAT_FLOATING_POINT
#include <cmath>
#endif
#if ETL_USING_CPP11
namespace etl
@ -509,7 +505,8 @@ namespace etl
struct basic_format_string
{
inline ETL_CONSTEVAL basic_format_string(const char* fmt)
: _sv(fmt)
: _str(fmt)
, _length(etl::char_traits<char>::length(fmt))
{
#if ETL_USING_CPP20
// Compile-time validation: check_format runs at compile time via consteval.
@ -527,12 +524,22 @@ namespace etl
ETL_CONSTEXPR string_view get() const
{
return _sv;
return string_view(_str, _length);
}
private:
string_view _sv;
// The format string is deliberately stored as a pointer plus a length, and
// not as a string_view.
//
// A string_view holds a pair of pointers, so constructing one here would
// initialise a member with the pointer arithmetic 'fmt + length(fmt)'.
// Microsoft's compiler (19.44) miscompiles exactly that case in a consteval
// constructor in debug builds: the resulting end pointer, and therefore the
// size of the view, is wrong. Storing the length as an integer instead
// computes correctly, and the view is formed on demand in get().
const char* _str;
size_t _length;
};
template <class... Args>
@ -1740,65 +1747,6 @@ namespace etl
double, long double>
long_double_format_type;
#if ETL_NOT_USING_FORMAT_LONG_DOUBLE_MATH
//***********************************
// Math function wrappers to handle toolchains that don't provide
// long double math functions (log10l, floorl, powl, modfl, roundl).
// When ETL_FORMAT_NO_LONG_DOUBLE_MATH is defined, long double overloads
// cast through double. For float and double, the standard functions are
// called directly via the template versions.
//***********************************
inline long double format_log10(long double value)
{
return static_cast<long double>(::log10(static_cast<double>(value)));
}
inline long double format_floor(long double value)
{
return static_cast<long double>(::floor(static_cast<double>(value)));
}
inline long double format_pow(long double base, long double exp)
{
return static_cast<long double>(::pow(static_cast<double>(base), static_cast<double>(exp)));
}
inline long double format_round(long double value)
{
return static_cast<long double>(::round(static_cast<double>(value)));
}
inline long double format_modf(long double value, long double* iptr)
{
double d_iptr;
double result = ::modf(static_cast<double>(value), &d_iptr);
*iptr = static_cast<long double>(d_iptr);
return static_cast<long double>(result);
}
#endif
template <typename T>
T format_log10(T value)
{
return ::log10(value);
}
template <typename T>
T format_floor(T value)
{
return ::floor(value);
}
template <typename T>
T format_pow(T base, T exp)
{
return ::pow(base, exp);
}
template <typename T>
T format_round(T value)
{
return ::round(value);
}
template <typename T>
T format_modf(T value, T* iptr)
{
return ::modf(value, iptr);
}
template <typename OutputIt, typename T>
void format_floating_default(OutputIt& it, T value, const format_spec_t& spec)
{
@ -1819,7 +1767,7 @@ namespace etl
}
T integral;
T fractional = format_modf(value, &integral);
T fractional = etl::math::modf(value, &integral);
// Take absolute values to avoid casting negative values to unsigned
if (sign)
@ -1829,7 +1777,7 @@ namespace etl
}
unsigned long long int scale = int_pow<unsigned long long int>(10, fractional_decimals);
unsigned long long int fractional_int = static_cast<unsigned long long int>(format_round(fractional * scale));
unsigned long long int fractional_int = static_cast<unsigned long long int>(etl::math::round(fractional * scale));
unsigned long long int integral_int = static_cast<unsigned long long int>(integral);
if (fractional_int == scale)
@ -1856,20 +1804,20 @@ namespace etl
bool sign = signbit(value);
T integral;
T fractional = format_modf(value, &integral);
T fractional = etl::math::modf(value, &integral);
while (value >= 0x10 || value <= -0x10)
{
++exponent_int;
value /= 0x10;
fractional = format_modf(value, &integral);
fractional = etl::math::modf(value, &integral);
}
while ((value > 0.0000000000001 && value < 1) || (value < -0.0000000000001 && value > -1))
{
--exponent_int;
value *= 0x10;
fractional = format_modf(value, &integral);
fractional = etl::math::modf(value, &integral);
}
// Take absolute values to avoid casting negative values to unsigned
@ -1880,7 +1828,7 @@ namespace etl
}
unsigned long long int scale = int_pow<unsigned long long int>(0x10, fractional_decimals);
unsigned long long int fractional_int = static_cast<unsigned long long int>(format_round(fractional * scale));
unsigned long long int fractional_int = static_cast<unsigned long long int>(etl::math::round(fractional * scale));
unsigned long long int integral_int = static_cast<unsigned long long int>(integral);
if (fractional_int == scale)
@ -1924,8 +1872,8 @@ namespace etl
if (abs_value > static_cast<T>(0))
{
exponent_int = static_cast<long long int>(format_floor(format_log10(abs_value)));
value = abs_value / format_pow(static_cast<T>(10), static_cast<T>(exponent_int));
exponent_int = static_cast<long long int>(etl::math::floor(etl::math::log10(abs_value)));
value = abs_value / etl::math::pow(static_cast<T>(10), static_cast<T>(exponent_int));
// Correct for floating-point rounding in log10/pow
if (value >= static_cast<T>(10))
{
@ -1944,10 +1892,10 @@ namespace etl
}
T integral;
T fractional = format_modf(value, &integral);
T fractional = etl::math::modf(value, &integral);
unsigned long long int scale = int_pow<unsigned long long int>(10, fractional_decimals);
unsigned long long int fractional_int = static_cast<unsigned long long int>(format_round(fractional * scale));
unsigned long long int fractional_int = static_cast<unsigned long long int>(etl::math::round(fractional * scale));
unsigned long long int integral_int = static_cast<unsigned long long int>(integral);
if (fractional_int == scale)
@ -1985,7 +1933,7 @@ namespace etl
bool sign = signbit(value);
T integral;
T fractional = format_modf(value, &integral);
T fractional = etl::math::modf(value, &integral);
// Take absolute values to avoid casting negative values to unsigned
if (sign)
@ -1995,7 +1943,7 @@ namespace etl
}
unsigned long long int scale = int_pow<unsigned long long int>(10, fractional_decimals);
unsigned long long int fractional_int = static_cast<unsigned long long int>(format_round(fractional * scale));
unsigned long long int fractional_int = static_cast<unsigned long long int>(etl::math::round(fractional * scale));
unsigned long long int integral_int = static_cast<unsigned long long int>(integral);
if (fractional_int == scale)

View File

@ -131,6 +131,209 @@ namespace etl
return value1 == value2;
}
#include "private/diagnostic_pop.h"
//***************************************************************************
// These functions wrap the C math.h functions.
// The functions are overloaded for the different floating point types.
// They provide a consistent interface for float, double and long double.
// They are in the `math` namespace to avoid conflicts with the C library and ETL functions.
// These take the place of std::floor, std::ceil etc which may not be available `No STL` environments.
// Avoids unpredictable behaviour for global calls of ::floor, ::ceil etc when both <math.h> and <cmath> are included.
//***************************************************************************
namespace math
{
//***************************************************************************
// floor
//***************************************************************************
ETL_NODISCARD
inline float floor(float value) ETL_NOEXCEPT
{
return ::floorf(value);
}
//*********************************
ETL_NODISCARD
inline double floor(double value) ETL_NOEXCEPT
{
return ::floor(value);
}
#if ETL_USING_LONG_DOUBLE_MATH
//*********************************
ETL_NODISCARD
inline long double floor(long double value) ETL_NOEXCEPT
{
return ::floorl(value);
}
#else
//*********************************
ETL_NODISCARD
inline long double floor(long double value) ETL_NOEXCEPT
{
return static_cast<long double>(::floor(static_cast<double>(value)));
}
#endif
//***************************************************************************
// ceil
//***************************************************************************
ETL_NODISCARD
inline float ceil(float value) ETL_NOEXCEPT
{
return ::ceilf(value);
}
//*********************************
ETL_NODISCARD
inline double ceil(double value) ETL_NOEXCEPT
{
return ::ceil(value);
}
#if ETL_USING_LONG_DOUBLE_MATH
//*********************************
ETL_NODISCARD
inline long double ceil(long double value) ETL_NOEXCEPT
{
return ::ceill(value);
}
#else
//*********************************
ETL_NODISCARD
inline long double ceil(long double value) ETL_NOEXCEPT
{
return static_cast<long double>(::ceil(static_cast<double>(value)));
}
#endif
//***************************************************************************
// log10
//***************************************************************************
ETL_NODISCARD
inline float log10(float value) ETL_NOEXCEPT
{
return ::log10f(value);
}
//*********************************
ETL_NODISCARD
inline double log10(double value) ETL_NOEXCEPT
{
return ::log10(value);
}
#if ETL_USING_LONG_DOUBLE_MATH
//*********************************
ETL_NODISCARD
inline long double log10(long double value) ETL_NOEXCEPT
{
return ::log10l(value);
}
#else
//*********************************
ETL_NODISCARD
inline long double log10(long double value) ETL_NOEXCEPT
{
return static_cast<long double>(::log10(static_cast<double>(value)));
}
#endif
//***************************************************************************
// round
//***************************************************************************
ETL_NODISCARD
inline float round(float value) ETL_NOEXCEPT
{
return ::roundf(value);
}
//*********************************
ETL_NODISCARD
inline double round(double value) ETL_NOEXCEPT
{
return ::round(value);
}
#if ETL_USING_LONG_DOUBLE_MATH
//*********************************
ETL_NODISCARD
inline long double round(long double value) ETL_NOEXCEPT
{
return ::roundl(value);
}
#else
//*********************************
ETL_NODISCARD
inline long double round(long double value) ETL_NOEXCEPT
{
return static_cast<long double>(::round(static_cast<double>(value)));
}
#endif
//***************************************************************************
// power
//***************************************************************************
ETL_NODISCARD
inline float pow(float base, float exponent) ETL_NOEXCEPT
{
return ::powf(base, exponent);
}
//*********************************
ETL_NODISCARD
inline double pow(double base, double exponent) ETL_NOEXCEPT
{
return ::pow(base, exponent);
}
#if ETL_USING_LONG_DOUBLE_MATH
//*********************************
ETL_NODISCARD
inline long double pow(long double base, long double exponent) ETL_NOEXCEPT
{
return ::powl(base, exponent);
}
#else
//*********************************
ETL_NODISCARD
inline long double pow(long double base, long double exponent) ETL_NOEXCEPT
{
return static_cast<long double>(::pow(static_cast<double>(base), static_cast<double>(exponent)));
}
#endif
//***************************************************************************
// modf
//***************************************************************************
inline float modf(float value, float* intpart) ETL_NOEXCEPT
{
return ::modff(value, intpart);
}
//*********************************
inline double modf(double value, double* intpart) ETL_NOEXCEPT
{
return ::modf(value, intpart);
}
#if ETL_USING_LONG_DOUBLE_MATH
//*********************************
inline long double modf(long double value, long double* intpart) ETL_NOEXCEPT
{
return ::modfl(value, intpart);
}
#else
//*********************************
inline long double modf(long double value, long double* intpart) ETL_NOEXCEPT
{
double d_iptr;
double result = ::modf(static_cast<double>(value), &d_iptr);
*intpart = static_cast<long double>(d_iptr);
return static_cast<long double>(result);
}
#endif
} // namespace math
} // namespace etl
#endif

View File

@ -158,6 +158,7 @@ namespace etl
: head(etl::timer::id::NO_TIMER)
, tail(etl::timer::id::NO_TIMER)
, ptimers(ptimers_)
, duplicate_insert(false)
{
}
@ -167,6 +168,15 @@ namespace etl
return head == etl::timer::id::NO_TIMER;
}
//*******************************
/// Returns true if an attempt was ever made to insert a timer that was
/// already in the list.
//*******************************
bool duplicate_insert_detected() const
{
return duplicate_insert;
}
//*******************************
// Inserts the timer at the correct delta position
//*******************************
@ -174,6 +184,16 @@ namespace etl
{
etl::message_timer_data& timer = ptimers[id_];
// A timer is in this list exactly when it is the head or has a previous
// link, as remove() clears both links. Inserting one that is already
// here would link it to itself and create a circular reference, so
// record the attempt and abandon the insert to keep the list intact.
if ((head == id_) || (timer.previous != etl::timer::id::NO_TIMER))
{
duplicate_insert = true;
return;
}
if (head == etl::timer::id::NO_TIMER)
{
// No entries yet.
@ -316,6 +336,10 @@ namespace etl
etl::timer::id::type tail;
etl::message_timer_data* const ptimers;
// Set if an attempt was ever made to insert a timer that was already
// in the list.
bool duplicate_insert;
};
} // namespace private_message_timer
@ -579,6 +603,16 @@ namespace etl
return false;
}
//*******************************************
/// Returns true if an attempt was ever made to insert a timer into the
/// active list when it was already there. Such an insert is rejected, as
/// it would create a circular reference in the list.
//*******************************************
bool duplicate_insert_detected() const
{
return active_list.duplicate_insert_detected();
}
//*******************************************
/// Check if there is an active timer.
//*******************************************

View File

@ -183,11 +183,9 @@ namespace etl
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
if (timer.p_router != ETL_NULLPTR)
{
timer.p_router->receive(timer.destination_router_id, *(timer.p_message));
}
// The timer is reinserted before the message is sent, so that
// a receiver that restarts the timer replaces this entry instead
// of the timer being inserted into the active list twice.
if (timer.repeating)
{
timer.delta = timer.period;
@ -195,6 +193,11 @@ namespace etl
insert_callback.call_if(timer.id);
}
if (timer.p_router != ETL_NULLPTR)
{
timer.p_router->receive(timer.destination_router_id, *(timer.p_message));
}
has_active = !active_list.empty();
}
@ -308,6 +311,16 @@ namespace etl
return false;
}
//*******************************************
/// Returns true if an attempt was ever made to insert a timer into the
/// active list when it was already there. Such an insert is rejected, as
/// it would create a circular reference in the list.
//*******************************************
bool duplicate_insert_detected() const
{
return active_list.duplicate_insert_detected();
}
//*******************************************
/// Check if there is an active timer.
//*******************************************
@ -467,6 +480,7 @@ namespace etl
: head(etl::timer::id::NO_TIMER)
, tail(etl::timer::id::NO_TIMER)
, ptimers(ptimers_)
, duplicate_insert(false)
{
}
@ -476,6 +490,15 @@ namespace etl
return head == etl::timer::id::NO_TIMER;
}
//*******************************
/// Returns true if an attempt was ever made to insert a timer that was
/// already in the list.
//*******************************
bool duplicate_insert_detected() const
{
return duplicate_insert;
}
//*******************************
// Inserts the timer at the correct delta position
//*******************************
@ -483,6 +506,16 @@ namespace etl
{
timer_data& timer = ptimers[id_];
// A timer is in this list exactly when it is the head or has a previous
// link, as remove() clears both links. Inserting one that is already
// here would link it to itself and create a circular reference, so
// record the attempt and abandon the insert to keep the list intact.
if ((head == id_) || (timer.previous != etl::timer::id::NO_TIMER))
{
duplicate_insert = true;
return;
}
if (head == etl::timer::id::NO_TIMER)
{
// No entries yet.
@ -625,6 +658,10 @@ namespace etl
etl::timer::id::type tail;
timer_data* const ptimers;
// Set if an attempt was ever made to insert a timer that was already
// in the list.
bool duplicate_insert;
};
// The array of timer data structures.

View File

@ -189,11 +189,9 @@ namespace etl
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
if (timer.p_router != ETL_NULLPTR)
{
timer.p_router->receive(timer.destination_router_id, *(timer.p_message));
}
// The timer is reinserted before the message is sent, so that
// a receiver that restarts the timer replaces this entry instead
// of the timer being inserted into the active list twice.
if (timer.repeating)
{
// Reinsert the timer.
@ -202,6 +200,11 @@ namespace etl
insert_callback.call_if(timer.id);
}
if (timer.p_router != ETL_NULLPTR)
{
timer.p_router->receive(timer.destination_router_id, *(timer.p_message));
}
has_active = !active_list.empty();
}
@ -316,6 +319,16 @@ namespace etl
return false;
}
//*******************************************
/// Returns true if an attempt was ever made to insert a timer into the
/// active list when it was already there. Such an insert is rejected, as
/// it would create a circular reference in the list.
//*******************************************
bool duplicate_insert_detected() const
{
return active_list.duplicate_insert_detected();
}
//*******************************************
/// Check if there is an active timer.
//*******************************************
@ -473,6 +486,7 @@ namespace etl
: head(etl::timer::id::NO_TIMER)
, tail(etl::timer::id::NO_TIMER)
, ptimers(ptimers_)
, duplicate_insert(false)
{
}
@ -482,6 +496,15 @@ namespace etl
return head == etl::timer::id::NO_TIMER;
}
//*******************************
/// Returns true if an attempt was ever made to insert a timer that was
/// already in the list.
//*******************************
bool duplicate_insert_detected() const
{
return duplicate_insert;
}
//*******************************
// Inserts the timer at the correct delta position
//*******************************
@ -489,6 +512,16 @@ namespace etl
{
timer_data& timer = ptimers[id_];
// A timer is in this list exactly when it is the head or has a previous
// link, as remove() clears both links. Inserting one that is already
// here would link it to itself and create a circular reference, so
// record the attempt and abandon the insert to keep the list intact.
if ((head == id_) || (timer.previous != etl::timer::id::NO_TIMER))
{
duplicate_insert = true;
return;
}
if (head == etl::timer::id::NO_TIMER)
{
// No entries yet.
@ -631,6 +664,10 @@ namespace etl
etl::timer::id::type tail;
timer_data* const ptimers;
// Set if an attempt was ever made to insert a timer that was already
// in the list.
bool duplicate_insert;
};
// The array of timer data structures.

View File

@ -186,11 +186,9 @@ namespace etl
active_list.remove(timer.id, true);
remove_callback.call_if(timer.id);
if (timer.p_router != ETL_NULLPTR)
{
timer.p_router->receive(timer.destination_router_id, *(timer.p_message));
}
// The timer is reinserted before the message is sent, so that
// a receiver that restarts the timer replaces this entry instead
// of the timer being inserted into the active list twice.
if (timer.repeating)
{
timer.delta = timer.period;
@ -198,6 +196,11 @@ namespace etl
insert_callback.call_if(timer.id);
}
if (timer.p_router != ETL_NULLPTR)
{
timer.p_router->receive(timer.destination_router_id, *(timer.p_message));
}
has_active = !active_list.empty();
}
@ -323,6 +326,16 @@ namespace etl
unlock = unlock_;
}
//*******************************************
/// Returns true if an attempt was ever made to insert a timer into the
/// active list when it was already there. Such an insert is rejected, as
/// it would create a circular reference in the list.
//*******************************************
bool duplicate_insert_detected() const
{
return active_list.duplicate_insert_detected();
}
//*******************************************
/// Check if there is an active timer.
//*******************************************
@ -481,6 +494,7 @@ namespace etl
: head(etl::timer::id::NO_TIMER)
, tail(etl::timer::id::NO_TIMER)
, ptimers(ptimers_)
, duplicate_insert(false)
{
}
@ -490,6 +504,15 @@ namespace etl
return head == etl::timer::id::NO_TIMER;
}
//*******************************
/// Returns true if an attempt was ever made to insert a timer that was
/// already in the list.
//*******************************
bool duplicate_insert_detected() const
{
return duplicate_insert;
}
//*******************************
// Inserts the timer at the correct delta position
//*******************************
@ -497,6 +520,16 @@ namespace etl
{
timer_data& timer = ptimers[id_];
// A timer is in this list exactly when it is the head or has a previous
// link, as remove() clears both links. Inserting one that is already
// here would link it to itself and create a circular reference, so
// record the attempt and abandon the insert to keep the list intact.
if ((head == id_) || (timer.previous != etl::timer::id::NO_TIMER))
{
duplicate_insert = true;
return;
}
if (head == etl::timer::id::NO_TIMER)
{
// No entries yet.
@ -639,6 +672,10 @@ namespace etl
etl::timer::id::type tail;
timer_data* const ptimers;
// Set if an attempt was ever made to insert a timer that was already
// in the list.
bool duplicate_insert;
};
// The array of timer data structures.

View File

@ -175,16 +175,17 @@ SOFTWARE.
#endif
//*************************************
// Helper macro for ETL_FORMAT_NO_LONG_DOUBLE_MATH.
// Define ETL_FORMAT_NO_LONG_DOUBLE_MATH if the toolchain does not provide
// Helper macro for ETL_NO_LONG_DOUBLE_MATH.
// Define ETL_NO_LONG_DOUBLE_MATH if the toolchain does not provide
// long double math functions (log10l, floorl, powl, modfl, roundl).
// When defined, long double arguments are cast to double for math operations.
#if defined(ETL_FORMAT_NO_LONG_DOUBLE_MATH)
#define ETL_USING_FORMAT_LONG_DOUBLE_MATH 0
#define ETL_NOT_USING_FORMAT_LONG_DOUBLE_MATH 1
// ETL_FORMAT_NO_LONG_DOUBLE_MATH is deprecated, but still supported for backwards compatibility.
#if defined(ETL_NO_LONG_DOUBLE_MATH) || defined(ETL_FORMAT_NO_LONG_DOUBLE_MATH)
#define ETL_USING_LONG_DOUBLE_MATH 0
#define ETL_NOT_USING_LONG_DOUBLE_MATH 1
#else
#define ETL_USING_FORMAT_LONG_DOUBLE_MATH 1
#define ETL_NOT_USING_FORMAT_LONG_DOUBLE_MATH 0
#define ETL_USING_LONG_DOUBLE_MATH 1
#define ETL_NOT_USING_LONG_DOUBLE_MATH 0
#endif
//*************************************

View File

@ -215,7 +215,7 @@ namespace etl
[[nodiscard]]
inline constexpr auto operator<=>(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT
{
return (static_cast<unsigned>(d1) <=> static_cast<unsigned>(d2));
return etl::make_strong_ordering(d1.compare(d2));
}
#endif

View File

@ -492,7 +492,37 @@ namespace etl
common_t l = etl::chrono::duration_cast<common_t>(lhs);
common_t r = etl::chrono::duration_cast<common_t>(rhs);
#if ETL_USING_STL
return (l.count() <=> r.count());
#else
// The STL returns the ordering category of the representation type.
// Mirror that: a floating point representation is only partially ordered.
if constexpr (etl::is_floating_point<typename common_t::rep>::value)
{
if (l.count() < r.count())
{
return etl::partial_ordering::less;
}
else if (r.count() < l.count())
{
return etl::partial_ordering::greater;
}
else if ((l.count() <= r.count()) && (r.count() <= l.count()))
{
// Equivalent. Expressed without '==' so that -Wfloat-equal is not triggered.
return etl::partial_ordering::equivalent;
}
else
{
// At least one of the values is NaN.
return etl::partial_ordering::unordered;
}
}
else
{
return etl::make_strong_ordering((l.count() < r.count()) ? -1 : (r.count() < l.count()) ? 1 : 0);
}
#endif
}
#endif

View File

@ -228,7 +228,7 @@ namespace etl
[[nodiscard]]
inline constexpr auto operator<=>(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT
{
return (static_cast<unsigned>(d1) <=> static_cast<unsigned>(d2));
return etl::make_strong_ordering(d1.compare(d2));
}
#endif

View File

@ -302,7 +302,7 @@ namespace etl
[[nodiscard]]
inline constexpr auto operator<=>(const etl::chrono::month_day_last& mdl1, const etl::chrono::month_day_last& mdl2) ETL_NOEXCEPT
{
return (static_cast<unsigned>(mdl1.month()) <=> static_cast<unsigned>(mdl2.month()));
return mdl1.month() <=> mdl2.month();
}
#endif
} // namespace chrono

View File

@ -244,7 +244,7 @@ namespace etl
[[nodiscard]]
inline constexpr auto operator<=>(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT
{
return (static_cast<int>(y1) <=> static_cast<int>(y2));
return etl::make_strong_ordering(y1.compare(y2));
}
#endif

View File

@ -44,8 +44,6 @@ SOFTWARE.
#include "../negative.h"
#include "../type_traits.h"
#include <math.h>
#if ETL_USING_STL && ETL_USING_CPP11
#include <iterator> // For std::begin, std::end and std::size
#endif
@ -347,11 +345,11 @@ namespace etl
}
// Find the integral part of the floating point
T f_integral = ::floor(scaled);
T f_integral = etl::math::floor(scaled);
uworkspace_t integral = static_cast<uworkspace_t>(f_integral);
// Find the fractional part of the floating point.
uworkspace_t fractional = static_cast<uworkspace_t>(::round((scaled - f_integral) * multiplier));
uworkspace_t fractional = static_cast<uworkspace_t>(etl::math::round((scaled - f_integral) * multiplier));
// Check for a rounding carry to the integral.
if (fractional == multiplier)
@ -404,7 +402,7 @@ namespace etl
}
// Find the integral part of the floating point
T f_integral = ::floor(etl::absolute(value));
T f_integral = etl::math::floor(etl::absolute(value));
uworkspace_t integral = static_cast<uworkspace_t>(f_integral);
// Find the fractional part of the floating point.

View File

@ -644,8 +644,7 @@ namespace etl
/// Obtains a span that is a view over the first count elements of this
/// span.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> first(size_t count) const
ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> first(size_t count) const ETL_NOEXCEPT_IF(ETL_NOT_CHECKING_EXTRA)
{
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
return count <= size() ? etl::span<element_type, etl::dynamic_extent>(pbegin, pbegin + count) : throw(ETL_ERROR(span_out_of_range));
@ -672,8 +671,7 @@ namespace etl
//*************************************************************************
/// Obtains a span that is a view over the last count elements of this span.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> last(size_t count) const
ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> last(size_t count) const ETL_NOEXCEPT_IF(ETL_NOT_CHECKING_EXTRA)
{
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
return count <= size() ? etl::span<element_type, etl::dynamic_extent>((pbegin + Extent) - count, (pbegin + Extent))
@ -735,7 +733,7 @@ namespace etl
/// elements of this span.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> subspan(size_t offset, size_t count = etl::dynamic_extent) const
ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
ETL_NOEXCEPT_IF(ETL_NOT_CHECKING_EXTRA)
{
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
return (offset <= size()) && (count != etl::dynamic_extent ? count <= (size() - offset) : true)
@ -1003,7 +1001,7 @@ namespace etl
//*************************************************************************
/// Returns a reference to the first element.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR reference front() const ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
ETL_NODISCARD ETL_CONSTEXPR reference front() const ETL_NOEXCEPT_IF(ETL_NOT_CHECKING_EXTRA)
{
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
return size() > 0 ? *pbegin : throw(ETL_ERROR(span_out_of_range));
@ -1017,7 +1015,7 @@ namespace etl
//*************************************************************************
/// Returns a reference to the last element.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR reference back() const ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
ETL_NODISCARD ETL_CONSTEXPR reference back() const ETL_NOEXCEPT_IF(ETL_NOT_CHECKING_EXTRA)
{
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
return size() > 0 ? *(pend - 1) : throw(ETL_ERROR(span_out_of_range));
@ -1197,7 +1195,7 @@ namespace etl
/// span.
//*************************************************************************
template <size_t COUNT>
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, COUNT> first() const ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, COUNT> first() const ETL_NOEXCEPT_IF(ETL_NOT_CHECKING_EXTRA)
{
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
return COUNT <= size() ? etl::span<element_type, COUNT>(pbegin, pbegin + COUNT) : throw(ETL_ERROR(span_out_of_range));
@ -1212,8 +1210,7 @@ namespace etl
/// Obtains a span that is a view over the first count elements of this
/// span.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> first(size_t count) const
ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> first(size_t count) const ETL_NOEXCEPT_IF(ETL_NOT_CHECKING_EXTRA)
{
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
return count <= size() ? etl::span<element_type, etl::dynamic_extent>(pbegin, pbegin + count) : throw(ETL_ERROR(span_out_of_range));
@ -1228,7 +1225,7 @@ namespace etl
/// Obtains a span that is a view over the last COUNT elements of this span.
//*************************************************************************
template <size_t COUNT>
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, COUNT> last() const ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, COUNT> last() const ETL_NOEXCEPT_IF(ETL_NOT_CHECKING_EXTRA)
{
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
return COUNT <= size() ? etl::span<element_type, COUNT>(pend - COUNT, pend) : throw(ETL_ERROR(span_out_of_range));
@ -1242,8 +1239,7 @@ namespace etl
//*************************************************************************
/// Obtains a span that is a view over the last count elements of this span.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> last(size_t count) const
ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
ETL_NODISCARD ETL_CONSTEXPR etl::span<element_type, etl::dynamic_extent> last(size_t count) const ETL_NOEXCEPT_IF(ETL_NOT_CHECKING_EXTRA)
{
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
return count <= size() ? etl::span<element_type, etl::dynamic_extent>(pend - count, pend) : throw(ETL_ERROR(span_out_of_range));
@ -1261,7 +1257,7 @@ namespace etl
//*************************************************************************
template <size_t OFFSET, size_t COUNT = etl::dynamic_extent>
ETL_NODISCARD ETL_CONSTEXPR etl::span< element_type, COUNT != etl::dynamic_extent ? COUNT : etl::dynamic_extent> subspan() const
ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
ETL_NOEXCEPT_IF(ETL_NOT_CHECKING_EXTRA)
{
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_EXTRA
return (OFFSET <= size()) && (COUNT != etl::dynamic_extent ? COUNT <= (size() - OFFSET) : true)
@ -1305,7 +1301,7 @@ namespace etl
/// elements of this span.
//*************************************************************************
ETL_NODISCARD ETL_CONSTEXPR14 etl::span<element_type, etl::dynamic_extent> subspan(size_t offset, size_t count = etl::dynamic_extent) const
ETL_NOEXCEPT_IF(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_EXTRA)
ETL_NOEXCEPT_IF(ETL_NOT_CHECKING_EXTRA)
{
ETL_ASSERT_CHECK_EXTRA(offset <= size(), ETL_ERROR(span_out_of_range));
ETL_ASSERT_CHECK_EXTRA(count != etl::dynamic_extent ? count <= (size() - offset) : true, ETL_ERROR(span_out_of_range));

View File

@ -355,7 +355,7 @@ namespace etl
/// If asserts or exceptions are enabled, throws an etl::string_view_bounds
/// if the index is out of bounds.
//*************************************************************************
ETL_CONSTEXPR const_reference operator[](size_type i) const ETL_NOEXCEPT_EXPR(ETL_NOT_USING_EXCEPTIONS || ETL_NOT_CHECKING_INDEX_OPERATOR)
ETL_CONSTEXPR const_reference operator[](size_type i) const ETL_NOEXCEPT_EXPR(ETL_NOT_CHECKING_INDEX_OPERATOR)
{
#if ETL_USING_CPP11 && ETL_NOT_USING_CPP14 && ETL_USING_EXCEPTIONS && ETL_CHECKING_INDEX_OPERATOR
return i < size() ? mbegin[i] : throw(ETL_ERROR(string_view_bounds));

View File

@ -4310,13 +4310,53 @@ namespace etl
#endif
#if ETL_USING_CPP11
//*********************************************
// Builtin-free noexcept-constructibility/assignability detection. Used when
// the __is_nothrow_constructible/__is_nothrow_assignable builtins are
// unavailable. Mirrors the void_t-based is_constructible/is_assignable
// fallbacks above so that (e.g.) a class with implicit noexcept move
// operations is correctly reported nothrow-(move-)constructible/assignable,
// and a const-qualified type is correctly reported NOT nothrow-assignable
// (the old is_arithmetic||is_pointer fallback ignored const-qualification).
#if !ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE
namespace private_type_traits
{
template <typename, typename T, typename... TArgs>
struct is_nothrow_constructible_ : etl::false_type
{
};
template <typename T, typename... TArgs>
struct is_nothrow_constructible_<etl::void_t<decltype(T(etl::declval<TArgs>()...))>, T, TArgs...>
: etl::bool_constant<noexcept(T(etl::declval<TArgs>()...))>
{
};
} // namespace private_type_traits
#endif
#if !ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE
namespace private_type_traits
{
template <typename, typename T, typename U>
struct is_nothrow_assignable_ : etl::false_type
{
};
template <typename T, typename U>
struct is_nothrow_assignable_<etl::void_t<decltype(etl::declval<T>() = etl::declval<U>())>, T, U>
: etl::bool_constant<noexcept(etl::declval<T>() = etl::declval<U>())>
{
};
} // namespace private_type_traits
#endif
//*********************************************
// is_nothrow_constructible
template <typename T, typename... TArgs>
#if ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE
struct is_nothrow_constructible : public etl::bool_constant<__is_nothrow_constructible(T, TArgs...)>
#else
struct is_nothrow_constructible : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
struct is_nothrow_constructible : public private_type_traits::is_nothrow_constructible_<etl::void_t<>, T, TArgs...>
#endif
{
};
@ -4324,33 +4364,21 @@ namespace etl
//*********************************************
// is_nothrow_default_constructible
template <typename T>
#if ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE
struct is_nothrow_default_constructible : public etl::is_nothrow_constructible<T>
#else
struct is_nothrow_default_constructible : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
#endif
{
};
//*********************************************
// is_nothrow_copy_constructible
template <typename T>
#if ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE
struct is_nothrow_copy_constructible : public etl::is_nothrow_constructible<T, typename etl::add_lvalue_reference<const T>::type>
#else
struct is_nothrow_copy_constructible : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
#endif
{
};
//*********************************************
// is_nothrow_move_constructible
template <typename T>
#if ETL_USING_BUILTIN_IS_NOTHROW_CONSTRUCTIBLE
struct is_nothrow_move_constructible : public etl::is_nothrow_constructible<T, typename etl::add_rvalue_reference<T>::type>
#else
struct is_nothrow_move_constructible : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
#endif
{
};
@ -4360,7 +4388,7 @@ namespace etl
#if ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE
struct is_nothrow_assignable : public etl::bool_constant<__is_nothrow_assignable(T, U)>
#else
struct is_nothrow_assignable : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
struct is_nothrow_assignable : public private_type_traits::is_nothrow_assignable_<etl::void_t<>, T, U>
#endif
{
};
@ -4368,24 +4396,16 @@ namespace etl
//*********************************************
// is_nothrow_copy_assignable
template <typename T>
#if ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE
struct is_nothrow_copy_assignable
: public etl::is_nothrow_assignable<typename etl::add_lvalue_reference<T>::type, typename etl::add_lvalue_reference<const T>::type>
#else
struct is_nothrow_copy_assignable : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
#endif
{
};
//*********************************************
// is_nothrow_move_assignable
template <typename T>
#if ETL_USING_BUILTIN_IS_NOTHROW_ASSIGNABLE
struct is_nothrow_move_assignable
: public etl::is_nothrow_assignable<typename etl::add_lvalue_reference<T>::type, typename etl::add_rvalue_reference<T>::type>
#else
struct is_nothrow_move_assignable : public etl::bool_constant<etl::is_arithmetic<T>::value || etl::is_pointer<T>::value>
#endif
{
};
#endif
@ -5175,20 +5195,26 @@ namespace etl
#elif ETL_USING_CPP11
namespace private_type_traits
{
template <typename T>
struct is_swappable_helper;
namespace swap_detect
{
// Bring std::swap into scope, if it is available, so that the unqualified
// call below finds it in those configurations that do not define etl::swap.
// Otherwise etl::swap is found by ordinary lookup in the enclosing
// namespace. Either way, a swap found by argument dependent lookup takes
// part in overload resolution.
#if ETL_USING_STL || defined(ETL_IN_UNIT_TEST)
using std::swap;
#endif
// A dummy declaration that can never be selected, as it takes no
// arguments, but which makes the name visible to ordinary lookup so that
// the unqualified calls below are well formed.
// Ordinary lookup stops here, so only a swap found by argument dependent
// lookup takes part in overload resolution.
// The generic swap that the standard library (or etl) provides is not
// detected this way, because not every implementation constrains it
// (Microsoft's C++14 std::swap does not), which would make every type
// appear to be swappable. Its viability is determined by the
// is_default_swappable traits below instead.
void swap();
// Selected only if 'swap(declval<T&>(), declval<T&>())' is a valid expression.
template <typename T>
struct is_swappable_test
struct is_adl_swappable_test
{
private:
@ -5206,7 +5232,7 @@ namespace etl
// Selected only if both 'swap(declval<T>(), declval<U>())' and
// 'swap(declval<U>(), declval<T>())' are valid expressions.
template <typename T, typename U>
struct is_swappable_with_test
struct is_adl_swappable_with_test
{
private:
@ -5221,15 +5247,61 @@ namespace etl
static ETL_CONSTANT bool value = decltype(test<T, U>(0))::value;
};
// Determines whether an expression of type T can be bound to a non-const
// lvalue reference to its referenced type.
// This is not simply 'is_lvalue_reference', because some compilers offer
// an extension that binds a class rvalue to a non-const lvalue reference.
template <typename T>
void binds_to_lvalue_reference_test(T&);
template <typename T, typename = void>
struct binds_to_lvalue_reference : etl::false_type
{
};
template <typename T>
struct binds_to_lvalue_reference<
T, etl::void_t<decltype(binds_to_lvalue_reference_test<typename etl::remove_reference<T>::type>(etl::declval<T>()))>> : etl::true_type
{
};
} // namespace swap_detect
// Determines whether the generic swap(T&, T&) is viable for T.
template <typename T>
struct is_swappable_helper : etl::bool_constant<swap_detect::is_swappable_test<T>::value>
struct is_default_swappable : etl::bool_constant<etl::is_move_constructible<T>::value && etl::is_move_assignable<T>::value>
{
};
// The generic swap for arrays requires the element type to be swappable.
template <typename T, size_t Size>
struct is_default_swappable<T[Size]> : is_swappable_helper<T>
{
};
// An array of unknown bound cannot be swapped.
template <typename T>
struct is_default_swappable<T[]> : etl::false_type
{
};
// The generic swap only participates when both arguments are lvalues of
// the same type.
template <typename T, typename U>
struct is_default_swappable_with
: etl::bool_constant<swap_detect::binds_to_lvalue_reference<T>::value && etl::is_same<T, U>::value
&& is_default_swappable<typename etl::remove_reference<T>::type>::value>
{
};
template <typename T>
struct is_swappable_helper : etl::bool_constant<swap_detect::is_adl_swappable_test<T>::value || is_default_swappable<T>::value>
{
};
template <typename T, typename U>
struct is_swappable_with_helper : etl::bool_constant<swap_detect::is_swappable_with_test<T, U>::value>
struct is_swappable_with_helper
: etl::bool_constant<swap_detect::is_adl_swappable_with_test<T, U>::value || is_default_swappable_with<T, U>::value>
{
};
} // namespace private_type_traits
@ -5271,43 +5343,75 @@ namespace etl
#elif ETL_USING_CPP11
namespace private_type_traits
{
template <typename T>
struct is_nothrow_swappable_helper;
namespace swap_detect
{
// Only 'true' if the type is swappable and the swap expression is noexcept.
template <typename T, bool Is_Swappable = is_swappable_test<T>::value>
struct is_nothrow_swappable_test
// Only 'true' if the type has an ADL found swap and the swap expression is noexcept.
template <typename T, bool Is_Adl_Swappable = is_adl_swappable_test<T>::value>
struct is_nothrow_adl_swappable_test
{
static ETL_CONSTANT bool value = false;
};
template <typename T>
struct is_nothrow_swappable_test<T, true>
struct is_nothrow_adl_swappable_test<T, true>
{
static ETL_CONSTANT bool value = noexcept(swap(etl::declval<T&>(), etl::declval<T&>()));
};
// Only 'true' if the types are swappable with each other and both of the
// swap expressions are noexcept.
template <typename T, typename U, bool Is_Swappable_With = is_swappable_with_test<T, U>::value>
struct is_nothrow_swappable_with_test
// Only 'true' if the types have ADL found swaps for each other and both of
// the swap expressions are noexcept.
template <typename T, typename U, bool Is_Adl_Swappable_With = is_adl_swappable_with_test<T, U>::value>
struct is_nothrow_adl_swappable_with_test
{
static ETL_CONSTANT bool value = false;
};
template <typename T, typename U>
struct is_nothrow_swappable_with_test<T, U, true>
struct is_nothrow_adl_swappable_with_test<T, U, true>
{
static ETL_CONSTANT bool value = noexcept(swap(etl::declval<T>(), etl::declval<U>())) && noexcept(swap(etl::declval<U>(), etl::declval<T>()));
};
} // namespace swap_detect
// Determines whether the generic swap(T&, T&) is viable for T and cannot throw.
template <typename T>
struct is_nothrow_swappable_helper : etl::bool_constant<swap_detect::is_nothrow_swappable_test<T>::value>
struct is_nothrow_default_swappable
: etl::bool_constant<etl::is_nothrow_move_constructible<T>::value && etl::is_nothrow_move_assignable<T>::value>
{
};
template <typename T, size_t Size>
struct is_nothrow_default_swappable<T[Size]> : is_nothrow_swappable_helper<T>
{
};
template <typename T>
struct is_nothrow_default_swappable<T[]> : etl::false_type
{
};
template <typename T, typename U>
struct is_nothrow_swappable_with_helper : etl::bool_constant<swap_detect::is_nothrow_swappable_with_test<T, U>::value>
struct is_nothrow_default_swappable_with
: etl::bool_constant<swap_detect::binds_to_lvalue_reference<T>::value && etl::is_same<T, U>::value
&& is_nothrow_default_swappable<typename etl::remove_reference<T>::type>::value>
{
};
// An ADL found swap hides the generic one, so it decides the result.
template <typename T>
struct is_nothrow_swappable_helper
: etl::bool_constant<swap_detect::is_adl_swappable_test<T>::value ? swap_detect::is_nothrow_adl_swappable_test<T>::value
: is_nothrow_default_swappable<T>::value>
{
};
template <typename T, typename U>
struct is_nothrow_swappable_with_helper
: etl::bool_constant<swap_detect::is_adl_swappable_with_test<T, U>::value ? swap_detect::is_nothrow_adl_swappable_with_test<T, U>::value
: is_nothrow_default_swappable_with<T, U>::value>
{
};
} // namespace private_type_traits

File diff suppressed because it is too large Load Diff

View File

@ -393,7 +393,7 @@ namespace etl
typename etl::enable_if<!etl::is_integral<TIterator>::value
&& etl::is_convertible<typename etl::iterator_traits<TIterator>::value_type, T>::value,
typename etl::enable_if<!etl::is_integral<TIterator>::value, void>::type>::type
assign(TIterator first, TIterator last) ETL_NOEXCEPT_IF((etl::is_nothrow_copy_constructible<T>::value && ETL_NOT_USING_EXCEPTIONS))
assign(TIterator first, TIterator last)
{
#if ETL_USING_CPP11
ETL_STATIC_ASSERT((etl::is_same<typename etl::remove_cv<T>::type,
@ -2082,7 +2082,6 @@ namespace etl
/// Copy constructor.
//*************************************************************************
vector_ext(const vector_ext& other, void* buffer, size_t max_size)
ETL_NOEXCEPT_IF((etl::is_nothrow_copy_constructible<T>::value && ETL_NOT_USING_EXCEPTIONS))
: etl::ivector<T>(reinterpret_cast<T*>(buffer), max_size)
{
if (&other != this)
@ -2094,7 +2093,7 @@ namespace etl
//*************************************************************************
/// Assignment operator.
//*************************************************************************
vector_ext& operator=(const vector_ext& rhs) ETL_NOEXCEPT_IF((etl::is_nothrow_copy_constructible<T>::value && ETL_NOT_USING_EXCEPTIONS))
vector_ext& operator=(const vector_ext& rhs)
{
if (&rhs != this)
{
@ -2109,7 +2108,6 @@ namespace etl
/// Move constructor.
//*************************************************************************
vector_ext(vector_ext&& other, void* buffer, size_t max_size)
ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible<T>::value && ETL_NOT_USING_EXCEPTIONS))
: etl::ivector<T>(reinterpret_cast<T*>(buffer), max_size)
{
if (&other != this)
@ -2123,7 +2121,7 @@ namespace etl
//*************************************************************************
/// Move assignment operator.
//*************************************************************************
vector_ext& operator=(vector_ext&& rhs) ETL_NOEXCEPT_IF((etl::is_nothrow_move_constructible<T>::value && ETL_NOT_USING_EXCEPTIONS))
vector_ext& operator=(vector_ext&& rhs)
{
if (&rhs != this)
{

View File

@ -11,14 +11,14 @@ TitleColour=$'\033[38;2;107;210;255m'
HelpColour=$'\033[38;2;250;180;250m'
NoColour=$'\033[0m'
ParseGitBranch()
ParseGitBranch()
{
git rev-parse --abbrev-ref HEAD
}
SetConfigurationName()
{
configuration_name=$1
configuration_name=$1
}
PrintHeader()
@ -147,10 +147,9 @@ RunCheck()
local cc_name=$1
local msg=$2
local no_stl=$3
local builtins=$4
local user_defined=$5
local force_03=$6
local build_dir=$7
local user_defined=$4
local force_03=$5
local build_dir=$6
if [ "$compiler_enabled" != "$cc_name" ] && [ "$compiler_enabled" != "All compilers" ]; then
return
@ -171,7 +170,7 @@ RunCheck()
rm -rdf bgcc
rm -rdf bclang
cmake -E make_directory bgcc bclang
CC=$cc CXX=$cxx cmake -E chdir $build_dir cmake -DNO_STL=$no_stl -DETL_USE_TYPE_TRAITS_BUILTINS=$builtins -DETL_USER_DEFINED_TYPE_TRAITS=$user_defined -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=$force_03 -DETL_CXX_STANDARD=$cxx_standard ..
CC=$cc CXX=$cxx cmake -E chdir $build_dir cmake -DNO_STL=$no_stl -DETL_USER_DEFINED_TYPE_TRAITS=$user_defined -DETL_FORCE_TEST_CPP03_IMPLEMENTATION=$force_03 -DETL_CXX_STANDARD=$cxx_standard ..
cmake --build $build_dir
if [ $? -eq 0 ]; then
PassedCompilation
@ -193,25 +192,21 @@ RunStandard()
cxx_standard=$std
# GCC configurations
RunCheck gcc "STL" OFF OFF OFF OFF bgcc
RunCheck gcc "No STL" ON OFF OFF OFF bgcc
RunCheck gcc "STL - Built-in traits" OFF ON OFF OFF bgcc
RunCheck gcc "No STL - Built-in traits" ON ON OFF OFF bgcc
RunCheck gcc "STL" OFF OFF OFF bgcc
RunCheck gcc "No STL" ON OFF OFF bgcc
if [ "$has_force_03" = "1" ]; then
RunCheck gcc "STL - Force C++03" OFF OFF OFF ON bgcc
RunCheck gcc "No STL - Force C++03" ON OFF OFF ON bgcc
RunCheck gcc "STL - Force C++03" OFF OFF ON bgcc
RunCheck gcc "No STL - Force C++03" ON OFF ON bgcc
fi
# Clang configurations
RunCheck clang "STL" OFF OFF OFF OFF bclang
RunCheck clang "No STL" ON OFF OFF OFF bclang
RunCheck clang "STL - Built-in traits" OFF ON OFF OFF bgcc
RunCheck clang "No STL - Built-in traits" ON ON OFF OFF bgcc
RunCheck clang "STL" OFF OFF OFF bclang
RunCheck clang "No STL" ON OFF OFF bclang
if [ "$has_force_03" = "1" ]; then
RunCheck clang "STL - Force C++03" OFF OFF OFF ON bclang
RunCheck clang "No STL - Force C++03" ON OFF OFF ON bclang
RunCheck clang "STL - Force C++03" OFF OFF ON bclang
RunCheck clang "No STL - Force C++03" ON OFF ON bclang
fi
}

View File

@ -37,3 +37,13 @@ etl::clamped_value<double> clamped_double_run_time;
#if ETL_HAS_COMPILE_TIME_FLOATING_POINT_CLAMPED_VALUE
etl::clamped_value<float, -1.0f, 1.0f> clamped_float_compile_time;
#endif
#if ETL_USING_CPP11
const etl::clamped_value_range<int> referenced_clamped_range(0, 10);
etl::referenced_clamped_value<int> referenced_clamped_int(referenced_clamped_range);
#if ETL_HAS_FLOATING_POINT_CLAMPED_VALUE
const etl::clamped_value_range<float> referenced_clamped_float_range(-1.0f, 1.0f);
etl::referenced_clamped_value<float> referenced_clamped_float(referenced_clamped_float_range);
#endif
#endif

View File

@ -149,6 +149,35 @@ namespace
callback_type free_function_callback2 = callback_type::create<free_callback2>();
//***************************************************************************
// Fixture for a repeating timer that restarts itself from within its own
// callback (regression test for issue #967).
//***************************************************************************
struct RestartInCallback
{
etl::callback_timer_atomic<1, std::atomic_uint32_t>* p_controller = nullptr;
etl::timer::id::type id = etl::timer::id::NO_TIMER;
uint32_t new_period = 0U;
std::vector<uint64_t> call_ticks;
void callback()
{
call_ticks.push_back(ticks);
// Change the period (this stops/deactivates the timer) and restart it
// from inside the callback. Before the fix, tick() would then insert the
// timer a second time, creating a circular reference in the active list.
p_controller->set_period(id, new_period);
p_controller->start(id);
}
};
RestartInCallback restart_in_callback;
using timer_callback_type = etl::icallback_timer_atomic<std::atomic_uint32_t>::callback_type;
timer_callback_type restart_in_callback_member =
timer_callback_type::create<RestartInCallback, restart_in_callback, &RestartInCallback::callback>();
SUITE(test_callback_timer_atomic)
{
//*************************************************************************
@ -855,6 +884,54 @@ namespace
CHECK_EQUAL(3, timerInsertRemoveTest.removed);
}
//*************************************************************************
// Regression test for issue #967:
// Calling start() from within a repeating timer's callback (after the
// period has been changed, which stops the timer) must not insert the timer
// twice and create a circular reference in the active list.
//*************************************************************************
TEST(callback_timer_atomic_restart_in_callback_no_circular_reference)
{
etl::callback_timer_atomic<1, std::atomic_uint32_t> timer_controller;
restart_in_callback.p_controller = &timer_controller;
restart_in_callback.new_period = 20U;
restart_in_callback.call_ticks.clear();
etl::timer::id::type id = timer_controller.register_timer(restart_in_callback_member, 10, etl::timer::mode::Repeating);
restart_in_callback.id = id;
timer_controller.start(id);
timer_controller.enable(true);
ticks = 0;
const uint32_t step = 1U;
// Run long enough for several firings at the original (10) then new (20) period.
while (ticks < 100U)
{
ticks += step;
timer_controller.tick(step);
}
// Detect a duplicated entry in the active list directly, rather than
// relying on the resulting circular reference hanging the test.
CHECK_FALSE(timer_controller.duplicate_insert_detected());
// The timer must still be active (alive, not corrupted) and scheduled at
// the new period. A circular reference would corrupt the active list.
CHECK_TRUE(timer_controller.is_active(id));
// First firing at 10, then every 20 thereafter: 10, 30, 50, 70, 90.
std::vector<uint64_t> compare = {10, 30, 50, 70, 90};
CHECK_EQUAL(compare.size(), restart_in_callback.call_ticks.size());
CHECK_ARRAY_EQUAL(compare.data(), restart_in_callback.call_ticks.data(), compare.size());
timer_controller.clear();
}
//*************************************************************************
#if REALTIME_TEST

View File

@ -162,6 +162,33 @@ namespace
callback_type free_function_callback2 = callback_type::create<free_callback2>();
//***************************************************************************
// Fixture for a repeating timer that restarts itself from within its own
// callback (regression test for issue #967).
//***************************************************************************
struct RestartInCallback
{
etl::callback_timer_interrupt<1, ScopedGuard>* p_controller = nullptr;
etl::timer::id::type id = etl::timer::id::NO_TIMER;
uint32_t new_period = 0U;
std::vector<uint64_t> call_ticks;
void callback()
{
call_ticks.push_back(ticks);
// Change the period (this stops/deactivates the timer) and restart it
// from inside the callback. Before the fix, tick() would then insert the
// timer a second time, creating a circular reference in the active list.
p_controller->set_period(id, new_period);
p_controller->start(id);
}
};
RestartInCallback restart_in_callback;
callback_type restart_in_callback_member = callback_type::create<RestartInCallback, restart_in_callback, &RestartInCallback::callback>();
SUITE(test_callback_timer_interrupt)
{
//*************************************************************************
@ -1001,5 +1028,55 @@ namespace
// Check the
CHECK_EQUAL(0U, ScopedGuard::guard_count);
}
//*************************************************************************
// Regression test for issue #967:
// Calling start() from within a repeating timer's callback (after the
// period has been changed, which stops the timer) must not insert the timer
// twice and create a circular reference in the active list.
//*************************************************************************
TEST(callback_timer_interrupt_restart_in_callback_no_circular_reference)
{
etl::callback_timer_interrupt<1, ScopedGuard> timer_controller;
restart_in_callback.p_controller = &timer_controller;
restart_in_callback.new_period = 20U;
restart_in_callback.call_ticks.clear();
etl::timer::id::type id = timer_controller.register_timer(restart_in_callback_member, 10, etl::timer::mode::Repeating);
restart_in_callback.id = id;
timer_controller.start(id);
timer_controller.enable(true);
ticks = 0;
const uint32_t step = 1U;
// Run long enough for several firings at the original (10) then new (20) period.
while (ticks < 100U)
{
ticks += step;
timer_controller.tick(step);
}
// Detect a duplicated entry in the active list directly, rather than
// relying on the resulting circular reference hanging the test.
CHECK_FALSE(timer_controller.duplicate_insert_detected());
// The timer must still be active (alive, not corrupted) and scheduled at
// the new period. A circular reference would corrupt the active list.
CHECK_TRUE(timer_controller.is_active(id));
// First firing at 10, then every 20 thereafter: 10, 30, 50, 70, 90.
std::vector<uint64_t> compare = {10, 30, 50, 70, 90};
CHECK_EQUAL(compare.size(), restart_in_callback.call_ticks.size());
CHECK_ARRAY_EQUAL(compare.data(), restart_in_callback.call_ticks.data(), compare.size());
timer_controller.clear();
CHECK_EQUAL(0U, ScopedGuard::guard_count);
}
}
} // namespace

View File

@ -184,6 +184,33 @@ namespace
callback_type free_function_callback2 = callback_type::create<free_callback2>();
//***************************************************************************
// Fixture for a repeating timer that restarts itself from within its own
// callback (regression test for issue #967).
//***************************************************************************
struct RestartInCallback
{
etl::callback_timer_locked<1>* p_controller = nullptr;
etl::timer::id::type id = etl::timer::id::NO_TIMER;
uint32_t new_period = 0U;
std::vector<uint64_t> call_ticks;
void callback()
{
call_ticks.push_back(ticks);
// Change the period (this stops/deactivates the timer) and restart it
// from inside the callback. Before the fix, tick() would then insert the
// timer a second time, creating a circular reference in the active list.
p_controller->set_period(id, new_period);
p_controller->start(id);
}
};
RestartInCallback restart_in_callback;
callback_type restart_in_callback_member = callback_type::create<RestartInCallback, restart_in_callback, &RestartInCallback::callback>();
SUITE(test_callback_timer_locked)
{
//*************************************************************************
@ -1004,6 +1031,59 @@ namespace
CHECK_FALSE(timer_controller.has_active_timer());
}
//*************************************************************************
// Regression test for issue #967:
// Calling start() from within a repeating timer's callback (after the
// period has been changed, which stops the timer) must not insert the timer
// twice and create a circular reference in the active list.
//*************************************************************************
TEST(callback_timer_locked_restart_in_callback_no_circular_reference)
{
locks.clear();
try_lock_type try_lock = try_lock_type::create<Locks, locks, &Locks::try_lock>();
lock_type lock = lock_type::create<Locks, locks, &Locks::lock>();
unlock_type unlock = unlock_type::create<Locks, locks, &Locks::unlock>();
etl::callback_timer_locked<1> timer_controller(try_lock, lock, unlock);
restart_in_callback.p_controller = &timer_controller;
restart_in_callback.new_period = 20U;
restart_in_callback.call_ticks.clear();
etl::timer::id::type id = timer_controller.register_timer(restart_in_callback_member, 10, etl::timer::mode::Repeating);
restart_in_callback.id = id;
timer_controller.start(id);
timer_controller.enable(true);
ticks = 0;
const uint32_t step = 1U;
// Run long enough for several firings at the original (10) then new (20) period.
while (ticks < 100U)
{
ticks += step;
timer_controller.tick(step);
}
// Detect a duplicated entry in the active list directly, rather than
// relying on the resulting circular reference hanging the test.
CHECK_FALSE(timer_controller.duplicate_insert_detected());
// The timer must still be active (alive, not corrupted) and scheduled at
// the new period. A circular reference would corrupt the active list.
CHECK_TRUE(timer_controller.is_active(id));
// First firing at 10, then every 20 thereafter: 10, 30, 50, 70, 90.
std::vector<uint64_t> compare = {10, 30, 50, 70, 90};
CHECK_EQUAL(compare.size(), restart_in_callback.call_ticks.size());
CHECK_ARRAY_EQUAL(compare.data(), restart_in_callback.call_ticks.data(), compare.size());
timer_controller.clear();
}
//*************************************************************************
#if REALTIME_TEST

View File

@ -1052,9 +1052,34 @@ namespace
Chrono::seconds s1(2); // 2 seconds
Chrono::milliseconds ms1(1500); // 1500 milliseconds
CHECK_TRUE(s1 <=> s1 == std::strong_ordering::equal);
CHECK_TRUE(ms1 <=> s1 == std::strong_ordering::less);
CHECK_TRUE(s1 <=> ms1 == std::strong_ordering::greater);
CHECK_TRUE(s1 <=> s1 == etl::strong_ordering::equal);
CHECK_TRUE(ms1 <=> s1 == etl::strong_ordering::less);
CHECK_TRUE(s1 <=> ms1 == etl::strong_ordering::greater);
static_assert(etl::is_same<decltype(s1 <=> ms1), etl::strong_ordering>::value, "Must return etl::strong_ordering");
}
//*************************************************************************
TEST(test_duration_spaceship_operator_floating_point_representation)
{
typedef Chrono::duration<double> fp_seconds;
fp_seconds fs1(1.5);
fp_seconds fs2(2.5);
// A floating point representation is only partially ordered.
static_assert(etl::is_same<decltype(fs1 <=> fs2), etl::partial_ordering>::value, "Must return etl::partial_ordering");
CHECK_TRUE((fs1 <=> fs1) == etl::partial_ordering::equivalent);
CHECK_TRUE((fs1 <=> fs2) == etl::partial_ordering::less);
CHECK_TRUE((fs2 <=> fs1) == etl::partial_ordering::greater);
fp_seconds nan_seconds(etl::numeric_limits<double>::quiet_NaN());
CHECK_TRUE((nan_seconds <=> fs1) == etl::partial_ordering::unordered);
CHECK_FALSE((nan_seconds <=> fs1) < 0);
CHECK_FALSE((nan_seconds <=> fs1) == 0);
CHECK_FALSE((nan_seconds <=> fs1) > 0);
}
#endif

View File

@ -97,9 +97,9 @@ namespace
Chrono::month_day md2{Chrono::February, Chrono::day{10}};
Chrono::month_day md3{Chrono::January, Chrono::day{15}};
CHECK_TRUE((md1 <=> md3) == std::strong_ordering::equal); // Same month and day
CHECK_TRUE((md1 <=> md2) == std::strong_ordering::less); // Different month and day
CHECK_TRUE((md2 <=> md1) == std::strong_ordering::greater); // Same month and day
CHECK_TRUE((md1 <=> md3) == etl::strong_ordering::equal); // Same month and day
CHECK_TRUE((md1 <=> md2) == etl::strong_ordering::less); // Different month and day
CHECK_TRUE((md2 <=> md1) == etl::strong_ordering::greater); // Same month and day
}
#endif

View File

@ -100,6 +100,20 @@ namespace
CHECK_TRUE(month_day_last1 != month_day_last3);
}
#if ETL_USING_CPP20
//*************************************************************************
TEST(test_month_day_last_spaceship_operator)
{
Chrono::month_day_last month_day_last1(Chrono::January);
Chrono::month_day_last month_day_last2(Chrono::February);
Chrono::month_day_last month_day_last3(Chrono::January);
CHECK_TRUE((month_day_last1 <=> month_day_last3) == etl::strong_ordering::equal);
CHECK_TRUE((month_day_last1 <=> month_day_last2) == etl::strong_ordering::less);
CHECK_TRUE((month_day_last2 <=> month_day_last1) == etl::strong_ordering::greater);
}
#endif
#if ETL_USING_ETL_CHRONO
//*************************************************************************
TEST(test_month_day_last_hashes_are_unique)

View File

@ -377,6 +377,8 @@ namespace
CHECK_TRUE((tp10d <=> tp10h) == 0);
CHECK_TRUE((tp10h <=> tp20d) < 0);
CHECK_TRUE((tp20d <=> tp10h) > 0);
static_assert(etl::is_same<decltype(tp10h <=> tp20d), etl::strong_ordering>::value, "Must return etl::strong_ordering");
#endif
}

View File

@ -97,11 +97,11 @@ namespace
Chrono::year_month ym2{Chrono::year(2001), Chrono::January};
Chrono::year_month ym3{Chrono::year(2000), Chrono::February};
CHECK_TRUE((ym1 <=> ym1) == std::strong_ordering::equal);
CHECK_TRUE((ym1 <=> ym2) == std::strong_ordering::less);
CHECK_TRUE((ym2 <=> ym1) == std::strong_ordering::greater);
CHECK_TRUE((ym1 <=> ym3) == std::strong_ordering::less);
CHECK_TRUE((ym3 <=> ym1) == std::strong_ordering::greater);
CHECK_TRUE((ym1 <=> ym1) == etl::strong_ordering::equal);
CHECK_TRUE((ym1 <=> ym2) == etl::strong_ordering::less);
CHECK_TRUE((ym2 <=> ym1) == etl::strong_ordering::greater);
CHECK_TRUE((ym1 <=> ym3) == etl::strong_ordering::less);
CHECK_TRUE((ym3 <=> ym1) == etl::strong_ordering::greater);
}
#endif

View File

@ -107,13 +107,13 @@ namespace
Chrono::year_month_day ym3{Chrono::year(2000), Chrono::February, Chrono::day(1)};
Chrono::year_month_day ym4{Chrono::year(2000), Chrono::January, Chrono::day(2)};
CHECK_TRUE((ym1 <=> ym1) == std::strong_ordering::equal);
CHECK_TRUE((ym1 <=> ym2) == std::strong_ordering::less);
CHECK_TRUE((ym2 <=> ym1) == std::strong_ordering::greater);
CHECK_TRUE((ym1 <=> ym3) == std::strong_ordering::less);
CHECK_TRUE((ym3 <=> ym1) == std::strong_ordering::greater);
CHECK_TRUE((ym1 <=> ym4) == std::strong_ordering::less);
CHECK_TRUE((ym4 <=> ym1) == std::strong_ordering::greater);
CHECK_TRUE((ym1 <=> ym1) == etl::strong_ordering::equal);
CHECK_TRUE((ym1 <=> ym2) == etl::strong_ordering::less);
CHECK_TRUE((ym2 <=> ym1) == etl::strong_ordering::greater);
CHECK_TRUE((ym1 <=> ym3) == etl::strong_ordering::less);
CHECK_TRUE((ym3 <=> ym1) == etl::strong_ordering::greater);
CHECK_TRUE((ym1 <=> ym4) == etl::strong_ordering::less);
CHECK_TRUE((ym4 <=> ym1) == etl::strong_ordering::greater);
}
#endif

View File

@ -160,6 +160,23 @@ namespace
CHECK_TRUE(year_month_day_last1 != year_month_day_last3);
}
#if ETL_USING_CPP20
//*************************************************************************
TEST(test_year_month_day_last_spaceship_operator)
{
Chrono::year_month_day_last year_month_day_last1(Chrono::year(2000), Chrono::month_day_last(Chrono::January));
Chrono::year_month_day_last year_month_day_last2(Chrono::year(2001), Chrono::month_day_last(Chrono::January));
Chrono::year_month_day_last year_month_day_last3(Chrono::year(2000), Chrono::month_day_last(Chrono::February));
Chrono::year_month_day_last year_month_day_last4(Chrono::year(2000), Chrono::month_day_last(Chrono::January));
CHECK_TRUE((year_month_day_last1 <=> year_month_day_last4) == etl::strong_ordering::equal);
CHECK_TRUE((year_month_day_last1 <=> year_month_day_last2) == etl::strong_ordering::less);
CHECK_TRUE((year_month_day_last2 <=> year_month_day_last1) == etl::strong_ordering::greater);
CHECK_TRUE((year_month_day_last1 <=> year_month_day_last3) == etl::strong_ordering::less);
CHECK_TRUE((year_month_day_last3 <=> year_month_day_last1) == etl::strong_ordering::greater);
}
#endif
#if ETL_USING_ETL_CHRONO
//*************************************************************************
TEST(test_year_month_day_last_hashes_are_unique)

View File

@ -531,5 +531,157 @@ namespace
}
#endif
#endif
#if ETL_USING_CPP11
//*************************************************************************
TEST(test_referenced_clamped_value_uses_shared_range)
{
const etl::clamped_value_range<int> range(2, 7);
etl::referenced_clamped_value<int> value1(range, 1);
etl::referenced_clamped_value<int> value2(range, 8);
CHECK_EQUAL(2, value1.get());
CHECK_EQUAL(7, value2.get());
CHECK_EQUAL(2, value1.min());
CHECK_EQUAL(7, value1.max());
CHECK_EQUAL(&range, &value1.range());
CHECK_EQUAL(&range, &value2.range());
}
//*************************************************************************
TEST(test_referenced_clamped_value_arithmetic_saturates)
{
const etl::clamped_value_range<int> range(-2, 3);
etl::referenced_clamped_value<int> value(range, 0);
value += 2;
CHECK_EQUAL(2, value.get());
++value;
++value;
CHECK_EQUAL(3, value.get());
value -= 4;
CHECK_EQUAL(-1, value.get());
--value;
--value;
CHECK_EQUAL(-2, value.get());
}
//*************************************************************************
TEST(test_referenced_clamped_value_modifiers_and_postfix_operators)
{
const etl::clamped_value_range<int> range(2, 7);
etl::referenced_clamped_value<int> value(range);
CHECK_EQUAL(2, value.get());
value.set(4);
CHECK_EQUAL(4, value.get());
etl::referenced_clamped_value<int> previous = value++;
CHECK_EQUAL(4, previous.get());
CHECK_EQUAL(5, value.get());
previous = value--;
CHECK_EQUAL(5, previous.get());
CHECK_EQUAL(4, value.get());
value.to_max();
CHECK_EQUAL(7, value.get());
value.to_min();
CHECK_EQUAL(2, value.get());
value = 100;
CHECK_EQUAL(7, value.get());
}
//*************************************************************************
TEST(test_referenced_clamped_value_default_range_and_comparisons)
{
const etl::clamped_value_range<int> default_range;
const etl::clamped_value_range<int> range(0, 10);
etl::referenced_clamped_value<int> value1(range, 3);
etl::referenced_clamped_value<int> value2(range, 4);
const int converted = value1;
CHECK_EQUAL(etl::numeric_limits<int>::lowest(), default_range.min());
CHECK_EQUAL(etl::numeric_limits<int>::max(), default_range.max());
CHECK_EQUAL(3, converted);
CHECK(value1 == value1);
CHECK(value1 != value2);
CHECK(value1 < value2);
CHECK(value1 <= value2);
CHECK(value2 > value1);
CHECK(value2 >= value1);
CHECK(value1 < 4);
CHECK(3 == value1);
}
//*************************************************************************
TEST(test_referenced_clamped_value_copy_assignment_and_swap_ranges)
{
const etl::clamped_value_range<int> range1(0, 10);
const etl::clamped_value_range<int> range2(20, 30);
etl::referenced_clamped_value<int> value1(range1, 4);
etl::referenced_clamped_value<int> value2(range2, 24);
etl::referenced_clamped_value<int> copy(value1);
CHECK_EQUAL(&range1, &copy.range());
CHECK_EQUAL(4, copy.get());
copy = value2;
CHECK_EQUAL(&range2, &copy.range());
CHECK_EQUAL(24, copy.get());
swap(value1, value2);
CHECK_EQUAL(&range2, &value1.range());
CHECK_EQUAL(24, value1.get());
CHECK_EQUAL(&range1, &value2.range());
CHECK_EQUAL(4, value2.get());
}
//*************************************************************************
TEST(test_referenced_clamped_value_rejects_invalid_range)
{
CHECK_THROW((etl::clamped_value_range<int>(7, 2)), etl::exception);
}
//*************************************************************************
TEST(test_referenced_clamped_value_rejects_temporary_range)
{
typedef etl::clamped_value_range<int> range_type;
typedef etl::referenced_clamped_value<int> value_type;
CHECK_FALSE((etl::is_constructible<value_type, range_type&&>::value));
CHECK_FALSE((etl::is_constructible<value_type, range_type&&, int>::value));
}
#if ETL_HAS_FLOATING_POINT_CLAMPED_VALUE
//*************************************************************************
TEST(test_referenced_floating_clamped_value)
{
const etl::clamped_value_range<float> range(-1.5F, 2.5F);
etl::referenced_clamped_value<float> value(range, 0.5F);
value += 1.25F;
CHECK_CLOSE(1.75F, value.get(), 0.0001F);
value.advance(10.0F);
CHECK_CLOSE(2.5F, value.get(), 0.0001F);
}
//*************************************************************************
TEST(test_referenced_floating_clamped_value_rejects_nan)
{
const float nan = etl::numeric_limits<float>::quiet_NaN();
CHECK_THROW((etl::clamped_value_range<float>(nan, 1.0F)), etl::exception);
const etl::clamped_value_range<float> range(-1.0F, 1.0F);
CHECK_THROW((etl::referenced_clamped_value<float>(range, nan)), etl::exception);
etl::referenced_clamped_value<float> value(range, 0.0F);
CHECK_THROW(value = nan, etl::exception);
CHECK_THROW(value.advance(nan), etl::exception);
}
#endif
#endif
}
} // namespace

View File

@ -91,6 +91,20 @@ namespace
}
};
struct ComparatorOnlyObject
{
int a;
int b;
};
struct LessBySecond
{
bool constexpr operator()(const ComparatorOnlyObject& lhs, const ComparatorOnlyObject& rhs) const
{
return lhs.b < rhs.b;
}
};
typedef etl::compare<Object, LessTest> CompareTest;
SUITE(test_compare)
@ -191,5 +205,139 @@ namespace
CHECK_EQUAL(CompareInt::Greater, cmp_test_greater);
CHECK_EQUAL(CompareInt::Equal, cmp_test_equal);
}
#if ETL_USING_CPP20
//*************************************************************************
TEST(test_strong_ordering)
{
constexpr etl::strong_ordering ordering_less(etl::strong_ordering::less);
constexpr etl::strong_ordering ordering_equal(etl::strong_ordering::equal);
constexpr etl::strong_ordering ordering_greater(etl::strong_ordering::greater);
CHECK(ordering_less < 0);
CHECK(ordering_less <= 0);
CHECK(!(ordering_less == 0));
CHECK(!(ordering_less > 0));
CHECK(ordering_equal == 0);
CHECK(ordering_equal <= 0);
CHECK(ordering_equal >= 0);
CHECK(ordering_greater > 0);
CHECK(ordering_greater >= 0);
CHECK(!(ordering_greater == 0));
// Reversed operands.
CHECK(0 > ordering_less);
CHECK(0 < ordering_greater);
static_assert(etl::strong_ordering::equivalent == etl::strong_ordering::equal, "Equivalent must alias equal");
static_assert(etl::is_same<etl::weak_ordering, decltype(etl::weak_ordering(etl::strong_ordering::less))>::value,
"Must convert to weak_ordering");
CHECK(etl::weak_ordering(etl::strong_ordering::less) < 0);
CHECK(etl::partial_ordering(etl::strong_ordering::greater) > 0);
}
//*************************************************************************
TEST(test_make_strong_ordering)
{
constexpr etl::strong_ordering ordering_less = etl::make_strong_ordering(-1);
constexpr etl::strong_ordering ordering_equal = etl::make_strong_ordering(0);
constexpr etl::strong_ordering ordering_greater = etl::make_strong_ordering(1);
CHECK(ordering_less < 0);
CHECK(ordering_equal == 0);
CHECK(ordering_greater > 0);
static_assert(etl::is_same<decltype(etl::make_strong_ordering(0)), etl::strong_ordering>::value, "Must return etl::strong_ordering");
}
//*************************************************************************
TEST(test_weak_ordering)
{
constexpr etl::weak_ordering ordering_less(etl::weak_ordering::less);
constexpr etl::weak_ordering ordering_equivalent(etl::weak_ordering::equivalent);
constexpr etl::weak_ordering ordering_greater(etl::weak_ordering::greater);
CHECK(ordering_less < 0);
CHECK(ordering_equivalent == 0);
CHECK(ordering_greater > 0);
CHECK(0 > ordering_less);
CHECK(0 < ordering_greater);
static_assert(etl::weak_ordering::equivalent == 0, "Equivalent must be zero");
CHECK(etl::partial_ordering(etl::weak_ordering::less) < 0);
}
//*************************************************************************
TEST(test_make_weak_ordering)
{
constexpr etl::weak_ordering ordering_less = etl::make_weak_ordering(-1);
constexpr etl::weak_ordering ordering_equivalent = etl::make_weak_ordering(0);
constexpr etl::weak_ordering ordering_greater = etl::make_weak_ordering(1);
CHECK(ordering_less < 0);
CHECK(ordering_equivalent == 0);
CHECK(ordering_greater > 0);
static_assert(etl::is_same<decltype(etl::make_weak_ordering(0)), etl::weak_ordering>::value, "Must return etl::weak_ordering");
}
//*************************************************************************
TEST(test_partial_ordering)
{
constexpr etl::partial_ordering ordering_less(etl::partial_ordering::less);
constexpr etl::partial_ordering ordering_equivalent(etl::partial_ordering::equivalent);
constexpr etl::partial_ordering ordering_greater(etl::partial_ordering::greater);
constexpr etl::partial_ordering ordering_unordered(etl::partial_ordering::unordered);
CHECK(ordering_less < 0);
CHECK(ordering_equivalent == 0);
CHECK(ordering_greater > 0);
// An unordered result compares false against zero in every direction.
CHECK(!(ordering_unordered < 0));
CHECK(!(ordering_unordered <= 0));
CHECK(!(ordering_unordered == 0));
CHECK(!(ordering_unordered >= 0));
CHECK(!(ordering_unordered > 0));
CHECK(ordering_unordered != 0);
static_assert(etl::partial_ordering::equivalent == 0, "Equivalent must be zero");
}
//*************************************************************************
TEST(test_make_partial_ordering)
{
constexpr etl::partial_ordering ordering_less = etl::make_partial_ordering(-1);
constexpr etl::partial_ordering ordering_equivalent = etl::make_partial_ordering(0);
constexpr etl::partial_ordering ordering_greater = etl::make_partial_ordering(1);
CHECK(ordering_less < 0);
CHECK(ordering_equivalent == 0);
CHECK(ordering_greater > 0);
static_assert(etl::is_same<decltype(etl::make_partial_ordering(0)), etl::partial_ordering>::value, "Must return etl::partial_ordering");
}
//*************************************************************************
TEST(test_three_way_compare_custom_less)
{
constexpr ComparatorOnlyObject lhs = {5, 1};
constexpr ComparatorOnlyObject rhs = {1, 2};
constexpr ComparatorOnlyObject eq = {9, 1};
constexpr int cmp_less = etl::three_way_compare<ComparatorOnlyObject, LessBySecond>(lhs, rhs);
constexpr int cmp_greater = etl::three_way_compare<ComparatorOnlyObject, LessBySecond>(rhs, lhs);
constexpr int cmp_equal = etl::three_way_compare<ComparatorOnlyObject, LessBySecond>(lhs, eq);
CHECK_EQUAL(-1, cmp_less);
CHECK_EQUAL(1, cmp_greater);
CHECK_EQUAL(0, cmp_equal);
CHECK(etl::make_strong_ordering(cmp_less) < 0);
CHECK(etl::make_strong_ordering(cmp_greater) > 0);
CHECK(etl::make_strong_ordering(cmp_equal) == 0);
}
#endif
}
} // namespace

View File

@ -56,6 +56,15 @@ namespace
CHECK_EQUAL(7, value.last());
}
//*************************************************************************
TEST(test_reversed_run_time_initialisation)
{
etl::cyclic_value<int> value(1, 2);
CHECK_THROW(etl::cyclic_value<int>(7, 2), etl::cyclic_value_reversed_limits);
CHECK_THROW(value.set(7, 2), etl::cyclic_value_reversed_limits);
}
//*************************************************************************
TEST(test_copy_constructor_compile_time)
{
@ -336,7 +345,7 @@ namespace
{
etl::cyclic_value<int, 2, 7> value;
value.advance(14);
value.advance(20);
CHECK_EQUAL(4, value);
}
@ -347,7 +356,7 @@ namespace
etl::cyclic_value<int> value;
value.set(2, 7);
value.advance(14);
value.advance(20);
CHECK_EQUAL(4, value);
}
@ -358,7 +367,7 @@ namespace
etl::cyclic_value<int, 2, 7> value;
value.to_last();
value.advance(-14);
value.advance(-20);
CHECK_EQUAL(5, value);
}
@ -370,7 +379,7 @@ namespace
value.set(2, 7);
value.to_last();
value.advance(-14);
value.advance(-20);
CHECK_EQUAL(5, value);
}
@ -408,6 +417,168 @@ namespace
CHECK_EQUAL(1U, value);
}
//*************************************************************************
TEST(test_add_positive_n_compile_time)
{
etl::cyclic_value<int, 2, 7> value;
value += 2;
CHECK_EQUAL(4, value);
}
//*************************************************************************
TEST(test_add_positive_n_run_time)
{
etl::cyclic_value<int> value;
value.set(2, 7);
value += 2;
CHECK_EQUAL(4, value);
}
//*************************************************************************
TEST(test_add_positive_n_large_compile_time)
{
etl::cyclic_value<int, 2, 7> value;
value += 20;
CHECK_EQUAL(4, value);
}
//*************************************************************************
TEST(test_add_positive_n_large_run_time)
{
etl::cyclic_value<int> value;
value.set(2, 7);
value += 20;
CHECK_EQUAL(4, value);
}
//*************************************************************************
TEST(test_add_negative_n_large_compile_time)
{
etl::cyclic_value<int, 2, 7> value;
value.to_last();
value += -20;
CHECK_EQUAL(5, value);
}
//*************************************************************************
TEST(test_add_negative_n_large_run_time)
{
etl::cyclic_value<int> value;
value.set(2, 7);
value.to_last();
value += -20;
CHECK_EQUAL(5, value);
}
//*************************************************************************
TEST(test_add_negative_n_unsigned_compile_time)
{
etl::cyclic_value<size_t, 0U, 2U> value;
value += -2;
CHECK_EQUAL(1U, value);
}
//*************************************************************************
TEST(test_add_negative_n_run_time)
{
etl::cyclic_value<int> value;
value.set(2, 7);
value.to_last();
value += -20;
CHECK_EQUAL(5, value);
}
//*************************************************************************
TEST(test_decrease_positive_compile_time)
{
etl::cyclic_value<int, 2, 7> value;
value -= 2;
CHECK_EQUAL(6, value);
}
//*************************************************************************
TEST(test_subtract_positive_n_run_time)
{
etl::cyclic_value<int> value;
value.set(2, 7);
value -= 2;
CHECK_EQUAL(6, value);
}
//*************************************************************************
TEST(test_subtract_positive_n_large_compile_time)
{
etl::cyclic_value<int, 2, 7> value;
value -= 20;
CHECK_EQUAL(6, value);
}
//*************************************************************************
TEST(test_subtract_positive_n_large_run_time)
{
etl::cyclic_value<int> value;
value.set(2, 7);
value -= 20;
CHECK_EQUAL(6, value);
}
//*************************************************************************
TEST(test_subtract_negative_n_large_compile_time)
{
etl::cyclic_value<int, 2, 7> value;
value.to_last();
value -= -20;
CHECK_EQUAL(3, value);
}
//*************************************************************************
TEST(test_subtract_negative_n_large_run_time)
{
etl::cyclic_value<int> value;
value.set(2, 7);
value.to_last();
value -= -20;
CHECK_EQUAL(3, value);
}
//*************************************************************************
TEST(test_subtract_negative_n_unsigned_compile_time)
{
etl::cyclic_value<size_t, 0U, 2U> value;
value -= -2;
CHECK_EQUAL(2U, value);
}
//*************************************************************************
TEST(test_assignment_compile_time)
{
@ -493,7 +664,50 @@ namespace
CHECK(data2 == compare1);
}
#if ETL_USING_CPP14
//*************************************************************************
TEST(test_comparison_operators)
{
etl::cyclic_value<int, 0, 9> cv1(3);
etl::cyclic_value<int, 0, 9> cv2(3);
etl::cyclic_value<int, 0, 9> cv3(5);
etl::cyclic_value<int, -1, 8> cv4(3);
CHECK_TRUE(cv1 == cv2);
CHECK_FALSE(cv1 == cv3);
CHECK_FALSE(cv1 != cv2);
CHECK_TRUE(cv1 != cv3);
CHECK_FALSE(cv1 < cv2);
CHECK_FALSE(cv2 < cv1);
CHECK_TRUE(cv1 < cv3);
CHECK_FALSE(cv3 < cv1);
CHECK_FALSE(cv1 < cv4);
CHECK_FALSE(cv4 < cv1);
CHECK_FALSE(cv1 > cv2);
CHECK_FALSE(cv2 > cv1);
CHECK_FALSE(cv1 > cv3);
CHECK_TRUE(cv3 > cv1);
CHECK_FALSE(cv1 > cv4);
CHECK_FALSE(cv4 > cv1);
CHECK_TRUE(cv1 <= cv2);
CHECK_TRUE(cv2 <= cv1);
CHECK_TRUE(cv1 <= cv3);
CHECK_FALSE(cv3 <= cv1);
CHECK_TRUE(cv1 <= cv4);
CHECK_TRUE(cv4 <= cv1);
CHECK_TRUE(cv1 >= cv2);
CHECK_TRUE(cv2 >= cv1);
CHECK_FALSE(cv1 >= cv3);
CHECK_TRUE(cv3 >= cv1);
CHECK_TRUE(cv1 >= cv4);
CHECK_TRUE(cv4 >= cv1);
}
#if ETL_USING_CPP11
//*************************************************************************
TEST(test_cyclic_value_constexpr_ctor)
{
@ -502,6 +716,7 @@ namespace
CHECK(true);
}
#if ETL_USING_CPP14
//*************************************************************************
TEST(test_cyclic_value_constexpr_ctor_with_range)
{
@ -510,6 +725,7 @@ namespace
static_assert(cv.last() == 9, "constexpr range ctor last");
CHECK(true);
}
#endif
//*************************************************************************
TEST(test_cyclic_value_constexpr_copy_ctor)
@ -519,6 +735,299 @@ namespace
static_assert(cv2.get() == 0, "constexpr copy ctor");
CHECK(true);
}
//*************************************************************************
TEST(test_constexpr_comparison_operators)
{
constexpr etl::cyclic_value<int, 0, 9> cv1(3);
constexpr etl::cyclic_value<int, 0, 9> cv2(3);
constexpr etl::cyclic_value<int, 0, 9> cv3(5);
constexpr etl::cyclic_value<int, -1, 8> cv4(3);
static_assert((cv1 == cv2), "(cv1 == cv2) failed");
static_assert(!(cv1 == cv3), "!(cv1 == cv3) failed");
static_assert(!(cv1 != cv2), "!(cv1 != cv2) failed");
static_assert((cv1 != cv3), "(cv1 != cv3) failed");
static_assert(!(cv1 < cv2), "!(cv1 < cv2) failed");
static_assert(!(cv2 < cv1), "!(cv2 < cv1) failed");
static_assert((cv1 < cv3), "(cv1 < cv3) failed");
static_assert(!(cv3 < cv1), "!(cv3 < cv1) failed");
static_assert(!(cv1 < cv4), "!(cv1 < cv4) failed");
static_assert(!(cv4 < cv1), "!(cv4 < cv1) failed");
static_assert(!(cv1 > cv2), "!(cv1 > cv2) failed");
static_assert(!(cv2 > cv1), "!(cv2 > cv1) failed");
static_assert(!(cv1 > cv3), "!(cv1 > cv3) failed");
static_assert((cv3 > cv1), "(cv3 > cv1) failed");
static_assert(!(cv1 > cv4), "!(cv1 > cv4) failed");
static_assert(!(cv4 > cv1), "!(cv4 > cv1) failed");
static_assert((cv1 <= cv2), "(cv1 <= cv2) failed");
static_assert((cv2 <= cv1), "(cv2 <= cv1) failed");
static_assert((cv1 <= cv3), "(cv1 <= cv3) failed");
static_assert(!(cv3 <= cv1), "!(cv3 <= cv1) failed");
static_assert((cv1 <= cv4), "(cv1 <= cv4) failed");
static_assert((cv4 <= cv1), "(cv4 <= cv1) failed");
static_assert((cv1 >= cv2), "(cv1 >= cv2) failed");
static_assert((cv2 >= cv1), "(cv2 >= cv1) failed");
static_assert(!(cv1 >= cv3), "!(cv1 >= cv3) failed");
static_assert((cv3 >= cv1), "(cv3 >= cv1) failed");
static_assert((cv1 >= cv4), "(cv1 >= cv4) failed");
static_assert((cv4 >= cv1), "(cv4 >= cv1) failed");
}
#endif
//*************************************************************************
TEST(test_maximum_unsigned_range_wrap_with_large_step_type)
{
etl::cyclic_value<uint8_t, 0, 255> value(0);
value.advance(static_cast<int32_t>(255));
CHECK_EQUAL(255, value);
value.advance(static_cast<int32_t>(1));
CHECK_EQUAL(0, value);
value.advance(static_cast<int32_t>(256));
CHECK_EQUAL(0, value);
value.advance(static_cast<int32_t>(-256));
CHECK_EQUAL(0, value);
value.advance(static_cast<int32_t>(-1));
CHECK_EQUAL(255, value);
}
//*************************************************************************
TEST(test_maximum_signed_range_wrap_with_large_step_type)
{
etl::cyclic_value<int8_t, -128, 127> value(0);
value.advance(static_cast<int32_t>(127));
CHECK_EQUAL(127, int(value));
value.advance(static_cast<int32_t>(1));
CHECK_EQUAL(-128, int(value));
value.advance(static_cast<int32_t>(256));
CHECK_EQUAL(-128, int(value));
value.advance(static_cast<int32_t>(-256));
CHECK_EQUAL(-128, int(value));
value.advance(static_cast<int32_t>(-1));
CHECK_EQUAL(127, int(value));
}
//*************************************************************************
TEST(test_compile_time_range_issue_in_advance_for_full_range_unsigned_limits_where_step_is_same_size_type)
{
const auto minimum = etl::integral_limits<uint8_t>::min;
const auto maximum = etl::integral_limits<uint8_t>::max;
etl::cyclic_value<uint8_t> value(minimum, maximum);
value.advance(int8_t(2));
CHECK_EQUAL(minimum + 2, value.get());
}
//*************************************************************************
TEST(test_compile_time_range_issue_in_advance_for_full_range_signed_limits_where_step_is_same_size_type)
{
const auto minimum = etl::integral_limits<int8_t>::min;
const auto maximum = etl::integral_limits<int8_t>::max;
etl::cyclic_value<int8_t> value(minimum, maximum);
value.advance(int8_t(2));
CHECK_EQUAL(minimum + 2, value.get());
}
//*************************************************************************
TEST(test_compile_time_range_issue_in_advance_for_full_range_unsigned_limits_where_step_is_larger_type)
{
const auto minimum = etl::integral_limits<uint8_t>::min;
const auto maximum = etl::integral_limits<uint8_t>::max;
etl::cyclic_value<uint8_t, minimum, maximum> value(0);
value.advance(int16_t(2));
CHECK_EQUAL(minimum + 2, value.get());
}
//*************************************************************************
TEST(test_compile_time_range_issue_in_advance_for_full_range_signed_limits_where_step_is_larger_type)
{
const auto minimum = etl::integral_limits<int8_t>::min;
const auto maximum = etl::integral_limits<int8_t>::max;
etl::cyclic_value<int8_t> value(minimum, maximum);
value.advance(uint16_t(2));
CHECK_EQUAL(minimum + 2, value.get());
}
//*************************************************************************
TEST(test_compile_time_range_issue_in_advance_for_full_range_unsigned_limits_where_step_is_smaller_type)
{
const auto minimum = etl::integral_limits<uint16_t>::min;
const auto maximum = etl::integral_limits<uint16_t>::max;
etl::cyclic_value<uint16_t, minimum, maximum> value(0);
value.advance(int8_t(2));
CHECK_EQUAL(minimum + 2, value.get());
}
//*************************************************************************
TEST(test_compile_time_range_issue_in_advance_for_full_range_signed_limits_where_step_is_smaller_type)
{
const auto minimum = etl::integral_limits<int16_t>::min;
const auto maximum = etl::integral_limits<int16_t>::max;
etl::cyclic_value<int16_t> value(minimum, maximum);
value.advance(int8_t(2));
CHECK_EQUAL(minimum + 2, value.get());
}
//*************************************************************************
TEST(test_compile_time_range_issue_in_advance_for_full_range_unsigned_limits_where_the_types_are_64bit)
{
const auto minimum = etl::integral_limits<uint64_t>::min;
const auto maximum = etl::integral_limits<uint64_t>::max;
etl::cyclic_value<uint64_t, minimum, maximum> value(0);
value.advance(int64_t(2));
CHECK_EQUAL(minimum + 2, value.get());
}
//*************************************************************************
TEST(test_compile_time_range_issue_in_advance_for_full_range_signed_limits_where_the_types_are_64bit)
{
const auto minimum = etl::integral_limits<int64_t>::min;
const auto maximum = etl::integral_limits<int64_t>::max;
etl::cyclic_value<int64_t> value(minimum, maximum);
value.advance(int64_t(2));
CHECK_EQUAL(minimum + 2, value.get());
}
//*************************************************************************
TEST(test_run_time_range_issue_in_advance_for_full_range_unsigned_limits_where_step_is_same_size_type)
{
const auto minimum = etl::integral_limits<uint8_t>::min;
const auto maximum = etl::integral_limits<uint8_t>::max;
etl::cyclic_value<uint8_t> value(minimum, maximum);
value.advance(int8_t(2));
CHECK_EQUAL(minimum + 2, value.get());
}
//*************************************************************************
TEST(test_run_time_range_issue_in_advance_for_full_range_signed_limits_where_step_is_same_size_type)
{
const auto minimum = etl::integral_limits<int8_t>::min;
const auto maximum = etl::integral_limits<int8_t>::max;
etl::cyclic_value<int8_t> value(minimum, maximum);
value.advance(int8_t(2));
CHECK_EQUAL(minimum + 2, value.get());
}
//*************************************************************************
TEST(test_run_time_range_issue_in_advance_for_full_range_unsigned_limits_where_step_is_larger_type)
{
const auto minimum = etl::integral_limits<uint8_t>::min;
const auto maximum = etl::integral_limits<uint8_t>::max;
etl::cyclic_value<uint8_t, minimum, maximum> value(0);
value.advance(int16_t(2));
CHECK_EQUAL(minimum + 2, value.get());
}
//*************************************************************************
TEST(test_run_time_range_issue_in_advance_for_full_range_signed_limits_where_step_is_larger_type)
{
const auto minimum = etl::integral_limits<int8_t>::min;
const auto maximum = etl::integral_limits<int8_t>::max;
etl::cyclic_value<int8_t> value(minimum, maximum);
value.advance(uint16_t(2));
CHECK_EQUAL(minimum + 2, value.get());
}
//*************************************************************************
TEST(test_run_time_range_issue_in_advance_for_full_range_unsigned_limits_where_step_is_smaller_type)
{
const auto minimum = etl::integral_limits<uint16_t>::min;
const auto maximum = etl::integral_limits<uint16_t>::max;
etl::cyclic_value<uint16_t, minimum, maximum> value(0);
value.advance(int8_t(2));
CHECK_EQUAL(minimum + 2, value.get());
}
//*************************************************************************
TEST(test_run_time_range_issue_in_advance_for_full_range_signed_limits_where_step_is_smaller_type)
{
const auto minimum = etl::integral_limits<int16_t>::min;
const auto maximum = etl::integral_limits<int16_t>::max;
etl::cyclic_value<int16_t> value(minimum, maximum);
value.advance(int8_t(2));
CHECK_EQUAL(minimum + 2, value.get());
}
//*************************************************************************
TEST(test_run_time_range_issue_in_advance_for_full_range_unsigned_limits_where_the_types_are_64bit)
{
const auto minimum = etl::integral_limits<uint64_t>::min;
const auto maximum = etl::integral_limits<uint64_t>::max;
etl::cyclic_value<uint64_t, minimum, maximum> value(0);
value.advance(int64_t(2));
CHECK_EQUAL(minimum + 2, value.get());
}
//*************************************************************************
TEST(test_run_time_range_issue_in_advance_for_full_range_signed_limits_where_the_types_are_64bit)
{
const auto minimum = etl::integral_limits<int64_t>::min;
const auto maximum = etl::integral_limits<int64_t>::max;
etl::cyclic_value<int64_t> value(minimum, maximum);
value.advance(int64_t(2));
CHECK_EQUAL(minimum + 2, value.get());
}
}
} // namespace

View File

@ -130,5 +130,120 @@ namespace
CHECK_TRUE(etl::is_exactly_equal(i1, i1));
CHECK_FALSE(etl::is_exactly_equal(i1, i2));
}
//*************************************************************************
TEST(test_floor)
{
float f1 = 1.7f;
float f2 = -1.7f;
double d1 = 1.7;
double d2 = -1.7;
long double ld1 = 1.7L;
long double ld2 = -1.7L;
CHECK_CLOSE(1.0f, etl::math::floor(f1), 0.0001f);
CHECK_CLOSE(-2.0f, etl::math::floor(f2), 0.0001f);
CHECK_CLOSE(1.0, etl::math::floor(d1), 0.0001);
CHECK_CLOSE(-2.0, etl::math::floor(d2), 0.0001);
CHECK_CLOSE(1.0L, etl::math::floor(ld1), 0.0001L);
CHECK_CLOSE(-2.0L, etl::math::floor(ld2), 0.0001L);
}
//*************************************************************************
TEST(test_ceil)
{
float f1 = 1.2f;
float f2 = -1.2f;
double d1 = 1.2;
double d2 = -1.2;
long double ld1 = 1.2L;
long double ld2 = -1.2L;
CHECK_CLOSE(2.0f, etl::math::ceil(f1), 0.0001f);
CHECK_CLOSE(-1.0f, etl::math::ceil(f2), 0.0001f);
CHECK_CLOSE(2.0, etl::math::ceil(d1), 0.0001);
CHECK_CLOSE(-1.0, etl::math::ceil(d2), 0.0001);
CHECK_CLOSE(2.0L, etl::math::ceil(ld1), 0.0001L);
CHECK_CLOSE(-1.0L, etl::math::ceil(ld2), 0.0001L);
}
//*************************************************************************
TEST(test_log10)
{
float f1 = 100.0f;
double d1 = 1000.0;
long double ld1 = 10000.0L;
CHECK_CLOSE(2.0f, etl::math::log10(f1), 0.0001f);
CHECK_CLOSE(3.0, etl::math::log10(d1), 0.0001);
CHECK_CLOSE(4.0L, etl::math::log10(ld1), 0.0001L);
}
//*************************************************************************
TEST(test_round)
{
float f1 = 1.5f;
float f2 = -1.5f;
float f3 = 1.4f;
float f4 = -1.4f;
double d1 = 2.5;
double d2 = -2.5;
double d3 = 2.4;
double d4 = -2.4;
long double ld1 = 3.5L;
long double ld2 = -3.5L;
long double ld3 = 3.4L;
long double ld4 = -3.4L;
CHECK_CLOSE(2.0f, etl::math::round(f1), 0.0001f);
CHECK_CLOSE(-2.0f, etl::math::round(f2), 0.0001f);
CHECK_CLOSE(1.0f, etl::math::round(f3), 0.0001f);
CHECK_CLOSE(-1.0f, etl::math::round(f4), 0.0001f);
CHECK_CLOSE(3.0, etl::math::round(d1), 0.0001);
CHECK_CLOSE(-3.0, etl::math::round(d2), 0.0001);
CHECK_CLOSE(2.0, etl::math::round(d3), 0.0001);
CHECK_CLOSE(-2.0, etl::math::round(d4), 0.0001);
CHECK_CLOSE(4.0L, etl::math::round(ld1), 0.0001L);
CHECK_CLOSE(-4.0L, etl::math::round(ld2), 0.0001L);
CHECK_CLOSE(3.0L, etl::math::round(ld3), 0.0001L);
CHECK_CLOSE(-3.0L, etl::math::round(ld4), 0.0001L);
}
//*************************************************************************
TEST(test_pow)
{
float fb = 2.0f;
float fe = 3.0f;
double db = 2.0;
double de = 10.0;
long double ldb = 2.0L;
long double lde = 4.0L;
CHECK_CLOSE(8.0f, etl::math::pow(fb, fe), 0.0001f);
CHECK_CLOSE(1024.0, etl::math::pow(db, de), 0.0001);
CHECK_CLOSE(16.0L, etl::math::pow(ldb, lde), 0.0001L);
}
//*************************************************************************
TEST(test_modf)
{
float f1 = 3.75f;
float f_intpart = 0.0f;
double d1 = 3.75;
double d_intpart = 0.0;
long double ld1 = 3.75L;
long double ld_intpart = 0.0L;
float f_frac = etl::math::modf(f1, &f_intpart);
double d_frac = etl::math::modf(d1, &d_intpart);
long double ld_frac = etl::math::modf(ld1, &ld_intpart);
CHECK_CLOSE(3.0f, f_intpart, 0.0001f);
CHECK_CLOSE(0.75f, f_frac, 0.0001f);
CHECK_CLOSE(3.0, d_intpart, 0.0001);
CHECK_CLOSE(0.75, d_frac, 0.0001);
CHECK_CLOSE((double)3.0L, (double)ld_intpart, 0.0001);
CHECK_CLOSE((double)0.75L, (double)ld_frac, 0.0001);
}
}
} // namespace

View File

@ -181,10 +181,21 @@ namespace
ss << etl::noboolalpha << false << STR(" ") << true << STR(" ") << etl::boolalpha << false << STR(" ") << true;
CHECK_EQUAL(String(STR("0 1 false true")), ss.str());
// Float
ss.str().clear();
ss << etl::setprecision(4) << 3.1415927f;
CHECK_EQUAL(String(STR("3.1416")), ss.str());
// Double
ss.str().clear();
ss << etl::setprecision(4) << 3.1415927;
CHECK_EQUAL(String(STR("3.1416")), ss.str());
// Long double
ss.str().clear();
ss << etl::setprecision(4) << 3.1415927l;
CHECK_EQUAL(String(STR("3.1416")), ss.str());
ss.str().clear();
ss << STR("abcdef") << STR(" ") << etl::uppercase << STR("abcdef");
CHECK_EQUAL(String(STR("abcdef abcdef")), ss.str());

View File

@ -181,10 +181,18 @@ namespace
ss << etl::noboolalpha << false << STR(" ") << true << STR(" ") << etl::boolalpha << false << STR(" ") << true;
CHECK_EQUAL(String(STR("0 1 false true")), ss.str());
ss.str().clear();
ss << etl::setprecision(4) << 3.1415927f;
CHECK_EQUAL(String(STR("3.1416")), ss.str());
ss.str().clear();
ss << etl::setprecision(4) << 3.1415927;
CHECK_EQUAL(String(STR("3.1416")), ss.str());
ss.str().clear();
ss << etl::setprecision(4) << 3.1415927l;
CHECK_EQUAL(String(STR("3.1416")), ss.str());
ss.str().clear();
ss << STR("abcdef") << STR(" ") << etl::uppercase << STR("abcdef");
CHECK_EQUAL(String(STR("abcdef abcdef")), ss.str());

View File

@ -181,10 +181,18 @@ namespace
ss << etl::noboolalpha << false << STR(" ") << true << STR(" ") << etl::boolalpha << false << STR(" ") << true;
CHECK_EQUAL(String(STR("0 1 false true")), ss.str());
ss.str().clear();
ss << etl::setprecision(4) << 3.1415927f;
CHECK_EQUAL(String(STR("3.1416")), ss.str());
ss.str().clear();
ss << etl::setprecision(4) << 3.1415927;
CHECK_EQUAL(String(STR("3.1416")), ss.str());
ss.str().clear();
ss << etl::setprecision(4) << 3.1415927l;
CHECK_EQUAL(String(STR("3.1416")), ss.str());
ss.str().clear();
ss << STR("abcdef") << STR(" ") << etl::uppercase << STR("abcdef");
CHECK_EQUAL(String(STR("abcdef abcdef")), ss.str());

View File

@ -184,10 +184,18 @@ namespace
ss << etl::noboolalpha << false << STR(" ") << true << STR(" ") << etl::boolalpha << false << STR(" ") << true;
CHECK_EQUAL(String(STR("0 1 false true")), ss.str());
ss.str().clear();
ss << etl::setprecision(4) << 3.1415927f;
CHECK_EQUAL(String(STR("3.1416")), ss.str());
ss.str().clear();
ss << etl::setprecision(4) << 3.1415927;
CHECK_EQUAL(String(STR("3.1416")), ss.str());
ss.str().clear();
ss << etl::setprecision(4) << 3.1415927l;
CHECK_EQUAL(String(STR("3.1416")), ss.str());
ss.str().clear();
ss << STR("abcdef") << STR(" ") << etl::uppercase << STR("abcdef");
CHECK_EQUAL(String(STR("abcdef abcdef")), ss.str());

View File

@ -182,10 +182,18 @@ namespace
ss << etl::noboolalpha << false << STR(" ") << true << STR(" ") << etl::boolalpha << false << STR(" ") << true;
CHECK_EQUAL(String(STR("0 1 false true")), ss.str());
ss.str().clear();
ss << etl::setprecision(4) << 3.1415927f;
CHECK_EQUAL(String(STR("3.1416")), ss.str());
ss.str().clear();
ss << etl::setprecision(4) << 3.1415927;
CHECK_EQUAL(String(STR("3.1416")), ss.str());
ss.str().clear();
ss << etl::setprecision(4) << 3.1415927l;
CHECK_EQUAL(String(STR("3.1416")), ss.str());
ss.str().clear();
ss << STR("abcdef") << STR(" ") << etl::uppercase << STR("abcdef");
CHECK_EQUAL(String(STR("abcdef abcdef")), ss.str());

View File

@ -44,32 +44,35 @@ namespace
{
typedef etl::format_spec Format;
using String20 = etl::string<20>;
using String64 = etl::string<64>;
SUITE(test_to_string)
{
//*************************************************************************
TEST(test_default_format_no_append)
{
etl::string<20> str;
String20 str;
CHECK(etl::string<20>(STR("0")) == etl::to_string(uint8_t(0), str));
CHECK(etl::string<20>(STR("0")) == etl::to_string(uint16_t(0), str));
CHECK(etl::string<20>(STR("0")) == etl::to_string(uint32_t(0), str));
CHECK(etl::string<20>(STR("0")) == etl::to_string(uint64_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint8_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint16_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint32_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint64_t(0), str));
CHECK(etl::string<20>(STR("128")) == etl::to_string(uint8_t(128), str));
CHECK(etl::string<20>(STR("32768")) == etl::to_string(uint16_t(32768), str));
CHECK(etl::string<20>(STR("2147483648")) == etl::to_string(uint32_t(2147483648ul), str));
CHECK(etl::string<20>(STR("9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str));
CHECK(String20(STR("128")) == etl::to_string(uint8_t(128), str));
CHECK(String20(STR("32768")) == etl::to_string(uint16_t(32768), str));
CHECK(String20(STR("2147483648")) == etl::to_string(uint32_t(2147483648ul), str));
CHECK(String20(STR("9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str));
CHECK(etl::string<20>(STR("127")) == etl::to_string(INT8_MAX, str));
CHECK(etl::string<20>(STR("32767")) == etl::to_string(INT16_MAX, str));
CHECK(etl::string<20>(STR("2147483647")) == etl::to_string(INT32_MAX, str));
CHECK(etl::string<20>(STR("9223372036854775807")) == etl::to_string(INT64_MAX, str));
CHECK(String20(STR("127")) == etl::to_string(INT8_MAX, str));
CHECK(String20(STR("32767")) == etl::to_string(INT16_MAX, str));
CHECK(String20(STR("2147483647")) == etl::to_string(INT32_MAX, str));
CHECK(String20(STR("9223372036854775807")) == etl::to_string(INT64_MAX, str));
CHECK(etl::string<20>(STR("-128")) == etl::to_string(INT8_MIN, str));
CHECK(etl::string<20>(STR("-32768")) == etl::to_string(INT16_MIN, str));
CHECK(etl::string<20>(STR("-2147483648")) == etl::to_string(INT32_MIN, str));
CHECK(etl::string<20>(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str));
CHECK(String20(STR("-128")) == etl::to_string(INT8_MIN, str));
CHECK(String20(STR("-32768")) == etl::to_string(INT16_MIN, str));
CHECK(String20(STR("-2147483648")) == etl::to_string(INT32_MIN, str));
CHECK(String20(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str));
}
//*************************************************************************
@ -107,89 +110,89 @@ namespace
//*************************************************************************
TEST(test_format_right_justified_no_append)
{
etl::string<20> str;
String20 str;
Format format = Format().base(10).width(20).fill(STR('#'));
etl::to_string(uint8_t(0), str, format);
CHECK(etl::string<20>(STR("###################0")) == etl::to_string(uint8_t(0), str, format));
CHECK(etl::string<20>(STR("###################0")) == etl::to_string(uint16_t(0), str, format));
CHECK(etl::string<20>(STR("###################0")) == etl::to_string(uint32_t(0), str, format));
CHECK(etl::string<20>(STR("###################0")) == etl::to_string(uint64_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint8_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint16_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint32_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint64_t(0), str, format));
CHECK(etl::string<20>(STR("#################128")) == etl::to_string(uint8_t(128), str, format));
CHECK(etl::string<20>(STR("###############32768")) == etl::to_string(uint16_t(32768), str, format));
CHECK(etl::string<20>(STR("##########2147483648")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(etl::string<20>(STR("#9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(String20(STR("#################128")) == etl::to_string(uint8_t(128), str, format));
CHECK(String20(STR("###############32768")) == etl::to_string(uint16_t(32768), str, format));
CHECK(String20(STR("##########2147483648")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(String20(STR("#9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(etl::string<20>(STR("#################127")) == etl::to_string(INT8_MAX, str, format));
CHECK(etl::string<20>(STR("###############32767")) == etl::to_string(INT16_MAX, str, format));
CHECK(etl::string<20>(STR("##########2147483647")) == etl::to_string(INT32_MAX, str, format));
CHECK(etl::string<20>(STR("#9223372036854775807")) == etl::to_string(INT64_MAX, str, format));
CHECK(String20(STR("#################127")) == etl::to_string(INT8_MAX, str, format));
CHECK(String20(STR("###############32767")) == etl::to_string(INT16_MAX, str, format));
CHECK(String20(STR("##########2147483647")) == etl::to_string(INT32_MAX, str, format));
CHECK(String20(STR("#9223372036854775807")) == etl::to_string(INT64_MAX, str, format));
CHECK(etl::string<20>(STR("################-128")) == etl::to_string(INT8_MIN, str, format));
CHECK(etl::string<20>(STR("##############-32768")) == etl::to_string(INT16_MIN, str, format));
CHECK(etl::string<20>(STR("#########-2147483648")) == etl::to_string(INT32_MIN, str, format));
CHECK(etl::string<20>(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
CHECK(String20(STR("################-128")) == etl::to_string(INT8_MIN, str, format));
CHECK(String20(STR("##############-32768")) == etl::to_string(INT16_MIN, str, format));
CHECK(String20(STR("#########-2147483648")) == etl::to_string(INT32_MIN, str, format));
CHECK(String20(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
}
//*************************************************************************
TEST(test_format_left_justified_no_append)
{
etl::string<20> str;
String20 str;
Format format = Format().base(10).width(20).fill(STR('#')).left();
CHECK(etl::string<20>(STR("0###################")) == etl::to_string(uint8_t(0), str, format));
CHECK(etl::string<20>(STR("0###################")) == etl::to_string(uint16_t(0), str, format));
CHECK(etl::string<20>(STR("0###################")) == etl::to_string(uint32_t(0), str, format));
CHECK(etl::string<20>(STR("0###################")) == etl::to_string(uint64_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint8_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint16_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint32_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint64_t(0), str, format));
CHECK(etl::string<20>(STR("128#################")) == etl::to_string(uint8_t(128), str, format));
CHECK(etl::string<20>(STR("32768###############")) == etl::to_string(uint16_t(32768), str, format));
CHECK(etl::string<20>(STR("2147483648##########")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(etl::string<20>(STR("9223372036854775808#")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(String20(STR("128#################")) == etl::to_string(uint8_t(128), str, format));
CHECK(String20(STR("32768###############")) == etl::to_string(uint16_t(32768), str, format));
CHECK(String20(STR("2147483648##########")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(String20(STR("9223372036854775808#")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(etl::string<20>(STR("127#################")) == etl::to_string(INT8_MAX, str, format));
CHECK(etl::string<20>(STR("32767###############")) == etl::to_string(INT16_MAX, str, format));
CHECK(etl::string<20>(STR("2147483647##########")) == etl::to_string(INT32_MAX, str, format));
CHECK(etl::string<20>(STR("9223372036854775807#")) == etl::to_string(INT64_MAX, str, format));
CHECK(String20(STR("127#################")) == etl::to_string(INT8_MAX, str, format));
CHECK(String20(STR("32767###############")) == etl::to_string(INT16_MAX, str, format));
CHECK(String20(STR("2147483647##########")) == etl::to_string(INT32_MAX, str, format));
CHECK(String20(STR("9223372036854775807#")) == etl::to_string(INT64_MAX, str, format));
CHECK(etl::string<20>(STR("-128################")) == etl::to_string(INT8_MIN, str, format));
CHECK(etl::string<20>(STR("-32768##############")) == etl::to_string(INT16_MIN, str, format));
CHECK(etl::string<20>(STR("-2147483648#########")) == etl::to_string(INT32_MIN, str, format));
CHECK(etl::string<20>(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
CHECK(String20(STR("-128################")) == etl::to_string(INT8_MIN, str, format));
CHECK(String20(STR("-32768##############")) == etl::to_string(INT16_MIN, str, format));
CHECK(String20(STR("-2147483648#########")) == etl::to_string(INT32_MIN, str, format));
CHECK(String20(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
}
//*************************************************************************
TEST(test_binary_format_no_append)
{
etl::string<64> str;
String64 str;
CHECK(etl::string<64>(STR("00000000")) == etl::to_string(uint8_t(0), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::string<64>(STR("0000000000000000")) == etl::to_string(uint16_t(0), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::string<64>(STR("00000000000000000000000000000000")) == etl::to_string(uint32_t(0), str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::string<64>(STR("0000000000000000000000000000000000000000000000000000000000000000"))
CHECK(String64(STR("00000000")) == etl::to_string(uint8_t(0), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("0000000000000000")) == etl::to_string(uint16_t(0), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("00000000000000000000000000000000")) == etl::to_string(uint32_t(0), str, Format().base(2).width(32).fill(STR('0'))));
CHECK(String64(STR("0000000000000000000000000000000000000000000000000000000000000000"))
== etl::to_string(uint64_t(0), str, Format().base(2).width(64).fill(STR('0'))));
CHECK(etl::string<64>(STR("10000000")) == etl::to_string(uint8_t(128), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::string<64>(STR("1000000000000000")) == etl::to_string(uint16_t(32768), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::string<64>(STR("10000000000000000000000000000000"))
CHECK(String64(STR("10000000")) == etl::to_string(uint8_t(128), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("1000000000000000")) == etl::to_string(uint16_t(32768), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("10000000000000000000000000000000"))
== etl::to_string(uint32_t(2147483648ul), str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::string<64>(STR("1000000000000000000000000000000000000000000000000000000000000000"))
CHECK(String64(STR("1000000000000000000000000000000000000000000000000000000000000000"))
== etl::to_string(uint64_t(9223372036854775808ull), str, Format().base(2).width(64).fill(STR('0'))));
CHECK(etl::string<64>(STR("01111111")) == etl::to_string(INT8_MAX, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::string<64>(STR("0111111111111111")) == etl::to_string(INT16_MAX, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::string<64>(STR("01111111111111111111111111111111")) == etl::to_string(INT32_MAX, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::string<64>(STR("0111111111111111111111111111111111111111111111111111111111111111"))
CHECK(String64(STR("01111111")) == etl::to_string(INT8_MAX, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("0111111111111111")) == etl::to_string(INT16_MAX, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("01111111111111111111111111111111")) == etl::to_string(INT32_MAX, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(String64(STR("0111111111111111111111111111111111111111111111111111111111111111"))
== etl::to_string(INT64_MAX, str, Format().base(2).width(64).fill(STR('0'))));
CHECK(etl::string<64>(STR("10000000")) == etl::to_string(INT8_MIN, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::string<64>(STR("1000000000000000")) == etl::to_string(INT16_MIN, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::string<64>(STR("10000000000000000000000000000000")) == etl::to_string(INT32_MIN, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::string<64>(STR("1000000000000000000000000000000000000000000000000000000000000000"))
CHECK(String64(STR("10000000")) == etl::to_string(INT8_MIN, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("1000000000000000")) == etl::to_string(INT16_MIN, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("10000000000000000000000000000000")) == etl::to_string(INT32_MIN, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(String64(STR("1000000000000000000000000000000000000000000000000000000000000000"))
== etl::to_string(INT64_MIN, str, Format().base(2).width(64).fill(STR('0'))));
}
@ -261,126 +264,126 @@ namespace
//*************************************************************************
TEST(test_floating_point_no_append)
{
etl::string<20> str;
String20 str;
CHECK(etl::string<20>(STR(" 0.000000")) == etl::to_string(0.0, str, Format().precision(6).width(10).right()));
CHECK(etl::string<20>(STR("0.000000 ")) == etl::to_string(0.0, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 0.000000")) == etl::to_string(0.0, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("0.000000 ")) == etl::to_string(0.0, str, Format().precision(6).width(10).left()));
CHECK(etl::string<20>(STR(" 0.000001")) == etl::to_string(0.000001, str, Format().precision(6).width(10).right()));
CHECK(etl::string<20>(STR("0.000001 ")) == etl::to_string(0.000001, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 0.000001")) == etl::to_string(0.000001, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("0.000001 ")) == etl::to_string(0.000001, str, Format().precision(6).width(10).left()));
CHECK(etl::string<20>(STR(" 1.000000")) == etl::to_string(1.0, str, Format().precision(6).width(10).right()));
CHECK(etl::string<20>(STR("1.000000 ")) == etl::to_string(1.0, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 1.000000")) == etl::to_string(1.0, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("1.000000 ")) == etl::to_string(1.0, str, Format().precision(6).width(10).left()));
CHECK(etl::string<20>(STR(" 1.000001")) == etl::to_string(1.000001, str, Format().precision(6).width(10).right()));
CHECK(etl::string<20>(STR("1.000001 ")) == etl::to_string(1.000001, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 1.000001")) == etl::to_string(1.000001, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("1.000001 ")) == etl::to_string(1.000001, str, Format().precision(6).width(10).left()));
CHECK(etl::string<20>(STR(" 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right()));
CHECK(etl::string<20>(STR("12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left()));
CHECK(etl::string<20>(STR(" -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right()));
CHECK(etl::string<20>(STR("-12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left()));
CHECK(String20(STR(" -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right()));
CHECK(String20(STR("-12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left()));
CHECK(etl::string<20>(STR(" -0.123456")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).right()));
CHECK(etl::string<20>(STR("-0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" -0.123456")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("-0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left()));
// Positive rollover
CHECK(etl::string<20>(STR(" 2.000000")) == etl::to_string(1.9999996, str, Format().precision(6).width(10).right()));
CHECK(etl::string<20>(STR("2.000000 ")) == etl::to_string(1.9999996, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 2.000000")) == etl::to_string(1.9999996, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("2.000000 ")) == etl::to_string(1.9999996, str, Format().precision(6).width(10).left()));
// Negative rollover
CHECK(etl::string<20>(STR(" -2.000000")) == etl::to_string(-1.9999996, str, Format().precision(6).width(10).right()));
CHECK(etl::string<20>(STR("-2.000000 ")) == etl::to_string(-1.9999996, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" -2.000000")) == etl::to_string(-1.9999996, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("-2.000000 ")) == etl::to_string(-1.9999996, str, Format().precision(6).width(10).left()));
}
//*************************************************************************
TEST(test_floating_point_append)
{
etl::string<20> str;
String20 str;
str.assign(STR("Result "));
CHECK(etl::string<20>(STR("Result 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right(), true));
CHECK(String20(STR("Result 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right(), true));
str.assign(STR("Result "));
CHECK(etl::string<20>(STR("Result 12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left(), true));
CHECK(String20(STR("Result 12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left(), true));
str.assign(STR("Result "));
CHECK(etl::string<20>(STR("Result -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right(), true));
CHECK(String20(STR("Result -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right(), true));
str.assign(STR("Result "));
CHECK(etl::string<20>(STR("Result -12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left(), true));
CHECK(String20(STR("Result -12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left(), true));
str.assign(STR("Result "));
CHECK(etl::string<20>(STR("Result -0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left(), true));
CHECK(String20(STR("Result -0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left(), true));
}
//*************************************************************************
TEST(test_floating_point_rounding)
{
etl::string<20> str;
String20 str;
CHECK(etl::string<20>(STR("0.00001")) == etl::to_string(0.000009, str, Format().precision(5).width(7).right()));
CHECK(etl::string<20>(STR("0.0001")) == etl::to_string(0.000099, str, Format().precision(4).width(6).right()));
CHECK(etl::string<20>(STR("0.001")) == etl::to_string(0.000999, str, Format().precision(3).width(5).right()));
CHECK(etl::string<20>(STR("0.01")) == etl::to_string(0.009999, str, Format().precision(2).width(4).right()));
CHECK(etl::string<20>(STR("0.1")) == etl::to_string(0.099999, str, Format().precision(1).width(3).right()));
CHECK(etl::string<20>(STR("1.0")) == etl::to_string(0.999999, str, Format().precision(1).width(3).right()));
CHECK(etl::string<20>(STR("1")) == etl::to_string(0.999999, str, Format().precision(0).width(1).right()));
CHECK(etl::string<20>(STR("2")) == etl::to_string(1.999999, str, Format().precision(0).width(1).right()));
CHECK(etl::string<20>(STR("10.0")) == etl::to_string(9.999999, str, Format().precision(1).width(4).right()));
CHECK(etl::string<20>(STR("20.0")) == etl::to_string(19.999999, str, Format().precision(1).width(4).right()));
CHECK(String20(STR("0.00001")) == etl::to_string(0.000009, str, Format().precision(5).width(7).right()));
CHECK(String20(STR("0.0001")) == etl::to_string(0.000099, str, Format().precision(4).width(6).right()));
CHECK(String20(STR("0.001")) == etl::to_string(0.000999, str, Format().precision(3).width(5).right()));
CHECK(String20(STR("0.01")) == etl::to_string(0.009999, str, Format().precision(2).width(4).right()));
CHECK(String20(STR("0.1")) == etl::to_string(0.099999, str, Format().precision(1).width(3).right()));
CHECK(String20(STR("1.0")) == etl::to_string(0.999999, str, Format().precision(1).width(3).right()));
CHECK(String20(STR("1")) == etl::to_string(0.999999, str, Format().precision(0).width(1).right()));
CHECK(String20(STR("2")) == etl::to_string(1.999999, str, Format().precision(0).width(1).right()));
CHECK(String20(STR("10.0")) == etl::to_string(9.999999, str, Format().precision(1).width(4).right()));
CHECK(String20(STR("20.0")) == etl::to_string(19.999999, str, Format().precision(1).width(4).right()));
}
//*************************************************************************
TEST(test_bool_no_append)
{
etl::string<20> str;
String20 str;
CHECK(etl::string<20>(STR(" 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(etl::string<20>(STR(" 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(etl::string<20>(STR("0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(etl::string<20>(STR("1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(String20(STR(" 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(String20(STR(" 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(String20(STR("0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(String20(STR("1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(etl::string<20>(STR(" false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(etl::string<20>(STR(" true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(etl::string<20>(STR("false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true)));
CHECK(etl::string<20>(STR("true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true)));
CHECK(String20(STR(" false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(String20(STR(" true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(String20(STR("false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true)));
CHECK(String20(STR("true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true)));
}
//*************************************************************************
TEST(test_bool_append)
{
etl::string<20> str;
String20 str;
str.assign(STR("Result "));
CHECK(etl::string<20>(STR("Result 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false), true));
CHECK(String20(STR("Result 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::string<20>(STR("Result 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false), true));
CHECK(String20(STR("Result 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::string<20>(STR("Result 0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false), true));
CHECK(String20(STR("Result 0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::string<20>(STR("Result 1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false), true));
CHECK(String20(STR("Result 1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::string<20>(STR("Result false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true), true));
CHECK(String20(STR("Result false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true), true));
str.assign(STR("Result "));
CHECK(etl::string<20>(STR("Result true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true), true));
CHECK(String20(STR("Result true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true), true));
str.assign(STR("Result "));
CHECK(etl::string<20>(STR("Result false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true), true));
CHECK(String20(STR("Result false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true), true));
str.assign(STR("Result "));
CHECK(etl::string<20>(STR("Result true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true), true));
CHECK(String20(STR("Result true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true), true));
}
//*************************************************************************
TEST(test_pointer_no_append)
{
etl::string<20> str;
String20 str;
static const volatile int cvi = 0;
@ -388,8 +391,8 @@ namespace
oss.width(10);
oss.fill(STR('0'));
oss << std::hex << std::right << uintptr_t(&cvi);
std::string temp(oss.str());
etl::string<20> compare(temp.begin(), temp.end());
std::string temp(oss.str());
String20 compare(temp.begin(), temp.end());
to_string(&cvi, str, Format().hex().width(10).right().fill(STR('0')));
CHECK(compare == str);
@ -409,7 +412,7 @@ namespace
//*************************************************************************
TEST(test_pointer_append)
{
etl::string<20> str;
String20 str;
static const volatile int cvi = 0;
@ -419,7 +422,7 @@ namespace
oss << std::hex << std::right << uintptr_t(&cvi);
std::string temp(STR("Result "));
temp.append(oss.str());
etl::string<20> compare(temp.begin(), temp.end());
String20 compare(temp.begin(), temp.end());
str.assign(STR("Result "));
to_string(&cvi, str, Format().hex().width(10).right().fill(STR('0')), true);
@ -442,229 +445,229 @@ namespace
//*************************************************************************
TEST(test_integer_denominator_default_format)
{
etl::string<20> result;
int value = -1234567;
String20 result;
int value = -1234567;
etl::to_string(value, 6U, result);
CHECK_EQUAL(etl::string<20>(STR("-1")).c_str(), result.c_str());
CHECK_EQUAL(String20(STR("-1")).c_str(), result.c_str());
}
//*************************************************************************
TEST(test_integer_denominator_huge_precision)
{
etl::string<20> result;
int value = -1234560;
String20 result;
int value = -1234560;
Format format = Format().precision(100);
etl::to_string(value, 6U, result, format);
CHECK_EQUAL(etl::string<20>(STR("-1.234560")).c_str(), result.c_str());
CHECK_EQUAL(String20(STR("-1.234560")).c_str(), result.c_str());
}
//*************************************************************************
TEST(test_integer_denominator_huge_precision_64bit)
{
etl::string<20> result;
int64_t value = INT64_MIN;
String20 result;
int64_t value = INT64_MIN;
Format format = Format().precision(100);
etl::to_string(value, 12U, result, format);
CHECK_EQUAL(etl::string<20>(STR("-9223372.036854775808")).c_str(), result.c_str());
CHECK_EQUAL(String20(STR("-9223372.036854775808")).c_str(), result.c_str());
}
//*************************************************************************
TEST(test_integer_denominator_zero_fractional)
{
etl::string<20> result_i;
int value_i = -1000000;
String20 result_i;
int value_i = -1000000;
etl::string<20> result_d;
double value_d = -1.000000;
String20 result_d;
double value_d = -1.000000;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK_EQUAL(etl::string<20>(STR("-1.0000")).c_str(), result_i.c_str());
CHECK_EQUAL(String20(STR("-1.0000")).c_str(), result_i.c_str());
CHECK_EQUAL(result_d.c_str(), result_i.c_str());
}
//*************************************************************************
TEST(test_integer_denominator_zero_value)
{
etl::string<20> result_i;
int value_i = 0;
String20 result_i;
int value_i = 0;
etl::string<20> result_d;
double value_d = -0.000000;
String20 result_d;
double value_d = -0.000000;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK_EQUAL(etl::string<20>(STR("0.0000")).c_str(), result_i.c_str());
CHECK_EQUAL(String20(STR("0.0000")).c_str(), result_i.c_str());
CHECK_EQUAL(result_d.c_str(), result_i.c_str());
}
//*************************************************************************
TEST(test_integer_denominator_zero_integral_small_fractional)
{
etl::string<20> result_i;
int value_i = -400;
String20 result_i;
int value_i = -400;
etl::string<20> result_d;
double value_d = -0.000400;
String20 result_d;
double value_d = -0.000400;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK_EQUAL(etl::string<20>(STR("-0.0004")).c_str(), result_i.c_str());
CHECK_EQUAL(String20(STR("-0.0004")).c_str(), result_i.c_str());
CHECK_EQUAL(result_d.c_str(), result_i.c_str());
}
//*************************************************************************
TEST(test_integer_denominator_small_fractional)
{
etl::string<20> result_i;
int value_i = -123000400;
String20 result_i;
int value_i = -123000400;
etl::string<20> result_d;
double value_d = -123.000400;
String20 result_d;
double value_d = -123.000400;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK_EQUAL(etl::string<20>(STR("-123.0004")).c_str(), result_i.c_str());
CHECK_EQUAL(String20(STR("-123.0004")).c_str(), result_i.c_str());
CHECK_EQUAL(result_d.c_str(), result_i.c_str());
}
//*************************************************************************
TEST(test_integer_denominator_very_small_fractional)
{
etl::string<20> result_i;
int value_i = -123000004;
String20 result_i;
int value_i = -123000004;
etl::string<20> result_d;
double value_d = -123.000004;
String20 result_d;
double value_d = -123.000004;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK_EQUAL(etl::string<20>(STR("-123.0000")).c_str(), result_i.c_str());
CHECK_EQUAL(String20(STR("-123.0000")).c_str(), result_i.c_str());
CHECK_EQUAL(result_d.c_str(), result_i.c_str());
}
//*************************************************************************
TEST(test_integer_denominator_very_small_fractional_rounded_up)
{
etl::string<20> result_i;
int value_i = -123000050;
String20 result_i;
int value_i = -123000050;
etl::string<20> result_d;
double value_d = -123.000050;
String20 result_d;
double value_d = -123.000050;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK_EQUAL(etl::string<20>(STR("-123.0001")).c_str(), result_i.c_str());
CHECK_EQUAL(String20(STR("-123.0001")).c_str(), result_i.c_str());
CHECK_EQUAL(result_d.c_str(), result_i.c_str());
}
//*************************************************************************
TEST(test_integer_denominator_shorter_width)
{
etl::string<20> result_i;
int value_i = -123456780;
String20 result_i;
int value_i = -123456780;
etl::string<20> result_d;
double value_d = -123.456780;
String20 result_d;
double value_d = -123.456780;
Format format = Format().precision(4).width(6).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK_EQUAL(etl::string<20>(STR("-123.4568")).c_str(), result_i.c_str());
CHECK_EQUAL(String20(STR("-123.4568")).c_str(), result_i.c_str());
CHECK_EQUAL(result_d.c_str(), result_i.c_str());
}
//*************************************************************************
TEST(test_double_formatting_10_decimal_point)
{
etl::string<20> result_d;
double value_d = 1.2345;
String20 result_d;
double value_d = 1.2345;
Format format = Format().precision(10);
etl::to_string(value_d, result_d, format);
CHECK_EQUAL(etl::string<20>(STR("1.2345000000")).c_str(), result_d.c_str());
CHECK_EQUAL(String20(STR("1.2345000000")).c_str(), result_d.c_str());
}
//*************************************************************************
TEST(test_integer_denominator_larger_width)
{
etl::string<20> result_i;
int value_i = -123456780;
String20 result_i;
int value_i = -123456780;
etl::string<20> result_d;
double value_d = -123.456780;
String20 result_d;
double value_d = -123.456780;
Format format = Format().precision(4).width(15).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK_EQUAL(etl::string<20>(STR(" -123.4568")).c_str(), result_i.c_str());
CHECK_EQUAL(String20(STR(" -123.4568")).c_str(), result_i.c_str());
CHECK_EQUAL(result_d.c_str(), result_i.c_str());
}
//*************************************************************************
TEST(test_integer_denominator_positive_rollover)
{
etl::string<20> result_i;
int value_i = 123999990;
String20 result_i;
int value_i = 123999990;
etl::string<20> result_d;
double value_d = 123.999990;
String20 result_d;
double value_d = 123.999990;
Format format = Format().precision(4).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK_EQUAL(etl::string<20>(STR("124.0000")).c_str(), result_i.c_str());
CHECK_EQUAL(String20(STR("124.0000")).c_str(), result_i.c_str());
CHECK_EQUAL(result_d.c_str(), result_i.c_str());
}
//*************************************************************************
TEST(test_integer_denominator_negative_rollover)
{
etl::string<20> result_i;
int value_i = -123999990;
String20 result_i;
int value_i = -123999990;
etl::string<20> result_d;
double value_d = -123.999990;
String20 result_d;
double value_d = -123.999990;
Format format = Format().precision(4).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK_EQUAL(etl::string<20>(STR("-124.0000")).c_str(), result_i.c_str());
CHECK_EQUAL(String20(STR("-124.0000")).c_str(), result_i.c_str());
CHECK_EQUAL(result_d.c_str(), result_i.c_str());
}
@ -674,48 +677,48 @@ namespace
if (std::numeric_limits<double>::is_iec559)
{
// Check forced scientific formatting for smaller numbers.
etl::string<64> s0;
String64 s0;
etl::to_string(1000.0, s0, Format().precision(5).width(15).right().scientific(true));
CHECK(etl::string<64>(STR(" 1.00000e+3")) == s0);
CHECK(String64(STR(" 1.00000e+3")) == s0);
etl::to_string(1000.0, s0, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::string<64>(STR(" 1.00000E+3")) == s0);
CHECK(String64(STR(" 1.00000E+3")) == s0);
// Maximum double value is 1.7976931348623157e+308, which rounds to 1.79769e+308 with 5 digits of precision.
etl::string<64> s1;
String64 s1;
etl::to_string(std::numeric_limits<double>::max(), s1, Format().precision(5).width(15).right());
CHECK(etl::string<64>(STR(" 1.79769e+308")) == s1);
CHECK(String64(STR(" 1.79769e+308")) == s1);
// Negative maximum double value is -1.7976931348623157e+308, which rounds to -1.79769e+308 with 5 digits of precision.
etl::string<64> s2;
String64 s2;
etl::to_string(-std::numeric_limits<double>::max(), s2, Format().precision(5).width(15).right());
CHECK(etl::string<64>(STR(" -1.79769e+308")) == s2);
CHECK(String64(STR(" -1.79769e+308")) == s2);
}
#if ETL_USING_64BIT_TYPES
using workspace_t = etl::private_to_string::workspace_t;
// Maximum workspace_t value is 9223372036854775807.
etl::string<64> s3;
String64 s3;
etl::to_string(std::numeric_limits<workspace_t>::max(), s3, Format().precision(5).width(21).right());
CHECK(etl::string<64>(STR(" 9223372036854775807")) == s3);
CHECK(String64(STR(" 9223372036854775807")) == s3);
// Minimum workspace_t value is -9223372036854775808.
etl::string<64> s4;
String64 s4;
etl::to_string(std::numeric_limits<workspace_t>::min(), s4, Format().precision(5).width(21).right());
CHECK(etl::string<64>(STR(" -9223372036854775808")) == s4);
CHECK(String64(STR(" -9223372036854775808")) == s4);
using uworkspace_t = etl::private_to_string::uworkspace_t;
// Maximum uworkspace_t value is 18446744073709551615.
etl::string<64> s5;
String64 s5;
etl::to_string(std::numeric_limits<uworkspace_t>::max(), s5, Format().precision(5).width(21).right());
CHECK(etl::string<64>(STR(" 18446744073709551615")) == s5);
CHECK(String64(STR(" 18446744073709551615")) == s5);
// Minimum uworkspace_t value is 0.
etl::string<64> s6;
String64 s6;
etl::to_string(std::numeric_limits<uworkspace_t>::min(), s6, Format().precision(5).width(21).right());
CHECK(etl::string<64>(STR(" 0")) == s6);
CHECK(String64(STR(" 0")) == s6);
#endif
}
@ -724,30 +727,48 @@ namespace
{
if (std::numeric_limits<double>::is_iec559)
{
etl::string<64> s1;
String64 s1;
etl::to_string(std::numeric_limits<double>::quiet_NaN(), s1, Format().precision(5).width(15).right().scientific(true).upper_case(false));
CHECK(etl::string<64>(STR(" nan")) == s1);
CHECK(String64(STR(" nan")) == s1);
etl::string<64> s2;
String64 s2;
etl::to_string(std::numeric_limits<double>::infinity(), s2, Format().precision(5).width(15).right().scientific(true).upper_case(false));
CHECK(etl::string<64>(STR(" inf")) == s2);
CHECK(String64(STR(" inf")) == s2);
etl::string<64> s3;
String64 s3;
etl::to_string(-std::numeric_limits<double>::infinity(), s3, Format().precision(5).width(15).right().scientific(true).upper_case(false));
CHECK(etl::string<64>(STR(" -inf")) == s3);
CHECK(String64(STR(" -inf")) == s3);
etl::string<64> s4;
String64 s4;
etl::to_string(std::numeric_limits<double>::quiet_NaN(), s4, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::string<64>(STR(" NAN")) == s4);
CHECK(String64(STR(" NAN")) == s4);
etl::string<64> s5;
String64 s5;
etl::to_string(std::numeric_limits<double>::infinity(), s5, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::string<64>(STR(" INF")) == s5);
CHECK(String64(STR(" INF")) == s5);
etl::string<64> s6;
String64 s6;
etl::to_string(-std::numeric_limits<double>::infinity(), s6, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::string<64>(STR(" -INF")) == s6);
CHECK(String64(STR(" -INF")) == s6);
}
}
//*************************************************************************
TEST(test_issue_1593_to_string_float_uses_double_math)
{
String64 s1;
// Float
etl::to_string(3.1415927f, s1, Format().precision(4));
CHECK_TRUE(String64(STR("3.1416")) == s1);
// Double
etl::to_string(3.1415927, s1, Format().precision(4));
CHECK_TRUE(String64(STR("3.1416")) == s1);
// Long double
etl::to_string(3.1415927l, s1, Format().precision(4));
CHECK_TRUE(String64(STR("3.1416")) == s1);
}
}
} // namespace

View File

@ -41,32 +41,35 @@ namespace
{
typedef etl::u16format_spec Format;
using String20 = etl::u16string<20>;
using String64 = etl::u16string<64>;
SUITE(test_to_u16string)
{
//*************************************************************************
TEST(test_default_format_no_append)
{
etl::u16string<20> str;
String20 str;
CHECK(etl::u16string<20>(STR("0")) == etl::to_string(uint8_t(0), str));
CHECK(etl::u16string<20>(STR("0")) == etl::to_string(uint16_t(0), str));
CHECK(etl::u16string<20>(STR("0")) == etl::to_string(uint32_t(0), str));
CHECK(etl::u16string<20>(STR("0")) == etl::to_string(uint64_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint8_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint16_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint32_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint64_t(0), str));
CHECK(etl::u16string<20>(STR("128")) == etl::to_string(uint8_t(128), str));
CHECK(etl::u16string<20>(STR("32768")) == etl::to_string(uint16_t(32768), str));
CHECK(etl::u16string<20>(STR("2147483648")) == etl::to_string(uint32_t(2147483648ul), str));
CHECK(etl::u16string<20>(STR("9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str));
CHECK(String20(STR("128")) == etl::to_string(uint8_t(128), str));
CHECK(String20(STR("32768")) == etl::to_string(uint16_t(32768), str));
CHECK(String20(STR("2147483648")) == etl::to_string(uint32_t(2147483648ul), str));
CHECK(String20(STR("9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str));
CHECK(etl::u16string<20>(STR("127")) == etl::to_string(INT8_MAX, str));
CHECK(etl::u16string<20>(STR("32767")) == etl::to_string(INT16_MAX, str));
CHECK(etl::u16string<20>(STR("2147483647")) == etl::to_string(INT32_MAX, str));
CHECK(etl::u16string<20>(STR("9223372036854775807")) == etl::to_string(INT64_MAX, str));
CHECK(String20(STR("127")) == etl::to_string(INT8_MAX, str));
CHECK(String20(STR("32767")) == etl::to_string(INT16_MAX, str));
CHECK(String20(STR("2147483647")) == etl::to_string(INT32_MAX, str));
CHECK(String20(STR("9223372036854775807")) == etl::to_string(INT64_MAX, str));
CHECK(etl::u16string<20>(STR("-128")) == etl::to_string(INT8_MIN, str));
CHECK(etl::u16string<20>(STR("-32768")) == etl::to_string(INT16_MIN, str));
CHECK(etl::u16string<20>(STR("-2147483648")) == etl::to_string(INT32_MIN, str));
CHECK(etl::u16string<20>(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str));
CHECK(String20(STR("-128")) == etl::to_string(INT8_MIN, str));
CHECK(String20(STR("-32768")) == etl::to_string(INT16_MIN, str));
CHECK(String20(STR("-2147483648")) == etl::to_string(INT32_MIN, str));
CHECK(String20(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str));
}
//*************************************************************************
@ -104,88 +107,87 @@ namespace
//*************************************************************************
TEST(test_format_right_justified_no_append)
{
etl::u16string<20> str;
String20 str;
Format format = Format().base(10).width(20).fill(STR('#'));
CHECK(etl::u16string<20>(STR("###################0")) == etl::to_string(uint8_t(0), str, format));
CHECK(etl::u16string<20>(STR("###################0")) == etl::to_string(uint16_t(0), str, format));
CHECK(etl::u16string<20>(STR("###################0")) == etl::to_string(uint32_t(0), str, format));
CHECK(etl::u16string<20>(STR("###################0")) == etl::to_string(uint64_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint8_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint16_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint32_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint64_t(0), str, format));
CHECK(etl::u16string<20>(STR("#################128")) == etl::to_string(uint8_t(128), str, format));
CHECK(etl::u16string<20>(STR("###############32768")) == etl::to_string(uint16_t(32768), str, format));
CHECK(etl::u16string<20>(STR("##########2147483648")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(etl::u16string<20>(STR("#9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(String20(STR("#################128")) == etl::to_string(uint8_t(128), str, format));
CHECK(String20(STR("###############32768")) == etl::to_string(uint16_t(32768), str, format));
CHECK(String20(STR("##########2147483648")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(String20(STR("#9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(etl::u16string<20>(STR("#################127")) == etl::to_string(INT8_MAX, str, format));
CHECK(etl::u16string<20>(STR("###############32767")) == etl::to_string(INT16_MAX, str, format));
CHECK(etl::u16string<20>(STR("##########2147483647")) == etl::to_string(INT32_MAX, str, format));
CHECK(etl::u16string<20>(STR("#9223372036854775807")) == etl::to_string(INT64_MAX, str, format));
CHECK(String20(STR("#################127")) == etl::to_string(INT8_MAX, str, format));
CHECK(String20(STR("###############32767")) == etl::to_string(INT16_MAX, str, format));
CHECK(String20(STR("##########2147483647")) == etl::to_string(INT32_MAX, str, format));
CHECK(String20(STR("#9223372036854775807")) == etl::to_string(INT64_MAX, str, format));
CHECK(etl::u16string<20>(STR("################-128")) == etl::to_string(INT8_MIN, str, format));
CHECK(etl::u16string<20>(STR("##############-32768")) == etl::to_string(INT16_MIN, str, format));
CHECK(etl::u16string<20>(STR("#########-2147483648")) == etl::to_string(INT32_MIN, str, format));
CHECK(etl::u16string<20>(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
CHECK(String20(STR("################-128")) == etl::to_string(INT8_MIN, str, format));
CHECK(String20(STR("##############-32768")) == etl::to_string(INT16_MIN, str, format));
CHECK(String20(STR("#########-2147483648")) == etl::to_string(INT32_MIN, str, format));
CHECK(String20(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
}
//*************************************************************************
TEST(test_format_left_justified_no_append)
{
etl::u16string<20> str;
String20 str;
Format format = Format().base(10).width(20).fill(STR('#')).left();
CHECK(etl::u16string<20>(STR("0###################")) == etl::to_string(uint8_t(0), str, format));
CHECK(etl::u16string<20>(STR("0###################")) == etl::to_string(uint16_t(0), str, format));
CHECK(etl::u16string<20>(STR("0###################")) == etl::to_string(uint32_t(0), str, format));
CHECK(etl::u16string<20>(STR("0###################")) == etl::to_string(uint64_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint8_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint16_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint32_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint64_t(0), str, format));
CHECK(etl::u16string<20>(STR("128#################")) == etl::to_string(uint8_t(128), str, format));
CHECK(etl::u16string<20>(STR("32768###############")) == etl::to_string(uint16_t(32768), str, format));
CHECK(etl::u16string<20>(STR("2147483648##########")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(etl::u16string<20>(STR("9223372036854775808#")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(String20(STR("128#################")) == etl::to_string(uint8_t(128), str, format));
CHECK(String20(STR("32768###############")) == etl::to_string(uint16_t(32768), str, format));
CHECK(String20(STR("2147483648##########")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(String20(STR("9223372036854775808#")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(etl::u16string<20>(STR("127#################")) == etl::to_string(INT8_MAX, str, format));
CHECK(etl::u16string<20>(STR("32767###############")) == etl::to_string(INT16_MAX, str, format));
CHECK(etl::u16string<20>(STR("2147483647##########")) == etl::to_string(INT32_MAX, str, format));
CHECK(etl::u16string<20>(STR("9223372036854775807#")) == etl::to_string(INT64_MAX, str, format));
CHECK(String20(STR("127#################")) == etl::to_string(INT8_MAX, str, format));
CHECK(String20(STR("32767###############")) == etl::to_string(INT16_MAX, str, format));
CHECK(String20(STR("2147483647##########")) == etl::to_string(INT32_MAX, str, format));
CHECK(String20(STR("9223372036854775807#")) == etl::to_string(INT64_MAX, str, format));
CHECK(etl::u16string<20>(STR("-128################")) == etl::to_string(INT8_MIN, str, format));
CHECK(etl::u16string<20>(STR("-32768##############")) == etl::to_string(INT16_MIN, str, format));
CHECK(etl::u16string<20>(STR("-2147483648#########")) == etl::to_string(INT32_MIN, str, format));
CHECK(etl::u16string<20>(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
CHECK(String20(STR("-128################")) == etl::to_string(INT8_MIN, str, format));
CHECK(String20(STR("-32768##############")) == etl::to_string(INT16_MIN, str, format));
CHECK(String20(STR("-2147483648#########")) == etl::to_string(INT32_MIN, str, format));
CHECK(String20(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
}
//*************************************************************************
TEST(test_binary_format_no_append)
{
etl::u16string<64> str;
String64 str;
CHECK(etl::u16string<64>(STR("00000000")) == etl::to_string(uint8_t(0), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::u16string<64>(STR("0000000000000000")) == etl::to_string(uint16_t(0), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::u16string<64>(STR("00000000000000000000000000000000"))
== etl::to_string(uint32_t(0), str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::u16string<64>(STR("0000000000000000000000000000000000000000000000000000000000000000"))
CHECK(String64(STR("00000000")) == etl::to_string(uint8_t(0), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("0000000000000000")) == etl::to_string(uint16_t(0), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("00000000000000000000000000000000")) == etl::to_string(uint32_t(0), str, Format().base(2).width(32).fill(STR('0'))));
CHECK(String64(STR("0000000000000000000000000000000000000000000000000000000000000000"))
== etl::to_string(uint64_t(0), str, Format().base(2).width(64).fill(STR('0'))));
CHECK(etl::u16string<64>(STR("10000000")) == etl::to_string(uint8_t(128), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::u16string<64>(STR("1000000000000000")) == etl::to_string(uint16_t(32768), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::u16string<64>(STR("10000000000000000000000000000000"))
CHECK(String64(STR("10000000")) == etl::to_string(uint8_t(128), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("1000000000000000")) == etl::to_string(uint16_t(32768), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("10000000000000000000000000000000"))
== etl::to_string(uint32_t(2147483648ul), str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::u16string<64>(STR("1000000000000000000000000000000000000000000000000000000000000000"))
CHECK(String64(STR("1000000000000000000000000000000000000000000000000000000000000000"))
== etl::to_string(uint64_t(9223372036854775808ull), str, Format().base(2).width(64).fill(STR('0'))));
CHECK(etl::u16string<64>(STR("01111111")) == etl::to_string(INT8_MAX, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::u16string<64>(STR("0111111111111111")) == etl::to_string(INT16_MAX, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::u16string<64>(STR("01111111111111111111111111111111")) == etl::to_string(INT32_MAX, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::u16string<64>(STR("0111111111111111111111111111111111111111111111111111111111111111"))
CHECK(String64(STR("01111111")) == etl::to_string(INT8_MAX, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("0111111111111111")) == etl::to_string(INT16_MAX, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("01111111111111111111111111111111")) == etl::to_string(INT32_MAX, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(String64(STR("0111111111111111111111111111111111111111111111111111111111111111"))
== etl::to_string(INT64_MAX, str, Format().base(2).width(64).fill(STR('0'))));
CHECK(etl::u16string<64>(STR("10000000")) == etl::to_string(INT8_MIN, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::u16string<64>(STR("1000000000000000")) == etl::to_string(INT16_MIN, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::u16string<64>(STR("10000000000000000000000000000000")) == etl::to_string(INT32_MIN, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::u16string<64>(STR("1000000000000000000000000000000000000000000000000000000000000000"))
CHECK(String64(STR("10000000")) == etl::to_string(INT8_MIN, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("1000000000000000")) == etl::to_string(INT16_MIN, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("10000000000000000000000000000000")) == etl::to_string(INT32_MIN, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(String64(STR("1000000000000000000000000000000000000000000000000000000000000000"))
== etl::to_string(INT64_MIN, str, Format().base(2).width(64).fill(STR('0'))));
}
@ -257,328 +259,328 @@ namespace
//*************************************************************************
TEST(test_floating_point_no_append)
{
etl::u16string<20> str;
String20 str;
CHECK(etl::u16string<20>(STR(" 0.000000")) == etl::to_string(0.0, str, Format().precision(6).width(10).right()));
CHECK(etl::u16string<20>(STR("0.000000 ")) == etl::to_string(0.0, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 0.000000")) == etl::to_string(0.0, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("0.000000 ")) == etl::to_string(0.0, str, Format().precision(6).width(10).left()));
CHECK(etl::u16string<20>(STR(" 0.000001")) == etl::to_string(0.000001, str, Format().precision(6).width(10).right()));
CHECK(etl::u16string<20>(STR("0.000001 ")) == etl::to_string(0.000001, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 0.000001")) == etl::to_string(0.000001, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("0.000001 ")) == etl::to_string(0.000001, str, Format().precision(6).width(10).left()));
CHECK(etl::u16string<20>(STR(" 1.000000")) == etl::to_string(1.0, str, Format().precision(6).width(10).right()));
CHECK(etl::u16string<20>(STR("1.000000 ")) == etl::to_string(1.0, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 1.000000")) == etl::to_string(1.0, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("1.000000 ")) == etl::to_string(1.0, str, Format().precision(6).width(10).left()));
CHECK(etl::u16string<20>(STR(" 1.000001")) == etl::to_string(1.000001, str, Format().precision(6).width(10).right()));
CHECK(etl::u16string<20>(STR("1.000001 ")) == etl::to_string(1.000001, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 1.000001")) == etl::to_string(1.000001, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("1.000001 ")) == etl::to_string(1.000001, str, Format().precision(6).width(10).left()));
CHECK(etl::u16string<20>(STR(" 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right()));
CHECK(etl::u16string<20>(STR("12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left()));
CHECK(etl::u16string<20>(STR(" -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right()));
CHECK(etl::u16string<20>(STR("-12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left()));
CHECK(String20(STR(" -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right()));
CHECK(String20(STR("-12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left()));
CHECK(etl::u16string<20>(STR(" -0.123456")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).right()));
CHECK(etl::u16string<20>(STR("-0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" -0.123456")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("-0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left()));
}
//*************************************************************************
TEST(test_floating_point_append)
{
etl::u16string<20> str;
String20 str;
str.assign(STR("Result "));
CHECK(etl::u16string<20>(STR("Result 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right(), true));
CHECK(String20(STR("Result 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right(), true));
str.assign(STR("Result "));
CHECK(etl::u16string<20>(STR("Result 12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left(), true));
CHECK(String20(STR("Result 12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left(), true));
str.assign(STR("Result "));
CHECK(etl::u16string<20>(STR("Result -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right(), true));
CHECK(String20(STR("Result -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right(), true));
str.assign(STR("Result "));
CHECK(etl::u16string<20>(STR("Result -12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left(), true));
CHECK(String20(STR("Result -12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left(), true));
str.assign(STR("Result "));
CHECK(etl::u16string<20>(STR("Result -0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left(), true));
CHECK(String20(STR("Result -0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left(), true));
}
//*************************************************************************
TEST(test_floating_point_rounding)
{
etl::u16string<20> str;
String20 str;
CHECK(etl::u16string<20>(STR("0.00001")) == etl::to_string(0.000009, str, Format().precision(5).width(7).right()));
CHECK(etl::u16string<20>(STR("0.0001")) == etl::to_string(0.000099, str, Format().precision(4).width(6).right()));
CHECK(etl::u16string<20>(STR("0.001")) == etl::to_string(0.000999, str, Format().precision(3).width(5).right()));
CHECK(etl::u16string<20>(STR("0.01")) == etl::to_string(0.009999, str, Format().precision(2).width(4).right()));
CHECK(etl::u16string<20>(STR("0.1")) == etl::to_string(0.099999, str, Format().precision(1).width(3).right()));
CHECK(etl::u16string<20>(STR("1.0")) == etl::to_string(0.999999, str, Format().precision(1).width(3).right()));
CHECK(etl::u16string<20>(STR("1")) == etl::to_string(0.999999, str, Format().precision(0).width(1).right()));
CHECK(etl::u16string<20>(STR("2")) == etl::to_string(1.999999, str, Format().precision(0).width(1).right()));
CHECK(etl::u16string<20>(STR("10.0")) == etl::to_string(9.999999, str, Format().precision(1).width(4).right()));
CHECK(etl::u16string<20>(STR("20.0")) == etl::to_string(19.999999, str, Format().precision(1).width(4).right()));
CHECK(String20(STR("0.00001")) == etl::to_string(0.000009, str, Format().precision(5).width(7).right()));
CHECK(String20(STR("0.0001")) == etl::to_string(0.000099, str, Format().precision(4).width(6).right()));
CHECK(String20(STR("0.001")) == etl::to_string(0.000999, str, Format().precision(3).width(5).right()));
CHECK(String20(STR("0.01")) == etl::to_string(0.009999, str, Format().precision(2).width(4).right()));
CHECK(String20(STR("0.1")) == etl::to_string(0.099999, str, Format().precision(1).width(3).right()));
CHECK(String20(STR("1.0")) == etl::to_string(0.999999, str, Format().precision(1).width(3).right()));
CHECK(String20(STR("1")) == etl::to_string(0.999999, str, Format().precision(0).width(1).right()));
CHECK(String20(STR("2")) == etl::to_string(1.999999, str, Format().precision(0).width(1).right()));
CHECK(String20(STR("10.0")) == etl::to_string(9.999999, str, Format().precision(1).width(4).right()));
CHECK(String20(STR("20.0")) == etl::to_string(19.999999, str, Format().precision(1).width(4).right()));
}
//*************************************************************************
TEST(test_bool_no_append)
{
etl::u16string<20> str;
String20 str;
CHECK(etl::u16string<20>(STR(" 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(etl::u16string<20>(STR(" 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(etl::u16string<20>(STR("0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(etl::u16string<20>(STR("1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(String20(STR(" 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(String20(STR(" 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(String20(STR("0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(String20(STR("1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(etl::u16string<20>(STR(" false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(etl::u16string<20>(STR(" true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(etl::u16string<20>(STR("false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true)));
CHECK(etl::u16string<20>(STR("true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true)));
CHECK(String20(STR(" false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(String20(STR(" true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(String20(STR("false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true)));
CHECK(String20(STR("true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true)));
}
//*************************************************************************
TEST(test_bool_append)
{
etl::u16string<20> str;
String20 str;
str.assign(STR("Result "));
CHECK(etl::u16string<20>(STR("Result 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false), true));
CHECK(String20(STR("Result 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::u16string<20>(STR("Result 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false), true));
CHECK(String20(STR("Result 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::u16string<20>(STR("Result 0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false), true));
CHECK(String20(STR("Result 0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::u16string<20>(STR("Result 1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false), true));
CHECK(String20(STR("Result 1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::u16string<20>(STR("Result false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true), true));
CHECK(String20(STR("Result false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true), true));
str.assign(STR("Result "));
CHECK(etl::u16string<20>(STR("Result true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true), true));
CHECK(String20(STR("Result true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true), true));
str.assign(STR("Result "));
CHECK(etl::u16string<20>(STR("Result false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true), true));
CHECK(String20(STR("Result false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true), true));
str.assign(STR("Result "));
CHECK(etl::u16string<20>(STR("Result true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true), true));
CHECK(String20(STR("Result true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true), true));
}
//*************************************************************************
TEST(test_integer_denominator_default_format)
{
etl::u16string<20> result;
int value = -1234567;
String20 result;
int value = -1234567;
etl::to_string(value, 6U, result);
CHECK(etl::u16string<20>(STR("-1")) == result);
CHECK(String20(STR("-1")) == result);
}
//*************************************************************************
TEST(test_integer_denominator_huge_precision)
{
etl::u16string<20> result;
int value = -1234560;
String20 result;
int value = -1234560;
Format format = Format().precision(100);
etl::to_string(value, 6U, result, format);
CHECK(etl::u16string<20>(STR("-1.234560")) == result);
CHECK(String20(STR("-1.234560")) == result);
}
//*************************************************************************
TEST(test_integer_denominator_huge_precision_64bit)
{
etl::u16string<20> result;
int64_t value = INT64_MIN;
String20 result;
int64_t value = INT64_MIN;
Format format = Format().precision(100);
etl::to_string(value, 12U, result, format);
CHECK(etl::u16string<20>(STR("-9223372.036854775808")) == result);
CHECK(String20(STR("-9223372.036854775808")) == result);
}
//*************************************************************************
TEST(test_integer_denominator_zero_fractional)
{
etl::u16string<20> result_i;
int value_i = -1000000;
String20 result_i;
int value_i = -1000000;
etl::u16string<20> result_d;
double value_d = -1.000000;
String20 result_d;
double value_d = -1.000000;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u16string<20>(STR("-1.0000")) == result_i);
CHECK(String20(STR("-1.0000")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_zero_value)
{
etl::u16string<20> result_i;
int value_i = 0;
String20 result_i;
int value_i = 0;
etl::u16string<20> result_d;
double value_d = -0.000000;
String20 result_d;
double value_d = -0.000000;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u16string<20>(STR("0.0000")) == result_i);
CHECK(String20(STR("0.0000")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_zero_integral_small_fractional)
{
etl::u16string<20> result_i;
int value_i = -400;
String20 result_i;
int value_i = -400;
etl::u16string<20> result_d;
double value_d = -0.000400;
String20 result_d;
double value_d = -0.000400;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u16string<20>(STR("-0.0004")) == result_i);
CHECK(String20(STR("-0.0004")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_small_fractional)
{
etl::u16string<20> result_i;
int value_i = -123000400;
String20 result_i;
int value_i = -123000400;
etl::u16string<20> result_d;
double value_d = -123.000400;
String20 result_d;
double value_d = -123.000400;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u16string<20>(STR("-123.0004")) == result_i);
CHECK(String20(STR("-123.0004")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_very_small_fractional)
{
etl::u16string<20> result_i;
int value_i = -123000004;
String20 result_i;
int value_i = -123000004;
etl::u16string<20> result_d;
double value_d = -123.000004;
String20 result_d;
double value_d = -123.000004;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u16string<20>(STR("-123.0000")) == result_i);
CHECK(String20(STR("-123.0000")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_very_small_fractional_rounded_up)
{
etl::u16string<20> result_i;
int value_i = -123000050;
String20 result_i;
int value_i = -123000050;
etl::u16string<20> result_d;
double value_d = -123.000050;
String20 result_d;
double value_d = -123.000050;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u16string<20>(STR("-123.0001")) == result_i);
CHECK(String20(STR("-123.0001")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_shorter_width)
{
etl::u16string<20> result_i;
int value_i = -123456780;
String20 result_i;
int value_i = -123456780;
etl::u16string<20> result_d;
double value_d = -123.456780;
String20 result_d;
double value_d = -123.456780;
Format format = Format().precision(4).width(6).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u16string<20>(STR("-123.4568")) == result_i);
CHECK(String20(STR("-123.4568")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_larger_width)
{
etl::u16string<20> result_i;
int value_i = -123456780;
String20 result_i;
int value_i = -123456780;
etl::u16string<20> result_d;
double value_d = -123.456780;
String20 result_d;
double value_d = -123.456780;
Format format = Format().precision(4).width(15).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u16string<20>(STR(" -123.4568")) == result_i);
CHECK(String20(STR(" -123.4568")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_positive_rollover)
{
etl::u16string<20> result_i;
int value_i = 123999990;
String20 result_i;
int value_i = 123999990;
etl::u16string<20> result_d;
double value_d = 123.999990;
String20 result_d;
double value_d = 123.999990;
Format format = Format().precision(4).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u16string<20>(STR("124.0000")) == result_i);
CHECK(String20(STR("124.0000")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_negative_rollover)
{
etl::u16string<20> result_i;
int value_i = -123999990;
String20 result_i;
int value_i = -123999990;
etl::u16string<20> result_d;
double value_d = -123.999990;
String20 result_d;
double value_d = -123.999990;
Format format = Format().precision(4).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u16string<20>(STR("-124.0000")) == result_i);
CHECK(String20(STR("-124.0000")) == result_i);
CHECK(result_d == result_i);
}
@ -588,48 +590,48 @@ namespace
if (std::numeric_limits<double>::is_iec559)
{
// Check forced scientific formatting for smaller numbers.
etl::u16string<64> s0;
String64 s0;
etl::to_string(1000.0, s0, Format().precision(5).width(15).right().scientific(true));
CHECK(etl::u16string<64>(STR(" 1.00000e+3")) == s0);
CHECK(String64(STR(" 1.00000e+3")) == s0);
etl::to_string(1000.0, s0, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::u16string<64>(STR(" 1.00000E+3")) == s0);
CHECK(String64(STR(" 1.00000E+3")) == s0);
// Maximum double value is 1.7976931348623157e+308, which rounds to 1.79769e+308 with 5 digits of precision.
etl::u16string<64> s1;
String64 s1;
etl::to_string(std::numeric_limits<double>::max(), s1, Format().precision(5).width(15).right());
CHECK(etl::u16string<64>(STR(" 1.79769e+308")) == s1);
CHECK(String64(STR(" 1.79769e+308")) == s1);
// Negative maximum double value is -1.7976931348623157e+308, which rounds to -1.79769e+308 with 5 digits of precision.
etl::u16string<64> s2;
String64 s2;
etl::to_string(-std::numeric_limits<double>::max(), s2, Format().precision(5).width(15).right());
CHECK(etl::u16string<64>(STR(" -1.79769e+308")) == s2);
CHECK(String64(STR(" -1.79769e+308")) == s2);
}
#if ETL_USING_64BIT_TYPES
using workspace_t = etl::private_to_string::workspace_t;
// Maximum workspace_t value is 9223372036854775807.
etl::u16string<64> s3;
String64 s3;
etl::to_string(std::numeric_limits<workspace_t>::max(), s3, Format().precision(5).width(21).right());
CHECK(etl::u16string<64>(STR(" 9223372036854775807")) == s3);
CHECK(String64(STR(" 9223372036854775807")) == s3);
// Minimum workspace_t value is -9223372036854775808.
etl::u16string<64> s4;
String64 s4;
etl::to_string(std::numeric_limits<workspace_t>::min(), s4, Format().precision(5).width(21).right());
CHECK(etl::u16string<64>(STR(" -9223372036854775808")) == s4);
CHECK(String64(STR(" -9223372036854775808")) == s4);
using uworkspace_t = etl::private_to_string::uworkspace_t;
// Maximum uworkspace_t value is 18446744073709551615.
etl::u16string<64> s5;
String64 s5;
etl::to_string(std::numeric_limits<uworkspace_t>::max(), s5, Format().precision(5).width(21).right());
CHECK(etl::u16string<64>(STR(" 18446744073709551615")) == s5);
CHECK(String64(STR(" 18446744073709551615")) == s5);
// Minimum uworkspace_t value is 0.
etl::u16string<64> s6;
String64 s6;
etl::to_string(std::numeric_limits<uworkspace_t>::min(), s6, Format().precision(5).width(21).right());
CHECK(etl::u16string<64>(STR(" 0")) == s6);
CHECK(String64(STR(" 0")) == s6);
#endif
}
@ -638,30 +640,48 @@ namespace
{
if (std::numeric_limits<double>::is_iec559)
{
etl::u16string<64> s1;
String64 s1;
etl::to_string(std::numeric_limits<double>::quiet_NaN(), s1, Format().precision(5).width(15).right().scientific(true).upper_case(false));
CHECK(etl::u16string<64>(STR(" nan")) == s1);
CHECK(String64(STR(" nan")) == s1);
etl::u16string<64> s2;
String64 s2;
etl::to_string(std::numeric_limits<double>::infinity(), s2, Format().precision(5).width(15).right().scientific(true).upper_case(false));
CHECK(etl::u16string<64>(STR(" inf")) == s2);
CHECK(String64(STR(" inf")) == s2);
etl::u16string<64> s3;
String64 s3;
etl::to_string(-std::numeric_limits<double>::infinity(), s3, Format().precision(5).width(15).right().scientific(true).upper_case(false));
CHECK(etl::u16string<64>(STR(" -inf")) == s3);
CHECK(String64(STR(" -inf")) == s3);
etl::u16string<64> s4;
String64 s4;
etl::to_string(std::numeric_limits<double>::quiet_NaN(), s4, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::u16string<64>(STR(" NAN")) == s4);
CHECK(String64(STR(" NAN")) == s4);
etl::u16string<64> s5;
String64 s5;
etl::to_string(std::numeric_limits<double>::infinity(), s5, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::u16string<64>(STR(" INF")) == s5);
CHECK(String64(STR(" INF")) == s5);
etl::u16string<64> s6;
String64 s6;
etl::to_string(-std::numeric_limits<double>::infinity(), s6, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::u16string<64>(STR(" -INF")) == s6);
CHECK(String64(STR(" -INF")) == s6);
}
}
//*************************************************************************
TEST(test_issue_1593_to_string_float_uses_double_math)
{
String64 s1;
// Float
etl::to_string(3.1415927f, s1, Format().precision(4));
CHECK_TRUE(String64(STR("3.1416")) == s1);
// Double
etl::to_string(3.1415927, s1, Format().precision(4));
CHECK_TRUE(String64(STR("3.1416")) == s1);
// Long double
etl::to_string(3.1415927l, s1, Format().precision(4));
CHECK_TRUE(String64(STR("3.1416")) == s1);
}
}
} // namespace

View File

@ -42,32 +42,35 @@ namespace
{
typedef etl::u32format_spec Format;
using String20 = etl::u32string<20>;
using String64 = etl::u32string<64>;
SUITE(test_to_u32string)
{
//*************************************************************************
TEST(test_default_format_no_append)
{
etl::u32string<20> str;
String20 str;
CHECK(etl::u32string<20>(STR("0")) == etl::to_string(uint8_t(0), str));
CHECK(etl::u32string<20>(STR("0")) == etl::to_string(uint16_t(0), str));
CHECK(etl::u32string<20>(STR("0")) == etl::to_string(uint32_t(0), str));
CHECK(etl::u32string<20>(STR("0")) == etl::to_string(uint64_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint8_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint16_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint32_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint64_t(0), str));
CHECK(etl::u32string<20>(STR("128")) == etl::to_string(uint8_t(128), str));
CHECK(etl::u32string<20>(STR("32768")) == etl::to_string(uint16_t(32768), str));
CHECK(etl::u32string<20>(STR("2147483648")) == etl::to_string(uint32_t(2147483648ul), str));
CHECK(etl::u32string<20>(STR("9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str));
CHECK(String20(STR("128")) == etl::to_string(uint8_t(128), str));
CHECK(String20(STR("32768")) == etl::to_string(uint16_t(32768), str));
CHECK(String20(STR("2147483648")) == etl::to_string(uint32_t(2147483648ul), str));
CHECK(String20(STR("9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str));
CHECK(etl::u32string<20>(STR("127")) == etl::to_string(INT8_MAX, str));
CHECK(etl::u32string<20>(STR("32767")) == etl::to_string(INT16_MAX, str));
CHECK(etl::u32string<20>(STR("2147483647")) == etl::to_string(INT32_MAX, str));
CHECK(etl::u32string<20>(STR("9223372036854775807")) == etl::to_string(INT64_MAX, str));
CHECK(String20(STR("127")) == etl::to_string(INT8_MAX, str));
CHECK(String20(STR("32767")) == etl::to_string(INT16_MAX, str));
CHECK(String20(STR("2147483647")) == etl::to_string(INT32_MAX, str));
CHECK(String20(STR("9223372036854775807")) == etl::to_string(INT64_MAX, str));
CHECK(etl::u32string<20>(STR("-128")) == etl::to_string(INT8_MIN, str));
CHECK(etl::u32string<20>(STR("-32768")) == etl::to_string(INT16_MIN, str));
CHECK(etl::u32string<20>(STR("-2147483648")) == etl::to_string(INT32_MIN, str));
CHECK(etl::u32string<20>(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str));
CHECK(String20(STR("-128")) == etl::to_string(INT8_MIN, str));
CHECK(String20(STR("-32768")) == etl::to_string(INT16_MIN, str));
CHECK(String20(STR("-2147483648")) == etl::to_string(INT32_MIN, str));
CHECK(String20(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str));
}
//*************************************************************************
@ -105,88 +108,87 @@ namespace
//*************************************************************************
TEST(test_format_right_justified_no_append)
{
etl::u32string<20> str;
String20 str;
Format format = Format().base(10).width(20).fill(STR('#'));
CHECK(etl::u32string<20>(STR("###################0")) == etl::to_string(uint8_t(0), str, format));
CHECK(etl::u32string<20>(STR("###################0")) == etl::to_string(uint16_t(0), str, format));
CHECK(etl::u32string<20>(STR("###################0")) == etl::to_string(uint32_t(0), str, format));
CHECK(etl::u32string<20>(STR("###################0")) == etl::to_string(uint64_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint8_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint16_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint32_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint64_t(0), str, format));
CHECK(etl::u32string<20>(STR("#################128")) == etl::to_string(uint8_t(128), str, format));
CHECK(etl::u32string<20>(STR("###############32768")) == etl::to_string(uint16_t(32768), str, format));
CHECK(etl::u32string<20>(STR("##########2147483648")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(etl::u32string<20>(STR("#9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(String20(STR("#################128")) == etl::to_string(uint8_t(128), str, format));
CHECK(String20(STR("###############32768")) == etl::to_string(uint16_t(32768), str, format));
CHECK(String20(STR("##########2147483648")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(String20(STR("#9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(etl::u32string<20>(STR("#################127")) == etl::to_string(INT8_MAX, str, format));
CHECK(etl::u32string<20>(STR("###############32767")) == etl::to_string(INT16_MAX, str, format));
CHECK(etl::u32string<20>(STR("##########2147483647")) == etl::to_string(INT32_MAX, str, format));
CHECK(etl::u32string<20>(STR("#9223372036854775807")) == etl::to_string(INT64_MAX, str, format));
CHECK(String20(STR("#################127")) == etl::to_string(INT8_MAX, str, format));
CHECK(String20(STR("###############32767")) == etl::to_string(INT16_MAX, str, format));
CHECK(String20(STR("##########2147483647")) == etl::to_string(INT32_MAX, str, format));
CHECK(String20(STR("#9223372036854775807")) == etl::to_string(INT64_MAX, str, format));
CHECK(etl::u32string<20>(STR("################-128")) == etl::to_string(INT8_MIN, str, format));
CHECK(etl::u32string<20>(STR("##############-32768")) == etl::to_string(INT16_MIN, str, format));
CHECK(etl::u32string<20>(STR("#########-2147483648")) == etl::to_string(INT32_MIN, str, format));
CHECK(etl::u32string<20>(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
CHECK(String20(STR("################-128")) == etl::to_string(INT8_MIN, str, format));
CHECK(String20(STR("##############-32768")) == etl::to_string(INT16_MIN, str, format));
CHECK(String20(STR("#########-2147483648")) == etl::to_string(INT32_MIN, str, format));
CHECK(String20(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
}
//*************************************************************************
TEST(test_format_left_justified_no_append)
{
etl::u32string<20> str;
String20 str;
Format format = Format().base(10).width(20).fill(STR('#')).left();
CHECK(etl::u32string<20>(STR("0###################")) == etl::to_string(uint8_t(0), str, format));
CHECK(etl::u32string<20>(STR("0###################")) == etl::to_string(uint16_t(0), str, format));
CHECK(etl::u32string<20>(STR("0###################")) == etl::to_string(uint32_t(0), str, format));
CHECK(etl::u32string<20>(STR("0###################")) == etl::to_string(uint64_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint8_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint16_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint32_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint64_t(0), str, format));
CHECK(etl::u32string<20>(STR("128#################")) == etl::to_string(uint8_t(128), str, format));
CHECK(etl::u32string<20>(STR("32768###############")) == etl::to_string(uint16_t(32768), str, format));
CHECK(etl::u32string<20>(STR("2147483648##########")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(etl::u32string<20>(STR("9223372036854775808#")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(String20(STR("128#################")) == etl::to_string(uint8_t(128), str, format));
CHECK(String20(STR("32768###############")) == etl::to_string(uint16_t(32768), str, format));
CHECK(String20(STR("2147483648##########")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(String20(STR("9223372036854775808#")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(etl::u32string<20>(STR("127#################")) == etl::to_string(INT8_MAX, str, format));
CHECK(etl::u32string<20>(STR("32767###############")) == etl::to_string(INT16_MAX, str, format));
CHECK(etl::u32string<20>(STR("2147483647##########")) == etl::to_string(INT32_MAX, str, format));
CHECK(etl::u32string<20>(STR("9223372036854775807#")) == etl::to_string(INT64_MAX, str, format));
CHECK(String20(STR("127#################")) == etl::to_string(INT8_MAX, str, format));
CHECK(String20(STR("32767###############")) == etl::to_string(INT16_MAX, str, format));
CHECK(String20(STR("2147483647##########")) == etl::to_string(INT32_MAX, str, format));
CHECK(String20(STR("9223372036854775807#")) == etl::to_string(INT64_MAX, str, format));
CHECK(etl::u32string<20>(STR("-128################")) == etl::to_string(INT8_MIN, str, format));
CHECK(etl::u32string<20>(STR("-32768##############")) == etl::to_string(INT16_MIN, str, format));
CHECK(etl::u32string<20>(STR("-2147483648#########")) == etl::to_string(INT32_MIN, str, format));
CHECK(etl::u32string<20>(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
CHECK(String20(STR("-128################")) == etl::to_string(INT8_MIN, str, format));
CHECK(String20(STR("-32768##############")) == etl::to_string(INT16_MIN, str, format));
CHECK(String20(STR("-2147483648#########")) == etl::to_string(INT32_MIN, str, format));
CHECK(String20(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
}
//*************************************************************************
TEST(test_binary_format_no_append)
{
etl::u32string<64> str;
String64 str;
CHECK(etl::u32string<64>(STR("00000000")) == etl::to_string(uint8_t(0), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::u32string<64>(STR("0000000000000000")) == etl::to_string(uint16_t(0), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::u32string<64>(STR("00000000000000000000000000000000"))
== etl::to_string(uint32_t(0), str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::u32string<64>(STR("0000000000000000000000000000000000000000000000000000000000000000"))
CHECK(String64(STR("00000000")) == etl::to_string(uint8_t(0), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("0000000000000000")) == etl::to_string(uint16_t(0), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("00000000000000000000000000000000")) == etl::to_string(uint32_t(0), str, Format().base(2).width(32).fill(STR('0'))));
CHECK(String64(STR("0000000000000000000000000000000000000000000000000000000000000000"))
== etl::to_string(uint64_t(0), str, Format().base(2).width(64).fill(STR('0'))));
CHECK(etl::u32string<64>(STR("10000000")) == etl::to_string(uint8_t(128), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::u32string<64>(STR("1000000000000000")) == etl::to_string(uint16_t(32768), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::u32string<64>(STR("10000000000000000000000000000000"))
CHECK(String64(STR("10000000")) == etl::to_string(uint8_t(128), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("1000000000000000")) == etl::to_string(uint16_t(32768), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("10000000000000000000000000000000"))
== etl::to_string(uint32_t(2147483648ul), str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::u32string<64>(STR("1000000000000000000000000000000000000000000000000000000000000000"))
CHECK(String64(STR("1000000000000000000000000000000000000000000000000000000000000000"))
== etl::to_string(uint64_t(9223372036854775808ull), str, Format().base(2).width(64).fill(STR('0'))));
CHECK(etl::u32string<64>(STR("01111111")) == etl::to_string(INT8_MAX, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::u32string<64>(STR("0111111111111111")) == etl::to_string(INT16_MAX, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::u32string<64>(STR("01111111111111111111111111111111")) == etl::to_string(INT32_MAX, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::u32string<64>(STR("0111111111111111111111111111111111111111111111111111111111111111"))
CHECK(String64(STR("01111111")) == etl::to_string(INT8_MAX, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("0111111111111111")) == etl::to_string(INT16_MAX, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("01111111111111111111111111111111")) == etl::to_string(INT32_MAX, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(String64(STR("0111111111111111111111111111111111111111111111111111111111111111"))
== etl::to_string(INT64_MAX, str, Format().base(2).width(64).fill(STR('0'))));
CHECK(etl::u32string<64>(STR("10000000")) == etl::to_string(INT8_MIN, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::u32string<64>(STR("1000000000000000")) == etl::to_string(INT16_MIN, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::u32string<64>(STR("10000000000000000000000000000000")) == etl::to_string(INT32_MIN, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::u32string<64>(STR("1000000000000000000000000000000000000000000000000000000000000000"))
CHECK(String64(STR("10000000")) == etl::to_string(INT8_MIN, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("1000000000000000")) == etl::to_string(INT16_MIN, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("10000000000000000000000000000000")) == etl::to_string(INT32_MIN, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(String64(STR("1000000000000000000000000000000000000000000000000000000000000000"))
== etl::to_string(INT64_MIN, str, Format().base(2).width(64).fill(STR('0'))));
}
@ -258,329 +260,329 @@ namespace
//*************************************************************************
TEST(test_floating_point_no_append)
{
etl::u32string<20> str;
String20 str;
CHECK(etl::u32string<20>(STR(" 0.000000")) == etl::to_string(0.0, str, Format().precision(6).width(10).right()));
CHECK(etl::u32string<20>(STR("0.000000 ")) == etl::to_string(0.0, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 0.000000")) == etl::to_string(0.0, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("0.000000 ")) == etl::to_string(0.0, str, Format().precision(6).width(10).left()));
CHECK(etl::u32string<20>(STR(" 0.000001")) == etl::to_string(0.000001, str, Format().precision(6).width(10).right()));
CHECK(etl::u32string<20>(STR("0.000001 ")) == etl::to_string(0.000001, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 0.000001")) == etl::to_string(0.000001, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("0.000001 ")) == etl::to_string(0.000001, str, Format().precision(6).width(10).left()));
CHECK(etl::u32string<20>(STR(" 1.000000")) == etl::to_string(1.0, str, Format().precision(6).width(10).right()));
CHECK(etl::u32string<20>(STR("1.000000 ")) == etl::to_string(1.0, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 1.000000")) == etl::to_string(1.0, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("1.000000 ")) == etl::to_string(1.0, str, Format().precision(6).width(10).left()));
CHECK(etl::u32string<20>(STR(" 1.000001")) == etl::to_string(1.000001, str, Format().precision(6).width(10).right()));
CHECK(etl::u32string<20>(STR("1.000001 ")) == etl::to_string(1.000001, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 1.000001")) == etl::to_string(1.000001, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("1.000001 ")) == etl::to_string(1.000001, str, Format().precision(6).width(10).left()));
CHECK(etl::u32string<20>(STR(" 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right()));
CHECK(etl::u32string<20>(STR("12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left()));
CHECK(etl::u32string<20>(STR(" -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right()));
CHECK(etl::u32string<20>(STR("-12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left()));
CHECK(String20(STR(" -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right()));
CHECK(String20(STR("-12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left()));
CHECK(etl::u32string<20>(STR(" -0.123456")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).right()));
CHECK(etl::u32string<20>(STR("-0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" -0.123456")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("-0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left()));
}
//*************************************************************************
TEST(test_floating_point_append)
{
etl::u32string<20> str;
String20 str;
str.assign(STR("Result "));
CHECK(etl::u32string<20>(STR("Result 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right(), true));
CHECK(String20(STR("Result 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right(), true));
str.assign(STR("Result "));
CHECK(etl::u32string<20>(STR("Result 12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left(), true));
CHECK(String20(STR("Result 12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left(), true));
str.assign(STR("Result "));
CHECK(etl::u32string<20>(STR("Result -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right(), true));
CHECK(String20(STR("Result -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right(), true));
str.assign(STR("Result "));
CHECK(etl::u32string<20>(STR("Result -12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left(), true));
CHECK(String20(STR("Result -12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left(), true));
str.assign(STR("Result "));
CHECK(etl::u32string<20>(STR("Result -0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left(), true));
CHECK(String20(STR("Result -0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left(), true));
}
//*************************************************************************
TEST(test_floating_point_rounding)
{
etl::u32string<20> str;
String20 str;
CHECK(etl::u32string<20>(STR("0.00001")) == etl::to_string(0.000009, str, Format().precision(5).width(7).right()));
CHECK(etl::u32string<20>(STR("0.0001")) == etl::to_string(0.000099, str, Format().precision(4).width(6).right()));
CHECK(etl::u32string<20>(STR("0.001")) == etl::to_string(0.000999, str, Format().precision(3).width(5).right()));
CHECK(etl::u32string<20>(STR("0.01")) == etl::to_string(0.009999, str, Format().precision(2).width(4).right()));
CHECK(etl::u32string<20>(STR("0.1")) == etl::to_string(0.099999, str, Format().precision(1).width(3).right()));
CHECK(etl::u32string<20>(STR("1.0")) == etl::to_string(0.999999, str, Format().precision(1).width(3).right()));
CHECK(etl::u32string<20>(STR("1")) == etl::to_string(0.999999, str, Format().precision(0).width(1).right()));
CHECK(etl::u32string<20>(STR("10.0")) == etl::to_string(9.999999, str, Format().precision(1).width(4).right()));
CHECK(etl::u32string<20>(STR("2")) == etl::to_string(1.999999, str, Format().precision(0).width(1).right()));
CHECK(etl::u32string<20>(STR("10.0")) == etl::to_string(9.999999, str, Format().precision(1).width(4).right()));
CHECK(etl::u32string<20>(STR("20.0")) == etl::to_string(19.999999, str, Format().precision(1).width(4).right()));
CHECK(String20(STR("0.00001")) == etl::to_string(0.000009, str, Format().precision(5).width(7).right()));
CHECK(String20(STR("0.0001")) == etl::to_string(0.000099, str, Format().precision(4).width(6).right()));
CHECK(String20(STR("0.001")) == etl::to_string(0.000999, str, Format().precision(3).width(5).right()));
CHECK(String20(STR("0.01")) == etl::to_string(0.009999, str, Format().precision(2).width(4).right()));
CHECK(String20(STR("0.1")) == etl::to_string(0.099999, str, Format().precision(1).width(3).right()));
CHECK(String20(STR("1.0")) == etl::to_string(0.999999, str, Format().precision(1).width(3).right()));
CHECK(String20(STR("1")) == etl::to_string(0.999999, str, Format().precision(0).width(1).right()));
CHECK(String20(STR("10.0")) == etl::to_string(9.999999, str, Format().precision(1).width(4).right()));
CHECK(String20(STR("2")) == etl::to_string(1.999999, str, Format().precision(0).width(1).right()));
CHECK(String20(STR("10.0")) == etl::to_string(9.999999, str, Format().precision(1).width(4).right()));
CHECK(String20(STR("20.0")) == etl::to_string(19.999999, str, Format().precision(1).width(4).right()));
}
//*************************************************************************
TEST(test_bool_no_append)
{
etl::u32string<20> str;
String20 str;
CHECK(etl::u32string<20>(STR(" 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(etl::u32string<20>(STR(" 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(etl::u32string<20>(STR("0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(etl::u32string<20>(STR("1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(String20(STR(" 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(String20(STR(" 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(String20(STR("0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(String20(STR("1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(etl::u32string<20>(STR(" false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(etl::u32string<20>(STR(" true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(etl::u32string<20>(STR("false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true)));
CHECK(etl::u32string<20>(STR("true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true)));
CHECK(String20(STR(" false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(String20(STR(" true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(String20(STR("false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true)));
CHECK(String20(STR("true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true)));
}
//*************************************************************************
TEST(test_bool_append)
{
etl::u32string<20> str;
String20 str;
str.assign(STR("Result "));
CHECK(etl::u32string<20>(STR("Result 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false), true));
CHECK(String20(STR("Result 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::u32string<20>(STR("Result 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false), true));
CHECK(String20(STR("Result 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::u32string<20>(STR("Result 0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false), true));
CHECK(String20(STR("Result 0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::u32string<20>(STR("Result 1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false), true));
CHECK(String20(STR("Result 1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::u32string<20>(STR("Result false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true), true));
CHECK(String20(STR("Result false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true), true));
str.assign(STR("Result "));
CHECK(etl::u32string<20>(STR("Result true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true), true));
CHECK(String20(STR("Result true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true), true));
str.assign(STR("Result "));
CHECK(etl::u32string<20>(STR("Result false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true), true));
CHECK(String20(STR("Result false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true), true));
str.assign(STR("Result "));
CHECK(etl::u32string<20>(STR("Result true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true), true));
CHECK(String20(STR("Result true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true), true));
}
//*************************************************************************
TEST(test_integer_denominator_default_format)
{
etl::u32string<20> result;
int value = -1234567;
String20 result;
int value = -1234567;
etl::to_string(value, 6U, result);
CHECK(etl::u32string<20>(STR("-1")) == result);
CHECK(String20(STR("-1")) == result);
}
//*************************************************************************
TEST(test_integer_denominator_huge_precision)
{
etl::u32string<20> result;
int value = -1234560;
String20 result;
int value = -1234560;
Format format = Format().precision(100);
etl::to_string(value, 6U, result, format);
CHECK(etl::u32string<20>(STR("-1.234560")) == result);
CHECK(String20(STR("-1.234560")) == result);
}
//*************************************************************************
TEST(test_integer_denominator_huge_precision_64bit)
{
etl::u32string<20> result;
int64_t value = INT64_MIN;
String20 result;
int64_t value = INT64_MIN;
Format format = Format().precision(100);
etl::to_string(value, 12U, result, format);
CHECK(etl::u32string<20>(STR("-9223372.036854775808")) == result);
CHECK(String20(STR("-9223372.036854775808")) == result);
}
//*************************************************************************
TEST(test_integer_denominator_zero_fractional)
{
etl::u32string<20> result_i;
int value_i = -1000000;
String20 result_i;
int value_i = -1000000;
etl::u32string<20> result_d;
double value_d = -1.000000;
String20 result_d;
double value_d = -1.000000;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u32string<20>(STR("-1.0000")) == result_i);
CHECK(String20(STR("-1.0000")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_zero_value)
{
etl::u32string<20> result_i;
int value_i = 0;
String20 result_i;
int value_i = 0;
etl::u32string<20> result_d;
double value_d = -0.000000;
String20 result_d;
double value_d = -0.000000;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u32string<20>(STR("0.0000")) == result_i);
CHECK(String20(STR("0.0000")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_zero_integral_small_fractional)
{
etl::u32string<20> result_i;
int value_i = -400;
String20 result_i;
int value_i = -400;
etl::u32string<20> result_d;
double value_d = -0.000400;
String20 result_d;
double value_d = -0.000400;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u32string<20>(STR("-0.0004")) == result_i);
CHECK(String20(STR("-0.0004")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_small_fractional)
{
etl::u32string<20> result_i;
int value_i = -123000400;
String20 result_i;
int value_i = -123000400;
etl::u32string<20> result_d;
double value_d = -123.000400;
String20 result_d;
double value_d = -123.000400;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u32string<20>(STR("-123.0004")) == result_i);
CHECK(String20(STR("-123.0004")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_very_small_fractional)
{
etl::u32string<20> result_i;
int value_i = -123000004;
String20 result_i;
int value_i = -123000004;
etl::u32string<20> result_d;
double value_d = -123.000004;
String20 result_d;
double value_d = -123.000004;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u32string<20>(STR("-123.0000")) == result_i);
CHECK(String20(STR("-123.0000")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_very_small_fractional_rounded_up)
{
etl::u32string<20> result_i;
int value_i = -123000050;
String20 result_i;
int value_i = -123000050;
etl::u32string<20> result_d;
double value_d = -123.000050;
String20 result_d;
double value_d = -123.000050;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u32string<20>(STR("-123.0001")) == result_i);
CHECK(String20(STR("-123.0001")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_shorter_width)
{
etl::u32string<20> result_i;
int value_i = -123456780;
String20 result_i;
int value_i = -123456780;
etl::u32string<20> result_d;
double value_d = -123.456780;
String20 result_d;
double value_d = -123.456780;
Format format = Format().precision(4).width(6).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u32string<20>(STR("-123.4568")) == result_i);
CHECK(String20(STR("-123.4568")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_larger_width)
{
etl::u32string<20> result_i;
int value_i = -123456780;
String20 result_i;
int value_i = -123456780;
etl::u32string<20> result_d;
double value_d = -123.456780;
String20 result_d;
double value_d = -123.456780;
Format format = Format().precision(4).width(15).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u32string<20>(STR(" -123.4568")) == result_i);
CHECK(String20(STR(" -123.4568")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_positive_rollover)
{
etl::u32string<20> result_i;
int value_i = 123999990;
String20 result_i;
int value_i = 123999990;
etl::u32string<20> result_d;
double value_d = 123.999990;
String20 result_d;
double value_d = 123.999990;
Format format = Format().precision(4).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u32string<20>(STR("124.0000")) == result_i);
CHECK(String20(STR("124.0000")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_negative_rollover)
{
etl::u32string<20> result_i;
int value_i = -123999990;
String20 result_i;
int value_i = -123999990;
etl::u32string<20> result_d;
double value_d = -123.999990;
String20 result_d;
double value_d = -123.999990;
Format format = Format().precision(4).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u32string<20>(STR("-124.0000")) == result_i);
CHECK(String20(STR("-124.0000")) == result_i);
CHECK(result_d == result_i);
}
@ -590,48 +592,48 @@ namespace
if (std::numeric_limits<double>::is_iec559)
{
// Check forced scientific formatting for smaller numbers.
etl::u32string<64> s0;
String64 s0;
etl::to_string(1000.0, s0, Format().precision(5).width(15).right().scientific(true));
CHECK(etl::u32string<64>(STR(" 1.00000e+3")) == s0);
CHECK(String64(STR(" 1.00000e+3")) == s0);
etl::to_string(1000.0, s0, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::u32string<64>(STR(" 1.00000E+3")) == s0);
CHECK(String64(STR(" 1.00000E+3")) == s0);
// Maximum double value is 1.7976931348623157e+308, which rounds to 1.79769e+308 with 5 digits of precision.
etl::u32string<64> s1;
String64 s1;
etl::to_string(std::numeric_limits<double>::max(), s1, Format().precision(5).width(15).right());
CHECK(etl::u32string<64>(STR(" 1.79769e+308")) == s1);
CHECK(String64(STR(" 1.79769e+308")) == s1);
// Negative maximum double value is -1.7976931348623157e+308, which rounds to -1.79769e+308 with 5 digits of precision.
etl::u32string<64> s2;
String64 s2;
etl::to_string(-std::numeric_limits<double>::max(), s2, Format().precision(5).width(15).right());
CHECK(etl::u32string<64>(STR(" -1.79769e+308")) == s2);
CHECK(String64(STR(" -1.79769e+308")) == s2);
}
#if ETL_USING_64BIT_TYPES
using workspace_t = etl::private_to_string::workspace_t;
// Maximum workspace_t value is 9223372036854775807.
etl::u32string<64> s3;
String64 s3;
etl::to_string(std::numeric_limits<workspace_t>::max(), s3, Format().precision(5).width(21).right());
CHECK(etl::u32string<64>(STR(" 9223372036854775807")) == s3);
CHECK(String64(STR(" 9223372036854775807")) == s3);
// Minimum workspace_t value is -9223372036854775808.
etl::u32string<64> s4;
String64 s4;
etl::to_string(std::numeric_limits<workspace_t>::min(), s4, Format().precision(5).width(21).right());
CHECK(etl::u32string<64>(STR(" -9223372036854775808")) == s4);
CHECK(String64(STR(" -9223372036854775808")) == s4);
using uworkspace_t = etl::private_to_string::uworkspace_t;
// Maximum uworkspace_t value is 18446744073709551615.
etl::u32string<64> s5;
String64 s5;
etl::to_string(std::numeric_limits<uworkspace_t>::max(), s5, Format().precision(5).width(21).right());
CHECK(etl::u32string<64>(STR(" 18446744073709551615")) == s5);
CHECK(String64(STR(" 18446744073709551615")) == s5);
// Minimum uworkspace_t value is 0.
etl::u32string<64> s6;
String64 s6;
etl::to_string(std::numeric_limits<uworkspace_t>::min(), s6, Format().precision(5).width(21).right());
CHECK(etl::u32string<64>(STR(" 0")) == s6);
CHECK(String64(STR(" 0")) == s6);
#endif
}
@ -640,30 +642,48 @@ namespace
{
if (std::numeric_limits<double>::is_iec559)
{
etl::u32string<64> s1;
String64 s1;
etl::to_string(std::numeric_limits<double>::quiet_NaN(), s1, Format().precision(5).width(15).right().scientific(true).upper_case(false));
CHECK(etl::u32string<64>(STR(" nan")) == s1);
CHECK(String64(STR(" nan")) == s1);
etl::u32string<64> s2;
String64 s2;
etl::to_string(std::numeric_limits<double>::infinity(), s2, Format().precision(5).width(15).right().scientific(true).upper_case(false));
CHECK(etl::u32string<64>(STR(" inf")) == s2);
CHECK(String64(STR(" inf")) == s2);
etl::u32string<64> s3;
String64 s3;
etl::to_string(-std::numeric_limits<double>::infinity(), s3, Format().precision(5).width(15).right().scientific(true).upper_case(false));
CHECK(etl::u32string<64>(STR(" -inf")) == s3);
CHECK(String64(STR(" -inf")) == s3);
etl::u32string<64> s4;
String64 s4;
etl::to_string(std::numeric_limits<double>::quiet_NaN(), s4, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::u32string<64>(STR(" NAN")) == s4);
CHECK(String64(STR(" NAN")) == s4);
etl::u32string<64> s5;
String64 s5;
etl::to_string(std::numeric_limits<double>::infinity(), s5, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::u32string<64>(STR(" INF")) == s5);
CHECK(String64(STR(" INF")) == s5);
etl::u32string<64> s6;
String64 s6;
etl::to_string(-std::numeric_limits<double>::infinity(), s6, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::u32string<64>(STR(" -INF")) == s6);
CHECK(String64(STR(" -INF")) == s6);
}
}
//*************************************************************************
TEST(test_issue_1593_to_string_float_uses_double_math)
{
String64 s1;
// Float
etl::to_string(3.1415927f, s1, Format().precision(4));
CHECK_TRUE(String64(STR("3.1416")) == s1);
// Double
etl::to_string(3.1415927, s1, Format().precision(4));
CHECK_TRUE(String64(STR("3.1416")) == s1);
// Long double
etl::to_string(3.1415927l, s1, Format().precision(4));
CHECK_TRUE(String64(STR("3.1416")) == s1);
}
}
} // namespace

View File

@ -43,32 +43,35 @@ namespace
{
typedef etl::u8format_spec Format;
using String20 = etl::u8string<20>;
using String64 = etl::u8string<64>;
SUITE(test_to_u8string)
{
//*************************************************************************
TEST(test_default_format_no_append)
{
etl::u8string<20> str;
String20 str;
CHECK(etl::u8string<20>(STR("0")) == etl::to_string(uint8_t(0), str));
CHECK(etl::u8string<20>(STR("0")) == etl::to_string(uint16_t(0), str));
CHECK(etl::u8string<20>(STR("0")) == etl::to_string(uint32_t(0), str));
CHECK(etl::u8string<20>(STR("0")) == etl::to_string(uint64_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint8_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint16_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint32_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint64_t(0), str));
CHECK(etl::u8string<20>(STR("128")) == etl::to_string(uint8_t(128), str));
CHECK(etl::u8string<20>(STR("32768")) == etl::to_string(uint16_t(32768), str));
CHECK(etl::u8string<20>(STR("2147483648")) == etl::to_string(uint32_t(2147483648ul), str));
CHECK(etl::u8string<20>(STR("9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str));
CHECK(String20(STR("128")) == etl::to_string(uint8_t(128), str));
CHECK(String20(STR("32768")) == etl::to_string(uint16_t(32768), str));
CHECK(String20(STR("2147483648")) == etl::to_string(uint32_t(2147483648ul), str));
CHECK(String20(STR("9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str));
CHECK(etl::u8string<20>(STR("127")) == etl::to_string(INT8_MAX, str));
CHECK(etl::u8string<20>(STR("32767")) == etl::to_string(INT16_MAX, str));
CHECK(etl::u8string<20>(STR("2147483647")) == etl::to_string(INT32_MAX, str));
CHECK(etl::u8string<20>(STR("9223372036854775807")) == etl::to_string(INT64_MAX, str));
CHECK(String20(STR("127")) == etl::to_string(INT8_MAX, str));
CHECK(String20(STR("32767")) == etl::to_string(INT16_MAX, str));
CHECK(String20(STR("2147483647")) == etl::to_string(INT32_MAX, str));
CHECK(String20(STR("9223372036854775807")) == etl::to_string(INT64_MAX, str));
CHECK(etl::u8string<20>(STR("-128")) == etl::to_string(INT8_MIN, str));
CHECK(etl::u8string<20>(STR("-32768")) == etl::to_string(INT16_MIN, str));
CHECK(etl::u8string<20>(STR("-2147483648")) == etl::to_string(INT32_MIN, str));
CHECK(etl::u8string<20>(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str));
CHECK(String20(STR("-128")) == etl::to_string(INT8_MIN, str));
CHECK(String20(STR("-32768")) == etl::to_string(INT16_MIN, str));
CHECK(String20(STR("-2147483648")) == etl::to_string(INT32_MIN, str));
CHECK(String20(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str));
}
//*************************************************************************
@ -106,88 +109,87 @@ namespace
//*************************************************************************
TEST(test_format_right_justified_no_append)
{
etl::u8string<20> str;
String20 str;
Format format = Format().base(10).width(20).fill(STR('#'));
CHECK(etl::u8string<20>(STR("###################0")) == etl::to_string(uint8_t(0), str, format));
CHECK(etl::u8string<20>(STR("###################0")) == etl::to_string(uint16_t(0), str, format));
CHECK(etl::u8string<20>(STR("###################0")) == etl::to_string(uint32_t(0), str, format));
CHECK(etl::u8string<20>(STR("###################0")) == etl::to_string(uint64_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint8_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint16_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint32_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint64_t(0), str, format));
CHECK(etl::u8string<20>(STR("#################128")) == etl::to_string(uint8_t(128), str, format));
CHECK(etl::u8string<20>(STR("###############32768")) == etl::to_string(uint16_t(32768), str, format));
CHECK(etl::u8string<20>(STR("##########2147483648")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(etl::u8string<20>(STR("#9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(String20(STR("#################128")) == etl::to_string(uint8_t(128), str, format));
CHECK(String20(STR("###############32768")) == etl::to_string(uint16_t(32768), str, format));
CHECK(String20(STR("##########2147483648")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(String20(STR("#9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(etl::u8string<20>(STR("#################127")) == etl::to_string(INT8_MAX, str, format));
CHECK(etl::u8string<20>(STR("###############32767")) == etl::to_string(INT16_MAX, str, format));
CHECK(etl::u8string<20>(STR("##########2147483647")) == etl::to_string(INT32_MAX, str, format));
CHECK(etl::u8string<20>(STR("#9223372036854775807")) == etl::to_string(INT64_MAX, str, format));
CHECK(String20(STR("#################127")) == etl::to_string(INT8_MAX, str, format));
CHECK(String20(STR("###############32767")) == etl::to_string(INT16_MAX, str, format));
CHECK(String20(STR("##########2147483647")) == etl::to_string(INT32_MAX, str, format));
CHECK(String20(STR("#9223372036854775807")) == etl::to_string(INT64_MAX, str, format));
CHECK(etl::u8string<20>(STR("################-128")) == etl::to_string(INT8_MIN, str, format));
CHECK(etl::u8string<20>(STR("##############-32768")) == etl::to_string(INT16_MIN, str, format));
CHECK(etl::u8string<20>(STR("#########-2147483648")) == etl::to_string(INT32_MIN, str, format));
CHECK(etl::u8string<20>(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
CHECK(String20(STR("################-128")) == etl::to_string(INT8_MIN, str, format));
CHECK(String20(STR("##############-32768")) == etl::to_string(INT16_MIN, str, format));
CHECK(String20(STR("#########-2147483648")) == etl::to_string(INT32_MIN, str, format));
CHECK(String20(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
}
//*************************************************************************
TEST(test_format_left_justified_no_append)
{
etl::u8string<20> str;
String20 str;
Format format = Format().base(10).width(20).fill(STR('#')).left();
CHECK(etl::u8string<20>(STR("0###################")) == etl::to_string(uint8_t(0), str, format));
CHECK(etl::u8string<20>(STR("0###################")) == etl::to_string(uint16_t(0), str, format));
CHECK(etl::u8string<20>(STR("0###################")) == etl::to_string(uint32_t(0), str, format));
CHECK(etl::u8string<20>(STR("0###################")) == etl::to_string(uint64_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint8_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint16_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint32_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint64_t(0), str, format));
CHECK(etl::u8string<20>(STR("128#################")) == etl::to_string(uint8_t(128), str, format));
CHECK(etl::u8string<20>(STR("32768###############")) == etl::to_string(uint16_t(32768), str, format));
CHECK(etl::u8string<20>(STR("2147483648##########")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(etl::u8string<20>(STR("9223372036854775808#")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(String20(STR("128#################")) == etl::to_string(uint8_t(128), str, format));
CHECK(String20(STR("32768###############")) == etl::to_string(uint16_t(32768), str, format));
CHECK(String20(STR("2147483648##########")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(String20(STR("9223372036854775808#")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(etl::u8string<20>(STR("127#################")) == etl::to_string(INT8_MAX, str, format));
CHECK(etl::u8string<20>(STR("32767###############")) == etl::to_string(INT16_MAX, str, format));
CHECK(etl::u8string<20>(STR("2147483647##########")) == etl::to_string(INT32_MAX, str, format));
CHECK(etl::u8string<20>(STR("9223372036854775807#")) == etl::to_string(INT64_MAX, str, format));
CHECK(String20(STR("127#################")) == etl::to_string(INT8_MAX, str, format));
CHECK(String20(STR("32767###############")) == etl::to_string(INT16_MAX, str, format));
CHECK(String20(STR("2147483647##########")) == etl::to_string(INT32_MAX, str, format));
CHECK(String20(STR("9223372036854775807#")) == etl::to_string(INT64_MAX, str, format));
CHECK(etl::u8string<20>(STR("-128################")) == etl::to_string(INT8_MIN, str, format));
CHECK(etl::u8string<20>(STR("-32768##############")) == etl::to_string(INT16_MIN, str, format));
CHECK(etl::u8string<20>(STR("-2147483648#########")) == etl::to_string(INT32_MIN, str, format));
CHECK(etl::u8string<20>(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
CHECK(String20(STR("-128################")) == etl::to_string(INT8_MIN, str, format));
CHECK(String20(STR("-32768##############")) == etl::to_string(INT16_MIN, str, format));
CHECK(String20(STR("-2147483648#########")) == etl::to_string(INT32_MIN, str, format));
CHECK(String20(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
}
//*************************************************************************
TEST(test_binary_format_no_append)
{
etl::u8string<64> str;
String64 str;
CHECK(etl::u8string<64>(STR("00000000")) == etl::to_string(uint8_t(0), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::u8string<64>(STR("0000000000000000")) == etl::to_string(uint16_t(0), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::u8string<64>(STR("00000000000000000000000000000000"))
== etl::to_string(uint32_t(0), str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::u8string<64>(STR("0000000000000000000000000000000000000000000000000000000000000000"))
CHECK(String64(STR("00000000")) == etl::to_string(uint8_t(0), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("0000000000000000")) == etl::to_string(uint16_t(0), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("00000000000000000000000000000000")) == etl::to_string(uint32_t(0), str, Format().base(2).width(32).fill(STR('0'))));
CHECK(String64(STR("0000000000000000000000000000000000000000000000000000000000000000"))
== etl::to_string(uint64_t(0), str, Format().base(2).width(64).fill(STR('0'))));
CHECK(etl::u8string<64>(STR("10000000")) == etl::to_string(uint8_t(128), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::u8string<64>(STR("1000000000000000")) == etl::to_string(uint16_t(32768), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::u8string<64>(STR("10000000000000000000000000000000"))
CHECK(String64(STR("10000000")) == etl::to_string(uint8_t(128), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("1000000000000000")) == etl::to_string(uint16_t(32768), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("10000000000000000000000000000000"))
== etl::to_string(uint32_t(2147483648ul), str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::u8string<64>(STR("1000000000000000000000000000000000000000000000000000000000000000"))
CHECK(String64(STR("1000000000000000000000000000000000000000000000000000000000000000"))
== etl::to_string(uint64_t(9223372036854775808ull), str, Format().base(2).width(64).fill(STR('0'))));
CHECK(etl::u8string<64>(STR("01111111")) == etl::to_string(INT8_MAX, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::u8string<64>(STR("0111111111111111")) == etl::to_string(INT16_MAX, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::u8string<64>(STR("01111111111111111111111111111111")) == etl::to_string(INT32_MAX, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::u8string<64>(STR("0111111111111111111111111111111111111111111111111111111111111111"))
CHECK(String64(STR("01111111")) == etl::to_string(INT8_MAX, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("0111111111111111")) == etl::to_string(INT16_MAX, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("01111111111111111111111111111111")) == etl::to_string(INT32_MAX, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(String64(STR("0111111111111111111111111111111111111111111111111111111111111111"))
== etl::to_string(INT64_MAX, str, Format().base(2).width(64).fill(STR('0'))));
CHECK(etl::u8string<64>(STR("10000000")) == etl::to_string(INT8_MIN, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::u8string<64>(STR("1000000000000000")) == etl::to_string(INT16_MIN, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::u8string<64>(STR("10000000000000000000000000000000")) == etl::to_string(INT32_MIN, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::u8string<64>(STR("1000000000000000000000000000000000000000000000000000000000000000"))
CHECK(String64(STR("10000000")) == etl::to_string(INT8_MIN, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("1000000000000000")) == etl::to_string(INT16_MIN, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("10000000000000000000000000000000")) == etl::to_string(INT32_MIN, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(String64(STR("1000000000000000000000000000000000000000000000000000000000000000"))
== etl::to_string(INT64_MIN, str, Format().base(2).width(64).fill(STR('0'))));
}
@ -259,328 +261,328 @@ namespace
//*************************************************************************
TEST(test_floating_point_no_append)
{
etl::u8string<20> str;
String20 str;
CHECK(etl::u8string<20>(STR(" 0.000000")) == etl::to_string(0.0, str, Format().precision(6).width(10).right()));
CHECK(etl::u8string<20>(STR("0.000000 ")) == etl::to_string(0.0, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 0.000000")) == etl::to_string(0.0, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("0.000000 ")) == etl::to_string(0.0, str, Format().precision(6).width(10).left()));
CHECK(etl::u8string<20>(STR(" 0.000001")) == etl::to_string(0.000001, str, Format().precision(6).width(10).right()));
CHECK(etl::u8string<20>(STR("0.000001 ")) == etl::to_string(0.000001, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 0.000001")) == etl::to_string(0.000001, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("0.000001 ")) == etl::to_string(0.000001, str, Format().precision(6).width(10).left()));
CHECK(etl::u8string<20>(STR(" 1.000000")) == etl::to_string(1.0, str, Format().precision(6).width(10).right()));
CHECK(etl::u8string<20>(STR("1.000000 ")) == etl::to_string(1.0, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 1.000000")) == etl::to_string(1.0, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("1.000000 ")) == etl::to_string(1.0, str, Format().precision(6).width(10).left()));
CHECK(etl::u8string<20>(STR(" 1.000001")) == etl::to_string(1.000001, str, Format().precision(6).width(10).right()));
CHECK(etl::u8string<20>(STR("1.000001 ")) == etl::to_string(1.000001, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 1.000001")) == etl::to_string(1.000001, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("1.000001 ")) == etl::to_string(1.000001, str, Format().precision(6).width(10).left()));
CHECK(etl::u8string<20>(STR(" 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right()));
CHECK(etl::u8string<20>(STR("12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left()));
CHECK(etl::u8string<20>(STR(" -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right()));
CHECK(etl::u8string<20>(STR("-12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left()));
CHECK(String20(STR(" -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right()));
CHECK(String20(STR("-12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left()));
CHECK(etl::u8string<20>(STR(" -0.123456")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).right()));
CHECK(etl::u8string<20>(STR("-0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" -0.123456")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("-0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left()));
}
//*************************************************************************
TEST(test_floating_point_append)
{
etl::u8string<20> str;
String20 str;
str.assign(STR("Result "));
CHECK(etl::u8string<20>(STR("Result 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right(), true));
CHECK(String20(STR("Result 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right(), true));
str.assign(STR("Result "));
CHECK(etl::u8string<20>(STR("Result 12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left(), true));
CHECK(String20(STR("Result 12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left(), true));
str.assign(STR("Result "));
CHECK(etl::u8string<20>(STR("Result -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right(), true));
CHECK(String20(STR("Result -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right(), true));
str.assign(STR("Result "));
CHECK(etl::u8string<20>(STR("Result -12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left(), true));
CHECK(String20(STR("Result -12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left(), true));
str.assign(STR("Result "));
CHECK(etl::u8string<20>(STR("Result -0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left(), true));
CHECK(String20(STR("Result -0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left(), true));
}
//*************************************************************************
TEST(test_floating_point_rounding)
{
etl::u8string<20> str;
String20 str;
CHECK(etl::u8string<20>(STR("0.00001")) == etl::to_string(0.000009, str, Format().precision(5).width(7).right()));
CHECK(etl::u8string<20>(STR("0.0001")) == etl::to_string(0.000099, str, Format().precision(4).width(6).right()));
CHECK(etl::u8string<20>(STR("0.001")) == etl::to_string(0.000999, str, Format().precision(3).width(5).right()));
CHECK(etl::u8string<20>(STR("0.01")) == etl::to_string(0.009999, str, Format().precision(2).width(4).right()));
CHECK(etl::u8string<20>(STR("0.1")) == etl::to_string(0.099999, str, Format().precision(1).width(3).right()));
CHECK(etl::u8string<20>(STR("1.0")) == etl::to_string(0.999999, str, Format().precision(1).width(3).right()));
CHECK(etl::u8string<20>(STR("1")) == etl::to_string(0.999999, str, Format().precision(0).width(1).right()));
CHECK(etl::u8string<20>(STR("2")) == etl::to_string(1.999999, str, Format().precision(0).width(1).right()));
CHECK(etl::u8string<20>(STR("10.0")) == etl::to_string(9.999999, str, Format().precision(1).width(4).right()));
CHECK(etl::u8string<20>(STR("20.0")) == etl::to_string(19.999999, str, Format().precision(1).width(4).right()));
CHECK(String20(STR("0.00001")) == etl::to_string(0.000009, str, Format().precision(5).width(7).right()));
CHECK(String20(STR("0.0001")) == etl::to_string(0.000099, str, Format().precision(4).width(6).right()));
CHECK(String20(STR("0.001")) == etl::to_string(0.000999, str, Format().precision(3).width(5).right()));
CHECK(String20(STR("0.01")) == etl::to_string(0.009999, str, Format().precision(2).width(4).right()));
CHECK(String20(STR("0.1")) == etl::to_string(0.099999, str, Format().precision(1).width(3).right()));
CHECK(String20(STR("1.0")) == etl::to_string(0.999999, str, Format().precision(1).width(3).right()));
CHECK(String20(STR("1")) == etl::to_string(0.999999, str, Format().precision(0).width(1).right()));
CHECK(String20(STR("2")) == etl::to_string(1.999999, str, Format().precision(0).width(1).right()));
CHECK(String20(STR("10.0")) == etl::to_string(9.999999, str, Format().precision(1).width(4).right()));
CHECK(String20(STR("20.0")) == etl::to_string(19.999999, str, Format().precision(1).width(4).right()));
}
//*************************************************************************
TEST(test_bool_no_append)
{
etl::u8string<20> str;
String20 str;
CHECK(etl::u8string<20>(STR(" 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(etl::u8string<20>(STR(" 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(etl::u8string<20>(STR("0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(etl::u8string<20>(STR("1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(String20(STR(" 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(String20(STR(" 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(String20(STR("0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(String20(STR("1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(etl::u8string<20>(STR(" false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(etl::u8string<20>(STR(" true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(etl::u8string<20>(STR("false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true)));
CHECK(etl::u8string<20>(STR("true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true)));
CHECK(String20(STR(" false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(String20(STR(" true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(String20(STR("false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true)));
CHECK(String20(STR("true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true)));
}
//*************************************************************************
TEST(test_bool_append)
{
etl::u8string<20> str;
String20 str;
str.assign(STR("Result "));
CHECK(etl::u8string<20>(STR("Result 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false), true));
CHECK(String20(STR("Result 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::u8string<20>(STR("Result 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false), true));
CHECK(String20(STR("Result 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::u8string<20>(STR("Result 0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false), true));
CHECK(String20(STR("Result 0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::u8string<20>(STR("Result 1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false), true));
CHECK(String20(STR("Result 1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::u8string<20>(STR("Result false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true), true));
CHECK(String20(STR("Result false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true), true));
str.assign(STR("Result "));
CHECK(etl::u8string<20>(STR("Result true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true), true));
CHECK(String20(STR("Result true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true), true));
str.assign(STR("Result "));
CHECK(etl::u8string<20>(STR("Result false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true), true));
CHECK(String20(STR("Result false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true), true));
str.assign(STR("Result "));
CHECK(etl::u8string<20>(STR("Result true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true), true));
CHECK(String20(STR("Result true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true), true));
}
//*************************************************************************
TEST(test_integer_denominator_default_format)
{
etl::u8string<20> result;
int value = -1234567;
String20 result;
int value = -1234567;
etl::to_string(value, 6U, result);
CHECK(etl::u8string<20>(STR("-1")) == result);
CHECK(String20(STR("-1")) == result);
}
//*************************************************************************
TEST(test_integer_denominator_huge_precision)
{
etl::u8string<20> result;
int value = -1234560;
String20 result;
int value = -1234560;
Format format = Format().precision(100);
etl::to_string(value, 6U, result, format);
CHECK(etl::u8string<20>(STR("-1.234560")) == result);
CHECK(String20(STR("-1.234560")) == result);
}
//*************************************************************************
TEST(test_integer_denominator_huge_precision_64bit)
{
etl::u8string<20> result;
int64_t value = INT64_MIN;
String20 result;
int64_t value = INT64_MIN;
Format format = Format().precision(100);
etl::to_string(value, 12U, result, format);
CHECK(etl::u8string<20>(STR("-9223372.036854775808")) == result);
CHECK(String20(STR("-9223372.036854775808")) == result);
}
//*************************************************************************
TEST(test_integer_denominator_zero_fractional)
{
etl::u8string<20> result_i;
int value_i = -1000000;
String20 result_i;
int value_i = -1000000;
etl::u8string<20> result_d;
double value_d = -1.000000;
String20 result_d;
double value_d = -1.000000;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u8string<20>(STR("-1.0000")) == result_i);
CHECK(String20(STR("-1.0000")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_zero_value)
{
etl::u8string<20> result_i;
int value_i = 0;
String20 result_i;
int value_i = 0;
etl::u8string<20> result_d;
double value_d = -0.000000;
String20 result_d;
double value_d = -0.000000;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u8string<20>(STR("0.0000")) == result_i);
CHECK(String20(STR("0.0000")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_zero_integral_small_fractional)
{
etl::u8string<20> result_i;
int value_i = -400;
String20 result_i;
int value_i = -400;
etl::u8string<20> result_d;
double value_d = -0.000400;
String20 result_d;
double value_d = -0.000400;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u8string<20>(STR("-0.0004")) == result_i);
CHECK(String20(STR("-0.0004")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_small_fractional)
{
etl::u8string<20> result_i;
int value_i = -123000400;
String20 result_i;
int value_i = -123000400;
etl::u8string<20> result_d;
double value_d = -123.000400;
String20 result_d;
double value_d = -123.000400;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u8string<20>(STR("-123.0004")) == result_i);
CHECK(String20(STR("-123.0004")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_very_small_fractional)
{
etl::u8string<20> result_i;
int value_i = -123000004;
String20 result_i;
int value_i = -123000004;
etl::u8string<20> result_d;
double value_d = -123.000004;
String20 result_d;
double value_d = -123.000004;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u8string<20>(STR("-123.0000")) == result_i);
CHECK(String20(STR("-123.0000")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_very_small_fractional_rounded_up)
{
etl::u8string<20> result_i;
int value_i = -123000050;
String20 result_i;
int value_i = -123000050;
etl::u8string<20> result_d;
double value_d = -123.000050;
String20 result_d;
double value_d = -123.000050;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u8string<20>(STR("-123.0001")) == result_i);
CHECK(String20(STR("-123.0001")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_shorter_width)
{
etl::u8string<20> result_i;
int value_i = -123456780;
String20 result_i;
int value_i = -123456780;
etl::u8string<20> result_d;
double value_d = -123.456780;
String20 result_d;
double value_d = -123.456780;
Format format = Format().precision(4).width(6).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u8string<20>(STR("-123.4568")) == result_i);
CHECK(String20(STR("-123.4568")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_larger_width)
{
etl::u8string<20> result_i;
int value_i = -123456780;
String20 result_i;
int value_i = -123456780;
etl::u8string<20> result_d;
double value_d = -123.456780;
String20 result_d;
double value_d = -123.456780;
Format format = Format().precision(4).width(15).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u8string<20>(STR(" -123.4568")) == result_i);
CHECK(String20(STR(" -123.4568")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_positive_rollover)
{
etl::u8string<20> result_i;
int value_i = 123999990;
String20 result_i;
int value_i = 123999990;
etl::u8string<20> result_d;
double value_d = 123.999990;
String20 result_d;
double value_d = 123.999990;
Format format = Format().precision(4).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u8string<20>(STR("124.0000")) == result_i);
CHECK(String20(STR("124.0000")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_negative_rollover)
{
etl::u8string<20> result_i;
int value_i = -123999990;
String20 result_i;
int value_i = -123999990;
etl::u8string<20> result_d;
double value_d = -123.999990;
String20 result_d;
double value_d = -123.999990;
Format format = Format().precision(4).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::u8string<20>(STR("-124.0000")) == result_i);
CHECK(String20(STR("-124.0000")) == result_i);
CHECK(result_d == result_i);
}
@ -590,48 +592,48 @@ namespace
if (std::numeric_limits<double>::is_iec559)
{
// Check forced scientific formatting for smaller numbers.
etl::u8string<64> s0;
String64 s0;
etl::to_string(1000.0, s0, Format().precision(5).width(15).right().scientific(true));
CHECK(etl::u8string<64>(STR(" 1.00000e+3")) == s0);
CHECK(String64(STR(" 1.00000e+3")) == s0);
etl::to_string(1000.0, s0, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::u8string<64>(STR(" 1.00000E+3")) == s0);
CHECK(String64(STR(" 1.00000E+3")) == s0);
// Maximum double value is 1.7976931348623157e+308, which rounds to 1.79769e+308 with 5 digits of precision.
etl::u8string<64> s1;
String64 s1;
etl::to_string(std::numeric_limits<double>::max(), s1, Format().precision(5).width(15).right());
CHECK(etl::u8string<64>(STR(" 1.79769e+308")) == s1);
CHECK(String64(STR(" 1.79769e+308")) == s1);
// Negative maximum double value is -1.7976931348623157e+308, which rounds to -1.79769e+308 with 5 digits of precision.
etl::u8string<64> s2;
String64 s2;
etl::to_string(-std::numeric_limits<double>::max(), s2, Format().precision(5).width(15).right());
CHECK(etl::u8string<64>(STR(" -1.79769e+308")) == s2);
CHECK(String64(STR(" -1.79769e+308")) == s2);
}
#if ETL_USING_64BIT_TYPES
using workspace_t = etl::private_to_string::workspace_t;
// Maximum workspace_t value is 9223372036854775807.
etl::u8string<64> s3;
String64 s3;
etl::to_string(std::numeric_limits<workspace_t>::max(), s3, Format().precision(5).width(21).right());
CHECK(etl::u8string<64>(STR(" 9223372036854775807")) == s3);
CHECK(String64(STR(" 9223372036854775807")) == s3);
// Minimum workspace_t value is -9223372036854775808.
etl::u8string<64> s4;
String64 s4;
etl::to_string(std::numeric_limits<workspace_t>::min(), s4, Format().precision(5).width(21).right());
CHECK(etl::u8string<64>(STR(" -9223372036854775808")) == s4);
CHECK(String64(STR(" -9223372036854775808")) == s4);
using uworkspace_t = etl::private_to_string::uworkspace_t;
// Maximum uworkspace_t value is 18446744073709551615.
etl::u8string<64> s5;
String64 s5;
etl::to_string(std::numeric_limits<uworkspace_t>::max(), s5, Format().precision(5).width(21).right());
CHECK(etl::u8string<64>(STR(" 18446744073709551615")) == s5);
CHECK(String64(STR(" 18446744073709551615")) == s5);
// Minimum uworkspace_t value is 0.
etl::u8string<64> s6;
String64 s6;
etl::to_string(std::numeric_limits<uworkspace_t>::min(), s6, Format().precision(5).width(21).right());
CHECK(etl::u8string<64>(STR(" 0")) == s6);
CHECK(String64(STR(" 0")) == s6);
#endif
}
@ -640,31 +642,49 @@ namespace
{
if (std::numeric_limits<double>::is_iec559)
{
etl::u8string<64> s1;
String64 s1;
etl::to_string(std::numeric_limits<double>::quiet_NaN(), s1, Format().precision(5).width(15).right().scientific(true).upper_case(false));
CHECK(etl::u8string<64>(STR(" nan")) == s1);
CHECK(String64(STR(" nan")) == s1);
etl::u8string<64> s2;
String64 s2;
etl::to_string(std::numeric_limits<double>::infinity(), s2, Format().precision(5).width(15).right().scientific(true).upper_case(false));
CHECK(etl::u8string<64>(STR(" inf")) == s2);
CHECK(String64(STR(" inf")) == s2);
etl::u8string<64> s3;
String64 s3;
etl::to_string(-std::numeric_limits<double>::infinity(), s3, Format().precision(5).width(15).right().scientific(true).upper_case(false));
CHECK(etl::u8string<64>(STR(" -inf")) == s3);
CHECK(String64(STR(" -inf")) == s3);
etl::u8string<64> s4;
String64 s4;
etl::to_string(std::numeric_limits<double>::quiet_NaN(), s4, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::u8string<64>(STR(" NAN")) == s4);
CHECK(String64(STR(" NAN")) == s4);
etl::u8string<64> s5;
String64 s5;
etl::to_string(std::numeric_limits<double>::infinity(), s5, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::u8string<64>(STR(" INF")) == s5);
CHECK(String64(STR(" INF")) == s5);
etl::u8string<64> s6;
String64 s6;
etl::to_string(-std::numeric_limits<double>::infinity(), s6, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::u8string<64>(STR(" -INF")) == s6);
CHECK(String64(STR(" -INF")) == s6);
}
}
//*************************************************************************
TEST(test_issue_1593_to_string_float_uses_double_math)
{
String64 s1;
// Float
etl::to_string(3.1415927f, s1, Format().precision(4));
CHECK_TRUE(String64(STR("3.1416")) == s1);
// Double
etl::to_string(3.1415927, s1, Format().precision(4));
CHECK_TRUE(String64(STR("3.1416")) == s1);
// Long double
etl::to_string(3.1415927l, s1, Format().precision(4));
CHECK_TRUE(String64(STR("3.1416")) == s1);
}
}
} // namespace

View File

@ -44,32 +44,35 @@ namespace
{
typedef etl::wformat_spec Format;
using String20 = etl::wstring<20>;
using String64 = etl::wstring<64>;
SUITE(test_to_wstring)
{
//*************************************************************************
TEST(test_default_format_no_append)
{
etl::wstring<20> str;
String20 str;
CHECK(etl::wstring<20>(STR("0")) == etl::to_string(uint8_t(0), str));
CHECK(etl::wstring<20>(STR("0")) == etl::to_string(uint16_t(0), str));
CHECK(etl::wstring<20>(STR("0")) == etl::to_string(uint32_t(0), str));
CHECK(etl::wstring<20>(STR("0")) == etl::to_string(uint64_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint8_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint16_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint32_t(0), str));
CHECK(String20(STR("0")) == etl::to_string(uint64_t(0), str));
CHECK(etl::wstring<20>(STR("128")) == etl::to_string(uint8_t(128), str));
CHECK(etl::wstring<20>(STR("32768")) == etl::to_string(uint16_t(32768), str));
CHECK(etl::wstring<20>(STR("2147483648")) == etl::to_string(uint32_t(2147483648ul), str));
CHECK(etl::wstring<20>(STR("9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str));
CHECK(String20(STR("128")) == etl::to_string(uint8_t(128), str));
CHECK(String20(STR("32768")) == etl::to_string(uint16_t(32768), str));
CHECK(String20(STR("2147483648")) == etl::to_string(uint32_t(2147483648ul), str));
CHECK(String20(STR("9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str));
CHECK(etl::wstring<20>(STR("127")) == etl::to_string(INT8_MAX, str));
CHECK(etl::wstring<20>(STR("32767")) == etl::to_string(INT16_MAX, str));
CHECK(etl::wstring<20>(STR("2147483647")) == etl::to_string(INT32_MAX, str));
CHECK(etl::wstring<20>(STR("9223372036854775807")) == etl::to_string(INT64_MAX, str));
CHECK(String20(STR("127")) == etl::to_string(INT8_MAX, str));
CHECK(String20(STR("32767")) == etl::to_string(INT16_MAX, str));
CHECK(String20(STR("2147483647")) == etl::to_string(INT32_MAX, str));
CHECK(String20(STR("9223372036854775807")) == etl::to_string(INT64_MAX, str));
CHECK(etl::wstring<20>(STR("-128")) == etl::to_string(INT8_MIN, str));
CHECK(etl::wstring<20>(STR("-32768")) == etl::to_string(INT16_MIN, str));
CHECK(etl::wstring<20>(STR("-2147483648")) == etl::to_string(INT32_MIN, str));
CHECK(etl::wstring<20>(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str));
CHECK(String20(STR("-128")) == etl::to_string(INT8_MIN, str));
CHECK(String20(STR("-32768")) == etl::to_string(INT16_MIN, str));
CHECK(String20(STR("-2147483648")) == etl::to_string(INT32_MIN, str));
CHECK(String20(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str));
}
//*************************************************************************
@ -107,87 +110,87 @@ namespace
//*************************************************************************
TEST(test_format_right_justified_no_append)
{
etl::wstring<20> str;
String20 str;
Format format = Format().base(10).width(20).fill(STR('#'));
CHECK(etl::wstring<20>(STR("###################0")) == etl::to_string(uint8_t(0), str, format));
CHECK(etl::wstring<20>(STR("###################0")) == etl::to_string(uint16_t(0), str, format));
CHECK(etl::wstring<20>(STR("###################0")) == etl::to_string(uint32_t(0), str, format));
CHECK(etl::wstring<20>(STR("###################0")) == etl::to_string(uint64_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint8_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint16_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint32_t(0), str, format));
CHECK(String20(STR("###################0")) == etl::to_string(uint64_t(0), str, format));
CHECK(etl::wstring<20>(STR("#################128")) == etl::to_string(uint8_t(128), str, format));
CHECK(etl::wstring<20>(STR("###############32768")) == etl::to_string(uint16_t(32768), str, format));
CHECK(etl::wstring<20>(STR("##########2147483648")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(etl::wstring<20>(STR("#9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(String20(STR("#################128")) == etl::to_string(uint8_t(128), str, format));
CHECK(String20(STR("###############32768")) == etl::to_string(uint16_t(32768), str, format));
CHECK(String20(STR("##########2147483648")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(String20(STR("#9223372036854775808")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(etl::wstring<20>(STR("#################127")) == etl::to_string(INT8_MAX, str, format));
CHECK(etl::wstring<20>(STR("###############32767")) == etl::to_string(INT16_MAX, str, format));
CHECK(etl::wstring<20>(STR("##########2147483647")) == etl::to_string(INT32_MAX, str, format));
CHECK(etl::wstring<20>(STR("#9223372036854775807")) == etl::to_string(INT64_MAX, str, format));
CHECK(String20(STR("#################127")) == etl::to_string(INT8_MAX, str, format));
CHECK(String20(STR("###############32767")) == etl::to_string(INT16_MAX, str, format));
CHECK(String20(STR("##########2147483647")) == etl::to_string(INT32_MAX, str, format));
CHECK(String20(STR("#9223372036854775807")) == etl::to_string(INT64_MAX, str, format));
CHECK(etl::wstring<20>(STR("################-128")) == etl::to_string(INT8_MIN, str, format));
CHECK(etl::wstring<20>(STR("##############-32768")) == etl::to_string(INT16_MIN, str, format));
CHECK(etl::wstring<20>(STR("#########-2147483648")) == etl::to_string(INT32_MIN, str, format));
CHECK(etl::wstring<20>(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
CHECK(String20(STR("################-128")) == etl::to_string(INT8_MIN, str, format));
CHECK(String20(STR("##############-32768")) == etl::to_string(INT16_MIN, str, format));
CHECK(String20(STR("#########-2147483648")) == etl::to_string(INT32_MIN, str, format));
CHECK(String20(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
}
//*************************************************************************
TEST(test_format_left_justified_no_append)
{
etl::wstring<20> str;
String20 str;
Format format = Format().base(10).width(20).fill(STR('#')).left();
CHECK(etl::wstring<20>(STR("0###################")) == etl::to_string(uint8_t(0), str, format));
CHECK(etl::wstring<20>(STR("0###################")) == etl::to_string(uint16_t(0), str, format));
CHECK(etl::wstring<20>(STR("0###################")) == etl::to_string(uint32_t(0), str, format));
CHECK(etl::wstring<20>(STR("0###################")) == etl::to_string(uint64_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint8_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint16_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint32_t(0), str, format));
CHECK(String20(STR("0###################")) == etl::to_string(uint64_t(0), str, format));
CHECK(etl::wstring<20>(STR("128#################")) == etl::to_string(uint8_t(128), str, format));
CHECK(etl::wstring<20>(STR("32768###############")) == etl::to_string(uint16_t(32768), str, format));
CHECK(etl::wstring<20>(STR("2147483648##########")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(etl::wstring<20>(STR("9223372036854775808#")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(String20(STR("128#################")) == etl::to_string(uint8_t(128), str, format));
CHECK(String20(STR("32768###############")) == etl::to_string(uint16_t(32768), str, format));
CHECK(String20(STR("2147483648##########")) == etl::to_string(uint32_t(2147483648ul), str, format));
CHECK(String20(STR("9223372036854775808#")) == etl::to_string(uint64_t(9223372036854775808ull), str, format));
CHECK(etl::wstring<20>(STR("127#################")) == etl::to_string(INT8_MAX, str, format));
CHECK(etl::wstring<20>(STR("32767###############")) == etl::to_string(INT16_MAX, str, format));
CHECK(etl::wstring<20>(STR("2147483647##########")) == etl::to_string(INT32_MAX, str, format));
CHECK(etl::wstring<20>(STR("9223372036854775807#")) == etl::to_string(INT64_MAX, str, format));
CHECK(String20(STR("127#################")) == etl::to_string(INT8_MAX, str, format));
CHECK(String20(STR("32767###############")) == etl::to_string(INT16_MAX, str, format));
CHECK(String20(STR("2147483647##########")) == etl::to_string(INT32_MAX, str, format));
CHECK(String20(STR("9223372036854775807#")) == etl::to_string(INT64_MAX, str, format));
CHECK(etl::wstring<20>(STR("-128################")) == etl::to_string(INT8_MIN, str, format));
CHECK(etl::wstring<20>(STR("-32768##############")) == etl::to_string(INT16_MIN, str, format));
CHECK(etl::wstring<20>(STR("-2147483648#########")) == etl::to_string(INT32_MIN, str, format));
CHECK(etl::wstring<20>(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
CHECK(String20(STR("-128################")) == etl::to_string(INT8_MIN, str, format));
CHECK(String20(STR("-32768##############")) == etl::to_string(INT16_MIN, str, format));
CHECK(String20(STR("-2147483648#########")) == etl::to_string(INT32_MIN, str, format));
CHECK(String20(STR("-9223372036854775808")) == etl::to_string(INT64_MIN, str, format));
}
//*************************************************************************
TEST(test_binary_format_no_append)
{
etl::wstring<64> str;
String64 str;
CHECK(etl::wstring<64>(STR("00000000")) == etl::to_string(uint8_t(0), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::wstring<64>(STR("0000000000000000")) == etl::to_string(uint16_t(0), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::wstring<64>(STR("00000000000000000000000000000000")) == etl::to_string(uint32_t(0), str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::wstring<64>(STR("0000000000000000000000000000000000000000000000000000000000000000"))
CHECK(String64(STR("00000000")) == etl::to_string(uint8_t(0), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("0000000000000000")) == etl::to_string(uint16_t(0), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("00000000000000000000000000000000")) == etl::to_string(uint32_t(0), str, Format().base(2).width(32).fill(STR('0'))));
CHECK(String64(STR("0000000000000000000000000000000000000000000000000000000000000000"))
== etl::to_string(uint64_t(0), str, Format().base(2).width(64).fill(STR('0'))));
CHECK(etl::wstring<64>(STR("10000000")) == etl::to_string(uint8_t(128), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::wstring<64>(STR("1000000000000000")) == etl::to_string(uint16_t(32768), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::wstring<64>(STR("10000000000000000000000000000000"))
CHECK(String64(STR("10000000")) == etl::to_string(uint8_t(128), str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("1000000000000000")) == etl::to_string(uint16_t(32768), str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("10000000000000000000000000000000"))
== etl::to_string(uint32_t(2147483648ul), str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::wstring<64>(STR("1000000000000000000000000000000000000000000000000000000000000000"))
CHECK(String64(STR("1000000000000000000000000000000000000000000000000000000000000000"))
== etl::to_string(uint64_t(9223372036854775808ull), str, Format().base(2).width(64).fill(STR('0'))));
CHECK(etl::wstring<64>(STR("01111111")) == etl::to_string(INT8_MAX, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::wstring<64>(STR("0111111111111111")) == etl::to_string(INT16_MAX, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::wstring<64>(STR("01111111111111111111111111111111")) == etl::to_string(INT32_MAX, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::wstring<64>(STR("0111111111111111111111111111111111111111111111111111111111111111"))
CHECK(String64(STR("01111111")) == etl::to_string(INT8_MAX, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("0111111111111111")) == etl::to_string(INT16_MAX, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("01111111111111111111111111111111")) == etl::to_string(INT32_MAX, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(String64(STR("0111111111111111111111111111111111111111111111111111111111111111"))
== etl::to_string(INT64_MAX, str, Format().base(2).width(64).fill(STR('0'))));
CHECK(etl::wstring<64>(STR("10000000")) == etl::to_string(INT8_MIN, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(etl::wstring<64>(STR("1000000000000000")) == etl::to_string(INT16_MIN, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(etl::wstring<64>(STR("10000000000000000000000000000000")) == etl::to_string(INT32_MIN, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(etl::wstring<64>(STR("1000000000000000000000000000000000000000000000000000000000000000"))
CHECK(String64(STR("10000000")) == etl::to_string(INT8_MIN, str, Format().base(2).width(8).fill(STR('0'))));
CHECK(String64(STR("1000000000000000")) == etl::to_string(INT16_MIN, str, Format().base(2).width(16).fill(STR('0'))));
CHECK(String64(STR("10000000000000000000000000000000")) == etl::to_string(INT32_MIN, str, Format().base(2).width(32).fill(STR('0'))));
CHECK(String64(STR("1000000000000000000000000000000000000000000000000000000000000000"))
== etl::to_string(INT64_MIN, str, Format().base(2).width(64).fill(STR('0'))));
}
@ -259,119 +262,119 @@ namespace
//*************************************************************************
TEST(test_floating_point_no_append)
{
etl::wstring<20> str;
String20 str;
CHECK(etl::wstring<20>(STR(" 0.000000")) == etl::to_string(0.0, str, Format().precision(6).width(10).right()));
CHECK(etl::wstring<20>(STR("0.000000 ")) == etl::to_string(0.0, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 0.000000")) == etl::to_string(0.0, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("0.000000 ")) == etl::to_string(0.0, str, Format().precision(6).width(10).left()));
CHECK(etl::wstring<20>(STR(" 0.000001")) == etl::to_string(0.000001, str, Format().precision(6).width(10).right()));
CHECK(etl::wstring<20>(STR("0.000001 ")) == etl::to_string(0.000001, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 0.000001")) == etl::to_string(0.000001, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("0.000001 ")) == etl::to_string(0.000001, str, Format().precision(6).width(10).left()));
CHECK(etl::wstring<20>(STR(" 1.000000")) == etl::to_string(1.0, str, Format().precision(6).width(10).right()));
CHECK(etl::wstring<20>(STR("1.000000 ")) == etl::to_string(1.0, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 1.000000")) == etl::to_string(1.0, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("1.000000 ")) == etl::to_string(1.0, str, Format().precision(6).width(10).left()));
CHECK(etl::wstring<20>(STR(" 1.000001")) == etl::to_string(1.000001, str, Format().precision(6).width(10).right()));
CHECK(etl::wstring<20>(STR("1.000001 ")) == etl::to_string(1.000001, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 1.000001")) == etl::to_string(1.000001, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("1.000001 ")) == etl::to_string(1.000001, str, Format().precision(6).width(10).left()));
CHECK(etl::wstring<20>(STR(" 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right()));
CHECK(etl::wstring<20>(STR("12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left()));
CHECK(etl::wstring<20>(STR(" -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right()));
CHECK(etl::wstring<20>(STR("-12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left()));
CHECK(String20(STR(" -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right()));
CHECK(String20(STR("-12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left()));
CHECK(etl::wstring<20>(STR(" -0.123456")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).right()));
CHECK(etl::wstring<20>(STR("-0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left()));
CHECK(String20(STR(" -0.123456")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).right()));
CHECK(String20(STR("-0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left()));
}
//*************************************************************************
TEST(test_floating_point_append)
{
etl::wstring<20> str;
String20 str;
str.assign(STR("Result "));
CHECK(etl::wstring<20>(STR("Result 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right(), true));
CHECK(String20(STR("Result 12.345678")) == etl::to_string(12.345678, str, Format().precision(6).width(10).right(), true));
str.assign(STR("Result "));
CHECK(etl::wstring<20>(STR("Result 12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left(), true));
CHECK(String20(STR("Result 12.345678 ")) == etl::to_string(12.345678, str, Format().precision(6).width(10).left(), true));
str.assign(STR("Result "));
CHECK(etl::wstring<20>(STR("Result -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right(), true));
CHECK(String20(STR("Result -12.345678")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).right(), true));
str.assign(STR("Result "));
CHECK(etl::wstring<20>(STR("Result -12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left(), true));
CHECK(String20(STR("Result -12.345678 ")) == etl::to_string(-12.345678, str, Format().precision(6).width(11).left(), true));
str.assign(STR("Result "));
CHECK(etl::wstring<20>(STR("Result -0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left(), true));
CHECK(String20(STR("Result -0.123456 ")) == etl::to_string(-0.123456, str, Format().precision(6).width(10).left(), true));
}
//*************************************************************************
TEST(test_floating_point_rounding)
{
etl::wstring<20> str;
String20 str;
CHECK(etl::wstring<20>(STR("0.00001")) == etl::to_string(0.000009, str, Format().precision(5).width(7).right()));
CHECK(etl::wstring<20>(STR("0.0001")) == etl::to_string(0.000099, str, Format().precision(4).width(6).right()));
CHECK(etl::wstring<20>(STR("0.001")) == etl::to_string(0.000999, str, Format().precision(3).width(5).right()));
CHECK(etl::wstring<20>(STR("0.01")) == etl::to_string(0.009999, str, Format().precision(2).width(4).right()));
CHECK(etl::wstring<20>(STR("0.1")) == etl::to_string(0.099999, str, Format().precision(1).width(3).right()));
CHECK(etl::wstring<20>(STR("1.0")) == etl::to_string(0.999999, str, Format().precision(1).width(3).right()));
CHECK(etl::wstring<20>(STR("1")) == etl::to_string(0.999999, str, Format().precision(0).width(1).right()));
CHECK(etl::wstring<20>(STR("10.0")) == etl::to_string(9.999999, str, Format().precision(1).width(4).right()));
CHECK(etl::wstring<20>(STR("2")) == etl::to_string(1.999999, str, Format().precision(0).width(1).right()));
CHECK(etl::wstring<20>(STR("10.0")) == etl::to_string(9.999999, str, Format().precision(1).width(4).right()));
CHECK(etl::wstring<20>(STR("20.0")) == etl::to_string(19.999999, str, Format().precision(1).width(4).right()));
CHECK(String20(STR("0.00001")) == etl::to_string(0.000009, str, Format().precision(5).width(7).right()));
CHECK(String20(STR("0.0001")) == etl::to_string(0.000099, str, Format().precision(4).width(6).right()));
CHECK(String20(STR("0.001")) == etl::to_string(0.000999, str, Format().precision(3).width(5).right()));
CHECK(String20(STR("0.01")) == etl::to_string(0.009999, str, Format().precision(2).width(4).right()));
CHECK(String20(STR("0.1")) == etl::to_string(0.099999, str, Format().precision(1).width(3).right()));
CHECK(String20(STR("1.0")) == etl::to_string(0.999999, str, Format().precision(1).width(3).right()));
CHECK(String20(STR("1")) == etl::to_string(0.999999, str, Format().precision(0).width(1).right()));
CHECK(String20(STR("10.0")) == etl::to_string(9.999999, str, Format().precision(1).width(4).right()));
CHECK(String20(STR("2")) == etl::to_string(1.999999, str, Format().precision(0).width(1).right()));
CHECK(String20(STR("10.0")) == etl::to_string(9.999999, str, Format().precision(1).width(4).right()));
CHECK(String20(STR("20.0")) == etl::to_string(19.999999, str, Format().precision(1).width(4).right()));
}
//*************************************************************************
TEST(test_bool_no_append)
{
etl::wstring<20> str;
String20 str;
CHECK(etl::wstring<20>(STR(" 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(etl::wstring<20>(STR(" 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(etl::wstring<20>(STR("0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(etl::wstring<20>(STR("1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(String20(STR(" 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(String20(STR(" 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false)));
CHECK(String20(STR("0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(String20(STR("1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false)));
CHECK(etl::wstring<20>(STR(" false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(etl::wstring<20>(STR(" true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(etl::wstring<20>(STR("false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true)));
CHECK(etl::wstring<20>(STR("true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true)));
CHECK(String20(STR(" false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(String20(STR(" true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true)));
CHECK(String20(STR("false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true)));
CHECK(String20(STR("true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true)));
}
//*************************************************************************
TEST(test_bool_append)
{
etl::wstring<20> str;
String20 str;
str.assign(STR("Result "));
CHECK(etl::wstring<20>(STR("Result 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false), true));
CHECK(String20(STR("Result 0")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::wstring<20>(STR("Result 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false), true));
CHECK(String20(STR("Result 1")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::wstring<20>(STR("Result 0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false), true));
CHECK(String20(STR("Result 0 ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::wstring<20>(STR("Result 1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false), true));
CHECK(String20(STR("Result 1 ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(false), true));
str.assign(STR("Result "));
CHECK(etl::wstring<20>(STR("Result false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true), true));
CHECK(String20(STR("Result false")) == to_string(false, str, Format().precision(6).width(10).right().boolalpha(true), true));
str.assign(STR("Result "));
CHECK(etl::wstring<20>(STR("Result true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true), true));
CHECK(String20(STR("Result true")) == to_string(true, str, Format().precision(6).width(10).right().boolalpha(true), true));
str.assign(STR("Result "));
CHECK(etl::wstring<20>(STR("Result false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true), true));
CHECK(String20(STR("Result false ")) == to_string(false, str, Format().precision(6).width(10).left().boolalpha(true), true));
str.assign(STR("Result "));
CHECK(etl::wstring<20>(STR("Result true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true), true));
CHECK(String20(STR("Result true ")) == to_string(true, str, Format().precision(6).width(10).left().boolalpha(true), true));
}
//*************************************************************************
TEST(test_pointer_no_append)
{
etl::wstring<20> str;
String20 str;
static const volatile int cvi = 0;
@ -379,8 +382,8 @@ namespace
oss.width(10);
oss.fill(STR('0'));
oss << std::hex << std::right << uintptr_t(&cvi);
std::wstring temp(oss.str());
etl::wstring<20> compare(temp.begin(), temp.end());
std::wstring temp(oss.str());
String20 compare(temp.begin(), temp.end());
to_string(&cvi, str, Format().hex().width(10).right().fill(STR('0')));
CHECK(compare == str);
@ -400,7 +403,7 @@ namespace
//*************************************************************************
TEST(test_pointer_append)
{
etl::wstring<20> str;
String20 str;
static const volatile int cvi = 0;
@ -410,7 +413,7 @@ namespace
oss << std::hex << std::right << uintptr_t(&cvi);
std::wstring temp(STR("Result "));
temp.append(oss.str());
etl::wstring<20> compare(temp.begin(), temp.end());
String20 compare(temp.begin(), temp.end());
str.assign(STR("Result "));
to_string(&cvi, str, Format().hex().width(10).right().fill(STR('0')), true);
@ -433,217 +436,217 @@ namespace
//*************************************************************************
TEST(test_integer_denominator_default_format)
{
etl::wstring<20> result;
int value = -1234567;
String20 result;
int value = -1234567;
etl::to_string(value, 6U, result);
CHECK(etl::wstring<20>(STR("-1")) == result);
CHECK(String20(STR("-1")) == result);
}
//*************************************************************************
TEST(test_integer_denominator_huge_precision)
{
etl::wstring<20> result;
int value = -1234560;
String20 result;
int value = -1234560;
Format format = Format().precision(100);
etl::to_string(value, 6U, result, format);
CHECK(etl::wstring<20>(STR("-1.234560")) == result);
CHECK(String20(STR("-1.234560")) == result);
}
//*************************************************************************
TEST(test_integer_denominator_huge_precision_64bit)
{
etl::wstring<20> result;
int64_t value = INT64_MIN;
String20 result;
int64_t value = INT64_MIN;
Format format = Format().precision(100);
etl::to_string(value, 12U, result, format);
CHECK(etl::wstring<20>(STR("-9223372.036854775808")) == result);
CHECK(String20(STR("-9223372.036854775808")) == result);
}
//*************************************************************************
TEST(test_integer_denominator_zero_fractional)
{
etl::wstring<20> result_i;
int value_i = -1000000;
String20 result_i;
int value_i = -1000000;
etl::wstring<20> result_d;
double value_d = -1.000000;
String20 result_d;
double value_d = -1.000000;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::wstring<20>(STR("-1.0000")) == result_i);
CHECK(String20(STR("-1.0000")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_zero_value)
{
etl::wstring<20> result_i;
int value_i = 0;
String20 result_i;
int value_i = 0;
etl::wstring<20> result_d;
double value_d = -0.000000;
String20 result_d;
double value_d = -0.000000;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::wstring<20>(STR("0.0000")) == result_i);
CHECK(String20(STR("0.0000")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_zero_integral_small_fractional)
{
etl::wstring<20> result_i;
int value_i = -400;
String20 result_i;
int value_i = -400;
etl::wstring<20> result_d;
double value_d = -0.000400;
String20 result_d;
double value_d = -0.000400;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::wstring<20>(STR("-0.0004")) == result_i);
CHECK(String20(STR("-0.0004")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_small_fractional)
{
etl::wstring<20> result_i;
int value_i = -123000400;
String20 result_i;
int value_i = -123000400;
etl::wstring<20> result_d;
double value_d = -123.000400;
String20 result_d;
double value_d = -123.000400;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::wstring<20>(STR("-123.0004")) == result_i);
CHECK(String20(STR("-123.0004")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_very_small_fractional)
{
etl::wstring<20> result_i;
int value_i = -123000004;
String20 result_i;
int value_i = -123000004;
etl::wstring<20> result_d;
double value_d = -123.000004;
String20 result_d;
double value_d = -123.000004;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::wstring<20>(STR("-123.0000")) == result_i);
CHECK(String20(STR("-123.0000")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_very_small_fractional_rounded_up)
{
etl::wstring<20> result_i;
int value_i = -123000050;
String20 result_i;
int value_i = -123000050;
etl::wstring<20> result_d;
double value_d = -123.000050;
String20 result_d;
double value_d = -123.000050;
Format format = Format().precision(4);
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::wstring<20>(STR("-123.0001")) == result_i);
CHECK(String20(STR("-123.0001")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_shorter_width)
{
etl::wstring<20> result_i;
int value_i = -123456780;
String20 result_i;
int value_i = -123456780;
etl::wstring<20> result_d;
double value_d = -123.456780;
String20 result_d;
double value_d = -123.456780;
Format format = Format().precision(4).width(6).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::wstring<20>(STR("-123.4568")) == result_i);
CHECK(String20(STR("-123.4568")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_larger_width)
{
etl::wstring<20> result_i;
int value_i = -123456780;
String20 result_i;
int value_i = -123456780;
etl::wstring<20> result_d;
double value_d = -123.456780;
String20 result_d;
double value_d = -123.456780;
Format format = Format().precision(4).width(15).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::wstring<20>(STR(" -123.4568")) == result_i);
CHECK(String20(STR(" -123.4568")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_positive_rollover)
{
etl::wstring<20> result_i;
int value_i = 123999990;
String20 result_i;
int value_i = 123999990;
etl::wstring<20> result_d;
double value_d = 123.999990;
String20 result_d;
double value_d = 123.999990;
Format format = Format().precision(4).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::wstring<20>(STR("124.0000")) == result_i);
CHECK(String20(STR("124.0000")) == result_i);
CHECK(result_d == result_i);
}
//*************************************************************************
TEST(test_integer_denominator_negative_rollover)
{
etl::wstring<20> result_i;
int value_i = -123999990;
String20 result_i;
int value_i = -123999990;
etl::wstring<20> result_d;
double value_d = -123.999990;
String20 result_d;
double value_d = -123.999990;
Format format = Format().precision(4).right();
etl::to_string(value_i, 6U, result_i, format);
etl::to_string(value_d, result_d, format);
CHECK(etl::wstring<20>(STR("-124.0000")) == result_i);
CHECK(String20(STR("-124.0000")) == result_i);
CHECK(result_d == result_i);
}
@ -653,48 +656,48 @@ namespace
if (std::numeric_limits<double>::is_iec559)
{
// Check forced scientific formatting for smaller numbers.
etl::wstring<64> s0;
String64 s0;
etl::to_string(1000.0, s0, Format().precision(5).width(15).right().scientific(true));
CHECK(etl::wstring<64>(STR(" 1.00000e+3")) == s0);
CHECK(String64(STR(" 1.00000e+3")) == s0);
etl::to_string(1000.0, s0, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::wstring<64>(STR(" 1.00000E+3")) == s0);
CHECK(String64(STR(" 1.00000E+3")) == s0);
// Maximum double value is 1.7976931348623157e+308, which rounds to 1.79769e+308 with 5 digits of precision.
etl::wstring<64> s1;
String64 s1;
etl::to_string(std::numeric_limits<double>::max(), s1, Format().precision(5).width(15).right());
CHECK(etl::wstring<64>(STR(" 1.79769e+308")) == s1);
CHECK(String64(STR(" 1.79769e+308")) == s1);
// Negative maximum double value is -1.7976931348623157e+308, which rounds to -1.79769e+308 with 5 digits of precision.
etl::wstring<64> s2;
String64 s2;
etl::to_string(-std::numeric_limits<double>::max(), s2, Format().precision(5).width(15).right());
CHECK(etl::wstring<64>(STR(" -1.79769e+308")) == s2);
CHECK(String64(STR(" -1.79769e+308")) == s2);
}
#if ETL_USING_64BIT_TYPES
using workspace_t = etl::private_to_string::workspace_t;
// Maximum workspace_t value is 9223372036854775807.
etl::wstring<64> s3;
String64 s3;
etl::to_string(std::numeric_limits<workspace_t>::max(), s3, Format().precision(5).width(21).right());
CHECK(etl::wstring<64>(STR(" 9223372036854775807")) == s3);
CHECK(String64(STR(" 9223372036854775807")) == s3);
// Minimum workspace_t value is -9223372036854775808.
etl::wstring<64> s4;
String64 s4;
etl::to_string(std::numeric_limits<workspace_t>::min(), s4, Format().precision(5).width(21).right());
CHECK(etl::wstring<64>(STR(" -9223372036854775808")) == s4);
CHECK(String64(STR(" -9223372036854775808")) == s4);
using uworkspace_t = etl::private_to_string::uworkspace_t;
// Maximum uworkspace_t value is 18446744073709551615.
etl::wstring<64> s5;
String64 s5;
etl::to_string(std::numeric_limits<uworkspace_t>::max(), s5, Format().precision(5).width(21).right());
CHECK(etl::wstring<64>(STR(" 18446744073709551615")) == s5);
CHECK(String64(STR(" 18446744073709551615")) == s5);
// Minimum uworkspace_t value is 0.
etl::wstring<64> s6;
String64 s6;
etl::to_string(std::numeric_limits<uworkspace_t>::min(), s6, Format().precision(5).width(21).right());
CHECK(etl::wstring<64>(STR(" 0")) == s6);
CHECK(String64(STR(" 0")) == s6);
#endif
}
@ -703,30 +706,48 @@ namespace
{
if (std::numeric_limits<double>::is_iec559)
{
etl::wstring<64> s1;
String64 s1;
etl::to_string(std::numeric_limits<double>::quiet_NaN(), s1, Format().precision(5).width(15).right().scientific(true).upper_case(false));
CHECK(etl::wstring<64>(STR(" nan")) == s1);
CHECK(String64(STR(" nan")) == s1);
etl::wstring<64> s2;
String64 s2;
etl::to_string(std::numeric_limits<double>::infinity(), s2, Format().precision(5).width(15).right().scientific(true).upper_case(false));
CHECK(etl::wstring<64>(STR(" inf")) == s2);
CHECK(String64(STR(" inf")) == s2);
etl::wstring<64> s3;
String64 s3;
etl::to_string(-std::numeric_limits<double>::infinity(), s3, Format().precision(5).width(15).right().scientific(true).upper_case(false));
CHECK(etl::wstring<64>(STR(" -inf")) == s3);
CHECK(String64(STR(" -inf")) == s3);
etl::wstring<64> s4;
String64 s4;
etl::to_string(std::numeric_limits<double>::quiet_NaN(), s4, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::wstring<64>(STR(" NAN")) == s4);
CHECK(String64(STR(" NAN")) == s4);
etl::wstring<64> s5;
String64 s5;
etl::to_string(std::numeric_limits<double>::infinity(), s5, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::wstring<64>(STR(" INF")) == s5);
CHECK(String64(STR(" INF")) == s5);
etl::wstring<64> s6;
String64 s6;
etl::to_string(-std::numeric_limits<double>::infinity(), s6, Format().precision(5).width(15).right().scientific(true).upper_case(true));
CHECK(etl::wstring<64>(STR(" -INF")) == s6);
CHECK(String64(STR(" -INF")) == s6);
}
}
//*************************************************************************
TEST(test_issue_1593_to_string_float_uses_double_math)
{
String64 s1;
// Float
etl::to_string(3.1415927f, s1, Format().precision(4));
CHECK_TRUE(String64(STR("3.1416")) == s1);
// Double
etl::to_string(3.1415927, s1, Format().precision(4));
CHECK_TRUE(String64(STR("3.1416")) == s1);
// Long double
etl::to_string(3.1415927l, s1, Format().precision(4));
CHECK_TRUE(String64(STR("3.1416")) == s1);
}
}
} // namespace

View File

@ -282,6 +282,294 @@ namespace
CHECK_THROW(etl::be_uint8_t be_byte_empty(buffer.data(), 0U), etl::unaligned_type_buffer_size);
}
//*************************************************************************
// 'value_from' reads a value straight out of a byte buffer, without first
// copying the bytes into an unaligned_type's own storage.
//*************************************************************************
TEST(test_value_from_integral)
{
const std::array<unsigned char, 8> buffer = {0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC, 0xDE, 0xF0};
CHECK_EQUAL(uint16_t(0x1234), etl::be_uint16_t::value_from(buffer.data()));
CHECK_EQUAL(uint16_t(0x3412), etl::le_uint16_t::value_from(buffer.data()));
CHECK_EQUAL(uint32_t(0x12345678), etl::be_uint32_t::value_from(buffer.data()));
CHECK_EQUAL(uint32_t(0x78563412), etl::le_uint32_t::value_from(buffer.data()));
CHECK_EQUAL(uint64_t(0x123456789ABCDEF0), etl::be_uint64_t::value_from(buffer.data()));
CHECK_EQUAL(uint64_t(0xF0DEBC9A78563412), etl::le_uint64_t::value_from(buffer.data()));
}
//*************************************************************************
/// The address need not be aligned for the value's type.
//*************************************************************************
TEST(test_value_from_unaligned_address)
{
const std::array<unsigned char, 6> buffer = {0xFF, 0x12, 0x34, 0x56, 0x78, 0xFF};
CHECK_EQUAL(uint32_t(0x12345678), etl::be_uint32_t::value_from(buffer.data() + 1));
CHECK_EQUAL(uint32_t(0x78563412), etl::le_uint32_t::value_from(buffer.data() + 1));
}
//*************************************************************************
/// 'value_from' must agree with constructing from the same address and
/// then reading the value back out.
//*************************************************************************
TEST(test_value_from_matches_construction)
{
const std::array<unsigned char, 8> buffer = {0xEE, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF};
CHECK_EQUAL(etl::be_uint16_t(buffer.data()).value(), etl::be_uint16_t::value_from(buffer.data()));
CHECK_EQUAL(etl::le_uint16_t(buffer.data()).value(), etl::le_uint16_t::value_from(buffer.data()));
CHECK_EQUAL(etl::be_uint32_t(buffer.data()).value(), etl::be_uint32_t::value_from(buffer.data()));
CHECK_EQUAL(etl::le_uint32_t(buffer.data()).value(), etl::le_uint32_t::value_from(buffer.data()));
CHECK_EQUAL(etl::be_uint64_t(buffer.data()).value(), etl::be_uint64_t::value_from(buffer.data()));
CHECK_EQUAL(etl::le_uint64_t(buffer.data()).value(), etl::le_uint64_t::value_from(buffer.data()));
}
//*************************************************************************
/// Boundary values must survive the round trip through the store.
//*************************************************************************
TEST(test_value_from_boundary_values)
{
const std::array<unsigned char, 4> zeroes = {0x00, 0x00, 0x00, 0x00};
const std::array<unsigned char, 4> ones = {0xFF, 0xFF, 0xFF, 0xFF};
CHECK_EQUAL(uint32_t(0), etl::be_uint32_t::value_from(zeroes.data()));
CHECK_EQUAL(uint32_t(0), etl::le_uint32_t::value_from(zeroes.data()));
CHECK_EQUAL(etl::integral_limits<uint32_t>::max, etl::be_uint32_t::value_from(ones.data()));
CHECK_EQUAL(etl::integral_limits<uint32_t>::max, etl::le_uint32_t::value_from(ones.data()));
}
//*************************************************************************
/// Signed types are reconstructed through their unsigned representation.
//*************************************************************************
TEST(test_value_from_negative_values)
{
const std::array<unsigned char, 4> buffer = {0xFF, 0xFF, 0xFF, 0xFE};
CHECK_EQUAL(int32_t(-2), etl::be_int32_t::value_from(buffer.data()));
CHECK_EQUAL(int16_t(-1), etl::be_int16_t::value_from(buffer.data()));
}
//*************************************************************************
/// The floating point specialisation provides 'value_from' too.
//*************************************************************************
TEST(test_value_from_float)
{
const float f = 3.1415927f;
const double d = 2.718281828459045;
etl::be_float_t be_f(f);
etl::le_double_t le_d(d);
CHECK_EQUAL(f, etl::be_float_t::value_from(be_f.data()));
CHECK_EQUAL(d, etl::le_double_t::value_from(le_d.data()));
}
/// Unsigned integers that have no native equivalent, such as 24 bit.
//*************************************************************************
TEST(test_uint24)
{
CHECK_EQUAL(3U, sizeof(etl::le_uint24_t));
CHECK_EQUAL(3U, sizeof(etl::be_uint24_t));
CHECK_EQUAL(3U, size_t(etl::le_uint24_t::Size));
CHECK((etl::is_same<uint32_t, etl::le_uint24_t::value_type>::value));
CHECK_EQUAL(uint32_t(0x00FFFFFF), etl::le_uint24_t::Max_Value);
etl::le_uint24_t le_v(0x123456U);
etl::be_uint24_t be_v(0x123456U);
CHECK_EQUAL(uint32_t(0x123456), le_v.value());
CHECK_EQUAL(uint32_t(0x123456), be_v.value());
// Check the storage byte order.
CHECK_EQUAL(0x56, int(le_v.data()[0]));
CHECK_EQUAL(0x34, int(le_v.data()[1]));
CHECK_EQUAL(0x12, int(le_v.data()[2]));
CHECK_EQUAL(0x12, int(be_v.data()[0]));
CHECK_EQUAL(0x34, int(be_v.data()[1]));
CHECK_EQUAL(0x56, int(be_v.data()[2]));
// Copy construction, including from the other endianness.
etl::le_uint24_t le_v2(le_v);
etl::be_uint24_t be_v2(be_v);
etl::le_uint24_t le_v3(be_v);
etl::be_uint24_t be_v3(le_v);
CHECK_EQUAL(uint32_t(0x123456), le_v2.value());
CHECK_EQUAL(uint32_t(0x123456), be_v2.value());
CHECK_EQUAL(uint32_t(0x123456), le_v3.value());
CHECK_EQUAL(uint32_t(0x123456), be_v3.value());
// Assignment.
le_v2 = 0xFFFFFFU;
be_v2 = 0xFFFFFFU;
CHECK_EQUAL(uint32_t(0xFFFFFF), le_v2.value());
CHECK_EQUAL(uint32_t(0xFFFFFF), be_v2.value());
// Boundary values.
etl::le_uint24_t le_zero(0U);
etl::be_uint24_t be_zero(0U);
CHECK_EQUAL(uint32_t(0), le_zero.value());
CHECK_EQUAL(uint32_t(0), be_zero.value());
// Values that do not fit are truncated, like a narrowing cast.
etl::le_uint24_t le_truncated(0xAB123456U);
etl::be_uint24_t be_truncated(0xAB123456U);
CHECK_EQUAL(uint32_t(0x123456), le_truncated.value());
CHECK_EQUAL(uint32_t(0x123456), be_truncated.value());
}
//*************************************************************************
TEST(test_uint24_decode_buffer)
{
const std::array<unsigned char, 4> buffer = {0xAA, 0xBB, 0xCC, 0xDD};
etl::le_uint24_t le_v(buffer.data(), buffer.size());
etl::be_uint24_t be_v(buffer.data(), buffer.size());
CHECK_EQUAL(uint32_t(0xCCBBAA), le_v.value());
CHECK_EQUAL(uint32_t(0xAABBCC), be_v.value());
// One byte short.
CHECK_THROW(etl::le_uint24_t le_short(buffer.data(), 2U), etl::unaligned_type_buffer_size);
CHECK_THROW(etl::be_uint24_t be_short(buffer.data(), 2U), etl::unaligned_type_buffer_size);
}
#if ETL_USING_64BIT_TYPES
//*************************************************************************
TEST(test_uint40_uint48_uint56)
{
CHECK_EQUAL(5U, sizeof(etl::be_uint40_t));
CHECK_EQUAL(6U, sizeof(etl::be_uint48_t));
CHECK_EQUAL(7U, sizeof(etl::be_uint56_t));
etl::be_uint48_t be_v(0x0123456789ABULL);
etl::le_uint48_t le_v(0x0123456789ABULL);
CHECK_EQUAL(uint64_t(0x0123456789AB), be_v.value());
CHECK_EQUAL(uint64_t(0x0123456789AB), le_v.value());
CHECK_EQUAL(0x01, int(be_v.data()[0]));
CHECK_EQUAL(0xAB, int(le_v.data()[0]));
CHECK_EQUAL(uint64_t(0x000000FFFFFFFFFF), etl::be_uint40_t::Max_Value);
CHECK_EQUAL(uint64_t(0x00FFFFFFFFFFFFFF), etl::be_uint56_t::Max_Value);
}
#endif
//*************************************************************************
/// Signed integers that have no native equivalent, such as 24 bit.
//*************************************************************************
TEST(test_int24)
{
CHECK_EQUAL(3U, sizeof(etl::le_int24_t));
CHECK_EQUAL(3U, sizeof(etl::be_int24_t));
CHECK_EQUAL(3U, size_t(etl::le_int24_t::Size));
CHECK((etl::is_same<int32_t, etl::le_int24_t::value_type>::value));
CHECK_EQUAL(int32_t(8388607), etl::le_int24_t::Max_Value);
CHECK_EQUAL(int32_t(-8388608), etl::le_int24_t::Min_Value);
etl::le_int24_t le_v(0x123456);
etl::be_int24_t be_v(0x123456);
CHECK_EQUAL(int32_t(0x123456), le_v.value());
CHECK_EQUAL(int32_t(0x123456), be_v.value());
// Check the storage byte order.
CHECK_EQUAL(0x56, int(le_v.data()[0]));
CHECK_EQUAL(0x12, int(le_v.data()[2]));
CHECK_EQUAL(0x12, int(be_v.data()[0]));
CHECK_EQUAL(0x56, int(be_v.data()[2]));
// Negative values are sign extended on reading.
etl::le_int24_t le_n(-2);
etl::be_int24_t be_n(-2);
CHECK_EQUAL(int32_t(-2), le_n.value());
CHECK_EQUAL(int32_t(-2), be_n.value());
CHECK_EQUAL(0xFE, int(le_n.data()[0]));
CHECK_EQUAL(0xFF, int(le_n.data()[1]));
CHECK_EQUAL(0xFF, int(le_n.data()[2]));
CHECK_EQUAL(0xFF, int(be_n.data()[0]));
CHECK_EQUAL(0xFF, int(be_n.data()[1]));
CHECK_EQUAL(0xFE, int(be_n.data()[2]));
// Copy construction, including from the other endianness.
etl::le_int24_t le_n2(be_n);
etl::be_int24_t be_n2(le_n);
CHECK_EQUAL(int32_t(-2), le_n2.value());
CHECK_EQUAL(int32_t(-2), be_n2.value());
// Assignment.
le_n2 = -1;
be_n2 = -1;
CHECK_EQUAL(int32_t(-1), le_n2.value());
CHECK_EQUAL(int32_t(-1), be_n2.value());
// Boundary values.
etl::le_int24_t le_min(etl::le_int24_t::Min_Value);
etl::be_int24_t be_min(etl::be_int24_t::Min_Value);
etl::le_int24_t le_max(etl::le_int24_t::Max_Value);
etl::be_int24_t be_max(etl::be_int24_t::Max_Value);
CHECK_EQUAL(int32_t(-8388608), le_min.value());
CHECK_EQUAL(int32_t(-8388608), be_min.value());
CHECK_EQUAL(int32_t(8388607), le_max.value());
CHECK_EQUAL(int32_t(8388607), be_max.value());
etl::le_int24_t le_zero(0);
CHECK_EQUAL(int32_t(0), le_zero.value());
// Values that do not fit are truncated, like a narrowing cast.
etl::be_int24_t be_truncated(0x7F123456);
CHECK_EQUAL(int32_t(0x123456), be_truncated.value());
}
//*************************************************************************
TEST(test_int24_decode_buffer)
{
const std::array<unsigned char, 4> buffer = {0x80, 0x00, 0x00, 0xDD};
etl::le_int24_t le_v(buffer.data(), buffer.size());
etl::be_int24_t be_v(buffer.data(), buffer.size());
CHECK_EQUAL(int32_t(0x000080), le_v.value());
CHECK_EQUAL(int32_t(-8388608), be_v.value());
// One byte short.
CHECK_THROW(etl::le_int24_t le_short(buffer.data(), 2U), etl::unaligned_type_buffer_size);
CHECK_THROW(etl::be_int24_t be_short(buffer.data(), 2U), etl::unaligned_type_buffer_size);
}
#if ETL_USING_64BIT_TYPES
//*************************************************************************
TEST(test_int40_int48_int56)
{
CHECK_EQUAL(5U, sizeof(etl::be_int40_t));
CHECK_EQUAL(6U, sizeof(etl::be_int48_t));
CHECK_EQUAL(7U, sizeof(etl::be_int56_t));
etl::be_int48_t be_v(-1099511627775LL);
etl::le_int48_t le_v(-1099511627775LL);
CHECK_EQUAL(int64_t(-1099511627775LL), be_v.value());
CHECK_EQUAL(int64_t(-1099511627775LL), le_v.value());
CHECK_EQUAL(int64_t(549755813887LL), etl::be_int40_t::Max_Value);
CHECK_EQUAL(int64_t(-549755813888LL), etl::be_int40_t::Min_Value);
CHECK_EQUAL(int64_t(36028797018963967LL), etl::be_int56_t::Max_Value);
CHECK_EQUAL(int64_t(-36028797018963968LL), etl::be_int56_t::Min_Value);
}
#endif
//*************************************************************************
// The following tests demonstrate the 'decode' direction: given a raw byte
// buffer (e.g. as received from a file, network socket or memory-mapped
@ -625,6 +913,25 @@ namespace
CHECK_EQUAL(0x12345678U, be_v.value());
}
//*************************************************************************
/// 'value_from' is usable at compile time for the same reason: it reads
/// the buffer through the 'const unsigned char*' path.
//*************************************************************************
TEST(test_constexpr_value_from_integral)
{
static ETL_CONSTANT unsigned char le_buffer[4] = {0x78, 0x56, 0x34, 0x12};
static ETL_CONSTANT unsigned char be_buffer[4] = {0x12, 0x34, 0x56, 0x78};
constexpr uint32_t le_v = etl::le_uint32_t::value_from(le_buffer);
constexpr uint32_t be_v = etl::be_uint32_t::value_from(be_buffer);
static_assert(le_v == 0x12345678U, "le_uint32_t constexpr value_from");
static_assert(be_v == 0x12345678U, "be_uint32_t constexpr value_from");
CHECK_EQUAL(0x12345678U, le_v);
CHECK_EQUAL(0x12345678U, be_v);
}
#if ETL_USING_BUILTIN_BIT_CAST
//*************************************************************************
TEST(test_constexpr_decode_buffer_float)

View File

@ -49,6 +49,8 @@ namespace
using storage_i16_t = std::array<unsigned char, sizeof(int16_t)>;
using storage_i32_t = std::array<unsigned char, sizeof(int32_t)>;
using storage_i64_t = std::array<unsigned char, sizeof(int64_t)>;
using storage_24_t = std::array<unsigned char, 3U>;
using storage_48_t = std::array<unsigned char, 6U>;
SUITE(test_unaligned_type_ext)
{
@ -506,6 +508,148 @@ namespace
CHECK_EQUAL(sizeof(uint64_t), etl::net_uint64_ext_t::Size);
}
//*************************************************************************
/// Integers that have no native equivalent, such as 24 bit.
//*************************************************************************
TEST(test_uint24)
{
storage_24_t store_le1;
storage_24_t store_be1;
storage_24_t store_le2;
storage_24_t store_be2;
CHECK_EQUAL(3U, size_t(etl::le_uint24_ext_t::Size));
CHECK((etl::is_same<uint32_t, etl::le_uint24_ext_t::value_type>::value));
CHECK_EQUAL(uint32_t(0x00FFFFFF), etl::le_uint24_ext_t::Max_Value);
CHECK_EQUAL(uint32_t(0), etl::le_uint24_ext_t::Min_Value);
etl::le_uint24_ext_t le_v1(store_le1.data());
le_v1 = 0x123456U;
etl::be_uint24_ext_t be_v1(0x123456U, store_be1.data());
CHECK_EQUAL(uint32_t(0x123456), le_v1.value());
CHECK_EQUAL(uint32_t(0x123456), be_v1.value());
// The external buffers hold the requested byte order.
CHECK_EQUAL(0x56, int(store_le1[0]));
CHECK_EQUAL(0x12, int(store_le1[2]));
CHECK_EQUAL(0x12, int(store_be1[0]));
CHECK_EQUAL(0x56, int(store_be1[2]));
// Copy construct from the other endianness.
etl::le_uint24_ext_t le_v2(be_v1, store_le2.data());
etl::be_uint24_ext_t be_v2(le_v1, store_be2.data());
CHECK_EQUAL(uint32_t(0x123456), le_v2.value());
CHECK_EQUAL(uint32_t(0x123456), be_v2.value());
// Assignment.
le_v2 = le_v1;
be_v2 = le_v1;
CHECK_EQUAL(uint32_t(0x123456), le_v2.value());
CHECK_EQUAL(uint32_t(0x123456), be_v2.value());
// Values that do not fit are truncated.
be_v2 = 0xABCDEF12U;
CHECK_EQUAL(uint32_t(0xCDEF12), be_v2.value());
}
//*************************************************************************
TEST(test_move_construction_uint24)
{
storage_24_t store_le1;
storage_24_t store_be1;
etl::le_uint24_ext_t le_v1(0x123456U, store_le1.data());
etl::be_uint24_ext_t be_v1(0x123456U, store_be1.data());
etl::le_uint24_ext_t le_v2(etl::move(le_v1));
etl::be_uint24_ext_t be_v2(etl::move(be_v1));
CHECK_TRUE(nullptr == le_v1.data());
CHECK_TRUE(nullptr == be_v1.data());
CHECK_EQUAL(uint32_t(0x123456), le_v2.value());
CHECK_EQUAL(uint32_t(0x123456), be_v2.value());
}
//*************************************************************************
TEST(test_int24)
{
storage_24_t store_le1;
storage_24_t store_be1;
storage_24_t store_le2;
storage_24_t store_be2;
CHECK_EQUAL(3U, size_t(etl::le_int24_ext_t::Size));
CHECK((etl::is_same<int32_t, etl::le_int24_ext_t::value_type>::value));
CHECK_EQUAL(int32_t(8388607), etl::le_int24_ext_t::Max_Value);
CHECK_EQUAL(int32_t(-8388608), etl::le_int24_ext_t::Min_Value);
etl::le_int24_ext_t le_v1(store_le1.data());
le_v1 = -2;
etl::be_int24_ext_t be_v1(-2, store_be1.data());
// Negative values are sign extended on reading.
CHECK_EQUAL(int32_t(-2), le_v1.value());
CHECK_EQUAL(int32_t(-2), be_v1.value());
CHECK_EQUAL(0xFE, int(store_le1[0]));
CHECK_EQUAL(0xFF, int(store_le1[2]));
CHECK_EQUAL(0xFF, int(store_be1[0]));
CHECK_EQUAL(0xFE, int(store_be1[2]));
// Copy construct from the other endianness.
etl::le_int24_ext_t le_v2(be_v1, store_le2.data());
etl::be_int24_ext_t be_v2(le_v1, store_be2.data());
CHECK_EQUAL(int32_t(-2), le_v2.value());
CHECK_EQUAL(int32_t(-2), be_v2.value());
// Boundary values.
le_v2 = etl::le_int24_ext_t::Min_Value;
be_v2 = etl::be_int24_ext_t::Max_Value;
CHECK_EQUAL(int32_t(-8388608), le_v2.value());
CHECK_EQUAL(int32_t(8388607), be_v2.value());
le_v2 = 0;
CHECK_EQUAL(int32_t(0), le_v2.value());
}
//*************************************************************************
TEST(test_move_construction_int24)
{
storage_24_t store_le1;
storage_24_t store_be1;
etl::le_int24_ext_t le_v1(-1234567, store_le1.data());
etl::be_int24_ext_t be_v1(-1234567, store_be1.data());
etl::le_int24_ext_t le_v2(etl::move(le_v1));
etl::be_int24_ext_t be_v2(etl::move(be_v1));
CHECK_TRUE(nullptr == le_v1.data());
CHECK_TRUE(nullptr == be_v1.data());
CHECK_EQUAL(int32_t(-1234567), le_v2.value());
CHECK_EQUAL(int32_t(-1234567), be_v2.value());
}
#if ETL_USING_64BIT_TYPES
//*************************************************************************
TEST(test_uint48_int48)
{
storage_48_t store_u;
storage_48_t store_i;
etl::be_uint48_ext_t be_u(0x0123456789ABULL, store_u.data());
etl::be_int48_ext_t be_i(-1099511627775LL, store_i.data());
CHECK_EQUAL(6U, size_t(etl::be_uint48_ext_t::Size));
CHECK_EQUAL(uint64_t(0x0123456789AB), be_u.value());
CHECK_EQUAL(int64_t(-1099511627775LL), be_i.value());
}
#endif
#if ETL_HAS_CONSTEXPR_ENDIANNESS
//*************************************************************************
TEST(test_host_sizes)
@ -1528,6 +1672,106 @@ namespace
CHECK_EQUAL(0x12, bev0);
CHECK_EQUAL(0x34, bev1);
}
//*************************************************************************
TEST(test_shared_storage_copy_construction_uint24)
{
storage_24_t store;
etl::be_uint24_ext_t be_v(0x123456, store.data());
// Reinterpret the same buffer with the opposite endianness.
etl::le_uint24_ext_t le_v(be_v, store.data());
CHECK_EQUAL(0x56, int(store[0]));
CHECK_EQUAL(0x34, int(store[1]));
CHECK_EQUAL(0x12, int(store[2]));
CHECK_EQUAL(0x123456, le_v.value());
}
//*************************************************************************
TEST(test_shared_storage_copy_construction_int24)
{
storage_24_t store;
etl::be_int24_ext_t be_v(-0x123456, store.data());
etl::le_int24_ext_t le_v(be_v, store.data());
CHECK_EQUAL(-0x123456, le_v.value());
}
//*************************************************************************
TEST(test_shared_storage_copy_assignment_uint24)
{
storage_24_t store;
etl::be_uint24_ext_t be_v(0x123456, store.data());
etl::le_uint24_ext_t le_v(store.data());
le_v = be_v;
CHECK_EQUAL(0x56, int(store[0]));
CHECK_EQUAL(0x34, int(store[1]));
CHECK_EQUAL(0x12, int(store[2]));
CHECK_EQUAL(0x123456, le_v.value());
}
//*************************************************************************
TEST(test_shared_storage_copy_assignment_int24)
{
storage_24_t store;
etl::be_int24_ext_t be_v(-0x123456, store.data());
etl::le_int24_ext_t le_v(store.data());
le_v = be_v;
CHECK_EQUAL(-0x123456, le_v.value());
}
//*************************************************************************
TEST(test_shared_storage_copy_assignment_uint32)
{
storage_i32_t store;
etl::be_uint32_ext_t be_v(0x12345678, store.data());
etl::le_uint32_ext_t le_v(store.data());
le_v = be_v;
CHECK_EQUAL(0x78, int(store[0]));
CHECK_EQUAL(0x56, int(store[1]));
CHECK_EQUAL(0x34, int(store[2]));
CHECK_EQUAL(0x12, int(store[3]));
CHECK_EQUAL(0x12345678, le_v.value());
}
//*************************************************************************
TEST(test_shared_storage_copy_assignment_same_endianness)
{
storage_i32_t store;
etl::le_uint32_ext_t le_v1(0x12345678, store.data());
etl::le_uint32_ext_t le_v2(store.data());
le_v2 = le_v1;
CHECK_EQUAL(0x12345678, le_v2.value());
}
//*************************************************************************
TEST(test_shared_storage_copy_assignment_float)
{
storage_f_t store;
etl::be_float_ext_t be_v(3.1415927f, store.data());
etl::le_float_ext_t le_v(store.data());
le_v = be_v;
CHECK_EQUAL(3.1415927f, le_v.value());
}
}
} // namespace

View File

@ -6304,7 +6304,26 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC C++20 - Force C++03|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC C++20 - Force C++03 - No virtual messages|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\syntax_check\clamped_value.h.t.cpp" />
<ClCompile Include="..\syntax_check\clamped_value.h.t.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC C++14|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC C++20|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC C++20 - No virtual imessage|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC C++ 20 - No Tests|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC C++23 - No STL|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC C++23|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC C++20 - No STL|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release MSVC C++20 - No STL - Optimised -O2|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release MSVC C++20 - No STL - Optimised -O2 - Sanitiser|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC C++20 - Force C++03 - No virtual messages|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC C++17|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC C++17 - No STL|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release MSVC C++20 - Optimised O2|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC C++20 - No virtual messages|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC C++14 - No STL|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC C++20 - Force C++03|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Clang C++20|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Clang C++20 - Optimised -O2|Win32'">true</ExcludedFromBuild>
</ClCompile>
<ClCompile Include="..\syntax_check\cyclic_value.h.t.cpp">
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug MSVC C++20|Win32'">true</ExcludedFromBuild>
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug Clang C++20|Win32'">true</ExcludedFromBuild>
@ -11807,4 +11826,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -4124,4 +4124,4 @@
<Filter>Resource Files\Images</Filter>
</Image>
</ItemGroup>
</Project>
</Project>