From 3f1aa09454304b6c9dd206d0252def42c2c4a576 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 11 Sep 2023 11:15:49 +0100 Subject: [PATCH 01/33] Work in progress --- include/etl/chrono.h | 39 +++++ include/etl/hash.h | 4 +- include/etl/private/chrono/day.h | 224 ++++++++++++++++++++++++++ include/etl/private/chrono/duration.h | 139 ++++++++++++++++ test/CMakeLists.txt | 3 + test/test_chrono_day.cpp | 216 +++++++++++++++++++++++++ test/vs2022/etl.vcxproj | 3 + test/vs2022/etl.vcxproj.filters | 15 ++ 8 files changed, 641 insertions(+), 2 deletions(-) create mode 100644 include/etl/chrono.h create mode 100644 include/etl/private/chrono/day.h create mode 100644 include/etl/private/chrono/duration.h create mode 100644 test/test_chrono_day.cpp diff --git a/include/etl/chrono.h b/include/etl/chrono.h new file mode 100644 index 00000000..0cf26e5b --- /dev/null +++ b/include/etl/chrono.h @@ -0,0 +1,39 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CHRONO_INCLUDED +#define ETL_CHRONO_INCLUDED + +#include "platform.h" + +#include "private/chrono/duration.h" +#include "private/chrono/day.h" + +#endif diff --git a/include/etl/hash.h b/include/etl/hash.h index 214ec8c5..9d012941 100644 --- a/include/etl/hash.h +++ b/include/etl/hash.h @@ -156,8 +156,8 @@ namespace etl /// Specialisation for signed char. ///\ingroup hash //*************************************************************************** - template<> struct - hash + template <> + struct hash { ETL_STATIC_ASSERT(sizeof(size_t) >= sizeof(signed char), "size_t smaller than type"); diff --git a/include/etl/private/chrono/day.h b/include/etl/private/chrono/day.h new file mode 100644 index 00000000..61d19e8b --- /dev/null +++ b/include/etl/private/chrono/day.h @@ -0,0 +1,224 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CHRONO_DAY_INCLUDED +#define ETL_CHRONO_DAY_INCLUDED + +#include "../../platform.h" +#include "../../hash.h" + +#include "duration.h" + +#include + +namespace etl +{ + namespace chrono + { + //*********************************************************************** + /// day + //*********************************************************************** + class day + { + public: + + //*********************************************************************** + ETL_CONSTEXPR day() + : value(0) + { + } + + //*********************************************************************** + ETL_CONSTEXPR day(unsigned value_) + : value(value_) + { + } + + //*********************************************************************** + ETL_CONSTEXPR day(const etl::chrono::day& other) + : value(other.value) + { + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator =(const etl::chrono::day& rhs) + { + value = rhs.value; + + return *this; + } + + //*********************************************************************** + template + ETL_CONSTEXPR etl::chrono::day& operator =(const etl::chrono::duration& rhs) + { + value = etl::chrono::duration_cast(rhs); + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator ++() ETL_NOEXCEPT + { + ++value; + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::day operator ++(int) ETL_NOEXCEPT + { + const etl::chrono::day temp = *this; + ++value; + + return temp; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator --() ETL_NOEXCEPT + { + --value; + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::day operator --(int) ETL_NOEXCEPT + { + const etl::chrono::day temp = *this; + --value; + + return temp; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator +=(const etl::chrono::days& ds) ETL_NOEXCEPT + { + value += static_cast(ds.count()); + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator -=(const etl::chrono::days& ds) ETL_NOEXCEPT + { + value -= static_cast(ds.count()); + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + { + return (value >= 1U) && (value <= 31U); + } + + //*********************************************************************** + ETL_CONSTEXPR operator unsigned() const ETL_NOEXCEPT + { + return static_cast(value); + } + + private: + + unsigned char value; + }; + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day operator +(const etl::chrono::day& d, const etl::chrono::days& ds) ETL_NOEXCEPT + { + etl::chrono::day result(d); + + result += ds; + + return result; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day operator +(const etl::chrono::days& ds, const etl::chrono::day& d) ETL_NOEXCEPT + { + etl::chrono::day result(d); + + result += ds; + + return result; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day operator -(const etl::chrono::day& d, const etl::chrono::days& ds) ETL_NOEXCEPT + { + etl::chrono::day result(d); + + result -= ds; + + return result; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::days operator -(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + etl::chrono::days result; + + return etl::chrono::days(static_cast(d1) - static_cast(d2)); + } + } + + //************************************************************************* + /// Hash function. + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::day& d) const + { + unsigned value = d; + const uint8_t* p = reinterpret_cast(&value); + + return etl::private_hash::generic_hash(p, p + sizeof(unsigned)); + } + }; +#endif +} + +namespace etl +{ + namespace literals + { + namespace chrono_literals + { + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day operator ""_d(unsigned long long d) ETL_NOEXCEPT + { + return etl::chrono::day(d); + } + } + } +} + +#endif \ No newline at end of file diff --git a/include/etl/private/chrono/duration.h b/include/etl/private/chrono/duration.h new file mode 100644 index 00000000..3e4ec95e --- /dev/null +++ b/include/etl/private/chrono/duration.h @@ -0,0 +1,139 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CHRONO_DURATION_INCLUDED +#define ETL_CHRONO_DURATION_INCLUDED + +#include "../../platform.h" +#include "../../ratio.h" +#include "../../static_assert.h" +#include "../../limits.h" + +namespace etl +{ + namespace chrono + { + //*********************************************************************** + /// duration + //*********************************************************************** + template > + class duration + { + public: + + //*********************************************************************** + ETL_CONSTEXPR duration() ETL_NOEXCEPT + { + } + + //*********************************************************************** + ETL_CONSTEXPR duration(const etl::chrono::duration& other) ETL_NOEXCEPT + : value(other.value) + { + } + + //*********************************************************************** + template< typename TValue2 > + ETL_CONSTEXPR explicit duration(const TValue2& value_) ETL_NOEXCEPT + : value(static_cast(value_)) + { + } + + //*********************************************************************** + template< typename TValue2, typename TPeriod2 > + ETL_CONSTEXPR duration(const etl::chrono::duration& other) ETL_NOEXCEPT + : value(static_cast(other.value)) + { + ETL_STATIC_ASSERT(!(etl::is_integral::value && etl::is_floating_point::value), "Cannot convert duration from floating point to integral"); + } + + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::duration< TValue, TPeriod> zero() ETL_NOEXCEPT + { + return etl::chrono::duration{ 0, TPeriod()}; + } + + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::duration min() ETL_NOEXCEPT + { + return etl::chrono::duration { etl::numeric_limits::min() }; + } + + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::duration max() ETL_NOEXCEPT + { + return etl::chrono::duration{ etl::numeric_limits::max() }; + } + + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR TValue count() const + { + return value; + } + + private: + + TValue value; + //TPeriod period; + }; + + //*********************************************************************** + /// Duration types + //*********************************************************************** +#if (ETL_USING_64BIT_TYPES) + typedef etl::chrono::duration nanoseconds; + typedef etl::chrono::duration microseconds; + typedef etl::chrono::duration milliseconds; + typedef etl::chrono::duration > seconds; +#else + typedef etl::chrono::duration nanoseconds; + typedef etl::chrono::duration microseconds; + typedef etl::chrono::duration milliseconds; + typedef etl::chrono::duration > seconds; +#endif + typedef etl::chrono::duration > minutes; + typedef etl::chrono::duration > hours; + typedef etl::chrono::duration > days; + typedef etl::chrono::duration > weeks; + typedef etl::chrono::duration > months; + typedef etl::chrono::duration > years; + + //*********************************************************************** + /// duration_cast + //*********************************************************************** + template + ETL_CONSTEXPR TToDuration duration_cast(const etl::chrono::duration& d) + { + return TToDuration(); + } + } +} + +#endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index af3359bd..85265ab1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -45,6 +45,9 @@ add_executable(etl_tests test_callback_timer_locked.cpp test_char_traits.cpp test_checksum.cpp + + test_chrono_day.cpp + test_circular_buffer.cpp test_circular_buffer_external_buffer.cpp test_circular_iterator.cpp diff --git a/test/test_chrono_day.cpp b/test/test_chrono_day.cpp new file mode 100644 index 00000000..f8a3d453 --- /dev/null +++ b/test/test_chrono_day.cpp @@ -0,0 +1,216 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#if ETL_USING_CPP20 + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include + +namespace +{ + SUITE(test_chrono_day) + { + //************************************************************************* + TEST(test_default_constructor) + { + std::chrono::day std_day; + etl::chrono::day day; + + CHECK_EQUAL(std_day.ok(), day.ok()); + } + + //************************************************************************* + TEST(test_constructor_in_range) + { + for (unsigned i = 0U; i < 256; ++i) + { + std::chrono::day std_day(i); + etl::chrono::day day(i); + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_pre_increment) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + for (int i = 0; i < 255; ++i) + { + ++std_day; + ++day; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_post_increment) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + for (int i = 0; i < 255; ++i) + { + std::chrono::day std_last_day = std_day++; + etl::chrono::day last_day = day++; + + CHECK_EQUAL(std_last_day.ok(), last_day.ok()); + CHECK_EQUAL(unsigned(std_last_day), unsigned(last_day)); + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_pre_decrement) + { + std::chrono::day std_day(256); + etl::chrono::day day(256); + + for (int i = 0; i < 255; ++i) + { + --std_day; + --day; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_post_decrement) + { + std::chrono::day std_day(256); + etl::chrono::day day(256); + + for (int i = 0; i < 255; ++i) + { + std::chrono::day std_last_day = std_day--; + etl::chrono::day last_day = day--; + + CHECK_EQUAL(std_last_day.ok(), last_day.ok()); + CHECK_EQUAL(unsigned(std_last_day), unsigned(last_day)); + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_plus_equal_days) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + std::chrono::days std_days(2); + etl::chrono::days days(2); + + for (int i = 0; i < 128; ++i) + { + std_day += std_days; + day += days; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_plus_days) + { + std::chrono::day std_day1(0); + std::chrono::day std_day2(0); + etl::chrono::day day1(0); + etl::chrono::day day2(0); + + std::chrono::days std_days(2); + etl::chrono::days days(2); + + for (int i = 0; i < 128; ++i) + { + std_day1 = std_days + std_day1; + std_day2 = std_day2 + std_days; + + day1 = days + day1; + day2 = day2 + days; + + CHECK_EQUAL(std_day1.ok(), day1.ok()); + CHECK_EQUAL(std_day2.ok(), day2.ok()); + CHECK_EQUAL(unsigned(std_day1), unsigned(day1)); + CHECK_EQUAL(unsigned(std_day2), unsigned(day2)); + } + } + + //************************************************************************* + TEST(test_minus_equal_days) + { + std::chrono::day std_day(256); + etl::chrono::day day(256); + + std::chrono::days std_days(2); + etl::chrono::days days(2); + + for (int i = 0; i < 128; ++i) + { + std_day -= std_days; + day -= days; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_literal_days) + { + using namespace std::literals::chrono_literals; + using namespace etl::literals::chrono_literals; + + std::chrono::day std_day = 25d; + etl::chrono::day day = 25_d; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + }; +} + +#endif \ No newline at end of file diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 96785631..6809a26e 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -2942,6 +2942,7 @@ + @@ -3000,6 +3001,7 @@ + @@ -14337,6 +14339,7 @@ + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index e96c1b61..ee1bc81b 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -220,6 +220,12 @@ {c75cedd3-8b6c-4662-b965-aecbe7fd5d1c} + + {46e23f29-ce01-418f-8331-9c739774414c} + + + {1b1afa65-108a-4665-9e74-3c67a27ff917} + @@ -1362,6 +1368,12 @@ ETL\Utilities + + ETL\Utilities + + + ETL\Private + @@ -3425,6 +3437,9 @@ Tests\Misc + + Tests\Chrono + From 8c78fdab0422a7bf5956fa2433d0d4bbd260a3f6 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 11 Sep 2023 11:15:49 +0100 Subject: [PATCH 02/33] Work in progress --- include/etl/chrono.h | 39 ++++ include/etl/hash.h | 4 +- include/etl/private/chrono/day.h | 271 +++++++++++++++++++++++ include/etl/private/chrono/duration.h | 139 ++++++++++++ test/CMakeLists.txt | 3 + test/test_chrono_day.cpp | 305 ++++++++++++++++++++++++++ test/vs2022/etl.vcxproj | 3 + test/vs2022/etl.vcxproj.filters | 15 ++ 8 files changed, 777 insertions(+), 2 deletions(-) create mode 100644 include/etl/chrono.h create mode 100644 include/etl/private/chrono/day.h create mode 100644 include/etl/private/chrono/duration.h create mode 100644 test/test_chrono_day.cpp diff --git a/include/etl/chrono.h b/include/etl/chrono.h new file mode 100644 index 00000000..0cf26e5b --- /dev/null +++ b/include/etl/chrono.h @@ -0,0 +1,39 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CHRONO_INCLUDED +#define ETL_CHRONO_INCLUDED + +#include "platform.h" + +#include "private/chrono/duration.h" +#include "private/chrono/day.h" + +#endif diff --git a/include/etl/hash.h b/include/etl/hash.h index 214ec8c5..9d012941 100644 --- a/include/etl/hash.h +++ b/include/etl/hash.h @@ -156,8 +156,8 @@ namespace etl /// Specialisation for signed char. ///\ingroup hash //*************************************************************************** - template<> struct - hash + template <> + struct hash { ETL_STATIC_ASSERT(sizeof(size_t) >= sizeof(signed char), "size_t smaller than type"); diff --git a/include/etl/private/chrono/day.h b/include/etl/private/chrono/day.h new file mode 100644 index 00000000..b04d3898 --- /dev/null +++ b/include/etl/private/chrono/day.h @@ -0,0 +1,271 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CHRONO_DAY_INCLUDED +#define ETL_CHRONO_DAY_INCLUDED + +#include "../../platform.h" +#include "../../hash.h" + +#include "duration.h" + +#include + +namespace etl +{ + namespace chrono + { + //*********************************************************************** + /// day + //*********************************************************************** + class day + { + public: + + //*********************************************************************** + ETL_CONSTEXPR day() + : value(0) + { + } + + //*********************************************************************** + ETL_CONSTEXPR day(unsigned value_) + : value(value_) + { + } + + //*********************************************************************** + ETL_CONSTEXPR day(const etl::chrono::day& other) + : value(other.value) + { + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator =(const etl::chrono::day& rhs) + { + value = rhs.value; + + return *this; + } + + //*********************************************************************** + template + ETL_CONSTEXPR etl::chrono::day& operator =(const etl::chrono::duration& rhs) + { + value = etl::chrono::duration_cast(rhs); + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator ++() ETL_NOEXCEPT + { + ++value; + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::day operator ++(int) ETL_NOEXCEPT + { + const etl::chrono::day temp = *this; + ++value; + + return temp; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator --() ETL_NOEXCEPT + { + --value; + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::day operator --(int) ETL_NOEXCEPT + { + const etl::chrono::day temp = *this; + --value; + + return temp; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator +=(const etl::chrono::days& ds) ETL_NOEXCEPT + { + value += static_cast(ds.count()); + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator -=(const etl::chrono::days& ds) ETL_NOEXCEPT + { + value -= static_cast(ds.count()); + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + { + return (value >= 1U) && (value <= 31U); + } + + //*********************************************************************** + ETL_CONSTEXPR operator unsigned() const ETL_NOEXCEPT + { + return static_cast(value); + } + + private: + + unsigned char value; + }; + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day operator +(const etl::chrono::day& d, const etl::chrono::days& ds) ETL_NOEXCEPT + { + etl::chrono::day result(d); + + result += ds; + + return result; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day operator +(const etl::chrono::days& ds, const etl::chrono::day& d) ETL_NOEXCEPT + { + etl::chrono::day result(d); + + result += ds; + + return result; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day operator -(const etl::chrono::day& d, const etl::chrono::days& ds) ETL_NOEXCEPT + { + etl::chrono::day result(d); + + result -= ds; + + return result; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::days operator -(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return etl::chrono::days(static_cast(static_cast(d1)) - + static_cast(static_cast(d2))); + } + + //*********************************************************************** + ETL_CONSTEXPR bool operator ==(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) == static_cast(d2)); + } + + //*********************************************************************** + ETL_CONSTEXPR bool operator !=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return !(d1 == d2); + } + + //*********************************************************************** + ETL_CONSTEXPR bool operator <(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) < static_cast(d2)); + } + + //*********************************************************************** + ETL_CONSTEXPR bool operator <=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) <= static_cast(d2)); + } + + //*********************************************************************** + ETL_CONSTEXPR bool operator >(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) > static_cast(d2)); + } + + //*********************************************************************** + ETL_CONSTEXPR bool operator >=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) >= static_cast(d2)); + } + + //*********************************************************************** +#if ETL_USING_CPP20 + ETL_CONSTEXPR auto operator <=>(const etl::chrono::day& d1, const etl::chrono::day& d2) + { + return (static_cast(d1) <=> static_cast(d2)); + } +#endif + } + + //************************************************************************* + /// Hash function. + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::day& d) const + { + unsigned value = d; + const uint8_t* p = reinterpret_cast(&value); + + return etl::private_hash::generic_hash(p, p + sizeof(unsigned)); + } + }; +#endif +} + +#if ETL_USING_CPP11 +namespace etl +{ + namespace literals + { + namespace chrono_literals + { + //*********************************************************************** + /// Literal for days + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day operator ""_d(unsigned long long d) ETL_NOEXCEPT + { + return etl::chrono::day(d); + } + } + } +} +#endif + +#endif \ No newline at end of file diff --git a/include/etl/private/chrono/duration.h b/include/etl/private/chrono/duration.h new file mode 100644 index 00000000..3e4ec95e --- /dev/null +++ b/include/etl/private/chrono/duration.h @@ -0,0 +1,139 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CHRONO_DURATION_INCLUDED +#define ETL_CHRONO_DURATION_INCLUDED + +#include "../../platform.h" +#include "../../ratio.h" +#include "../../static_assert.h" +#include "../../limits.h" + +namespace etl +{ + namespace chrono + { + //*********************************************************************** + /// duration + //*********************************************************************** + template > + class duration + { + public: + + //*********************************************************************** + ETL_CONSTEXPR duration() ETL_NOEXCEPT + { + } + + //*********************************************************************** + ETL_CONSTEXPR duration(const etl::chrono::duration& other) ETL_NOEXCEPT + : value(other.value) + { + } + + //*********************************************************************** + template< typename TValue2 > + ETL_CONSTEXPR explicit duration(const TValue2& value_) ETL_NOEXCEPT + : value(static_cast(value_)) + { + } + + //*********************************************************************** + template< typename TValue2, typename TPeriod2 > + ETL_CONSTEXPR duration(const etl::chrono::duration& other) ETL_NOEXCEPT + : value(static_cast(other.value)) + { + ETL_STATIC_ASSERT(!(etl::is_integral::value && etl::is_floating_point::value), "Cannot convert duration from floating point to integral"); + } + + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::duration< TValue, TPeriod> zero() ETL_NOEXCEPT + { + return etl::chrono::duration{ 0, TPeriod()}; + } + + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::duration min() ETL_NOEXCEPT + { + return etl::chrono::duration { etl::numeric_limits::min() }; + } + + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::duration max() ETL_NOEXCEPT + { + return etl::chrono::duration{ etl::numeric_limits::max() }; + } + + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR TValue count() const + { + return value; + } + + private: + + TValue value; + //TPeriod period; + }; + + //*********************************************************************** + /// Duration types + //*********************************************************************** +#if (ETL_USING_64BIT_TYPES) + typedef etl::chrono::duration nanoseconds; + typedef etl::chrono::duration microseconds; + typedef etl::chrono::duration milliseconds; + typedef etl::chrono::duration > seconds; +#else + typedef etl::chrono::duration nanoseconds; + typedef etl::chrono::duration microseconds; + typedef etl::chrono::duration milliseconds; + typedef etl::chrono::duration > seconds; +#endif + typedef etl::chrono::duration > minutes; + typedef etl::chrono::duration > hours; + typedef etl::chrono::duration > days; + typedef etl::chrono::duration > weeks; + typedef etl::chrono::duration > months; + typedef etl::chrono::duration > years; + + //*********************************************************************** + /// duration_cast + //*********************************************************************** + template + ETL_CONSTEXPR TToDuration duration_cast(const etl::chrono::duration& d) + { + return TToDuration(); + } + } +} + +#endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index af3359bd..85265ab1 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -45,6 +45,9 @@ add_executable(etl_tests test_callback_timer_locked.cpp test_char_traits.cpp test_checksum.cpp + + test_chrono_day.cpp + test_circular_buffer.cpp test_circular_buffer_external_buffer.cpp test_circular_iterator.cpp diff --git a/test/test_chrono_day.cpp b/test/test_chrono_day.cpp new file mode 100644 index 00000000..e6de125c --- /dev/null +++ b/test/test_chrono_day.cpp @@ -0,0 +1,305 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#if ETL_USING_CPP20 + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include + +namespace +{ + SUITE(test_chrono_day) + { + //************************************************************************* + TEST(test_default_constructor) + { + std::chrono::day std_day; + etl::chrono::day day; + + CHECK_EQUAL(std_day.ok(), day.ok()); + } + + //************************************************************************* + TEST(test_constructor_in_range) + { + for (unsigned i = 0U; i < 256; ++i) + { + std::chrono::day std_day(i); + etl::chrono::day day(i); + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_pre_increment) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + for (int i = 0; i < 255; ++i) + { + ++std_day; + ++day; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_post_increment) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + for (int i = 0; i < 255; ++i) + { + std::chrono::day std_last_day = std_day++; + etl::chrono::day last_day = day++; + + CHECK_EQUAL(std_last_day.ok(), last_day.ok()); + CHECK_EQUAL(unsigned(std_last_day), unsigned(last_day)); + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_pre_decrement) + { + std::chrono::day std_day(256); + etl::chrono::day day(256); + + for (int i = 0; i < 255; ++i) + { + --std_day; + --day; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_post_decrement) + { + std::chrono::day std_day(256); + etl::chrono::day day(256); + + for (int i = 0; i < 255; ++i) + { + std::chrono::day std_last_day = std_day--; + etl::chrono::day last_day = day--; + + CHECK_EQUAL(std_last_day.ok(), last_day.ok()); + CHECK_EQUAL(unsigned(std_last_day), unsigned(last_day)); + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_plus_equal_days) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + std::chrono::days std_days(2); + etl::chrono::days days(2); + + for (int i = 0; i < 128; ++i) + { + std_day += std_days; + day += days; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_day_plus_days) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + std::chrono::days std_days(2); + etl::chrono::days days(2); + + for (int i = 0; i < 128; ++i) + { + std_day = std_day + std_days; + day = day + days; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_days_plus_day) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + std::chrono::days std_days(2); + etl::chrono::days days(2); + + for (int i = 0; i < 128; ++i) + { + std_day = std_days + std_day; + day = days + day; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_minus_equal_days) + { + std::chrono::day std_day(256); + etl::chrono::day day(256); + + std::chrono::days std_days(2); + etl::chrono::days days(2); + + for (int i = 0; i < 128; ++i) + { + std_day -= std_days; + day -= days; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_day_minus_days) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + std::chrono::days std_days(2); + etl::chrono::days days(2); + + for (int i = 0; i < 128; ++i) + { + std_day = std_day - std_days; + day = day - days; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_day_minus_day) + { + for (int i = 1; i < 31; ++i) + { + std::chrono::day std_day1(i); + std::chrono::day std_day2(31 - i); + + etl::chrono::day day1(i); + etl::chrono::day day2(31 - i); + + std::chrono::days std_days = std_day1 - std_day2; + etl::chrono::days days = day1 - day2; + + CHECK_EQUAL(std_days.count(), days.count()); + } + } + + //************************************************************************* + TEST(test_literal_days) + { + using namespace std::literals::chrono_literals; + using namespace etl::literals::chrono_literals; + + std::chrono::day std_day = 25d; + etl::chrono::day day = 25_d; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + + //************************************************************************* + TEST(test_day_comparison_operators) + { + etl::chrono::day day10(10); + etl::chrono::day day20(20); + + CHECK_TRUE(day10 == day10); + CHECK_FALSE(day10 != day10); + CHECK_TRUE(day10 < day20); + CHECK_FALSE(day10 < day10); + CHECK_FALSE(day20 < day10); + CHECK_TRUE(day10 <= day20); + CHECK_TRUE(day10 <= day10); + CHECK_FALSE(day20 <= day10); + CHECK_FALSE(day10 > day20); + CHECK_FALSE(day10 > day10); + CHECK_TRUE(day20 > day10); + CHECK_FALSE(day10 >= day20); + CHECK_TRUE(day10 >= day10); + CHECK_TRUE(day20 >= day10); + +#if ETL_USING_CPP20 + CHECK_TRUE((day10 <=> day10) == 0); + CHECK_TRUE((day10 <=> day20) < 0); + CHECK_TRUE((day20 <=> day10) > 0); +#endif + } + + //************************************************************************* + TEST(test_day_hash) + { + etl::chrono::day day(10); + + size_t h = 0; + + h = etl::hash()(day); + + CHECK_TRUE(h != 0); + } + }; +} + +#endif \ No newline at end of file diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 96785631..6809a26e 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -2942,6 +2942,7 @@ + @@ -3000,6 +3001,7 @@ + @@ -14337,6 +14339,7 @@ + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index e96c1b61..ee1bc81b 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -220,6 +220,12 @@ {c75cedd3-8b6c-4662-b965-aecbe7fd5d1c} + + {46e23f29-ce01-418f-8331-9c739774414c} + + + {1b1afa65-108a-4665-9e74-3c67a27ff917} + @@ -1362,6 +1368,12 @@ ETL\Utilities + + ETL\Utilities + + + ETL\Private + @@ -3425,6 +3437,9 @@ Tests\Misc + + Tests\Chrono + From fc0576ad9512f284bbbc726a56f65de2e83b1bf2 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 11 Sep 2023 11:15:49 +0100 Subject: [PATCH 03/33] Work in progress --- include/etl/chrono.h | 39 ++++ include/etl/hash.h | 4 +- include/etl/private/chrono/day.h | 271 +++++++++++++++++++++++ include/etl/private/chrono/duration.h | 139 ++++++++++++ test/CMakeLists.txt | 3 + test/test_chrono_day.cpp | 305 ++++++++++++++++++++++++++ test/vs2022/etl.vcxproj | 3 + test/vs2022/etl.vcxproj.filters | 15 ++ 8 files changed, 777 insertions(+), 2 deletions(-) create mode 100644 include/etl/chrono.h create mode 100644 include/etl/private/chrono/day.h create mode 100644 include/etl/private/chrono/duration.h create mode 100644 test/test_chrono_day.cpp diff --git a/include/etl/chrono.h b/include/etl/chrono.h new file mode 100644 index 00000000..0cf26e5b --- /dev/null +++ b/include/etl/chrono.h @@ -0,0 +1,39 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CHRONO_INCLUDED +#define ETL_CHRONO_INCLUDED + +#include "platform.h" + +#include "private/chrono/duration.h" +#include "private/chrono/day.h" + +#endif diff --git a/include/etl/hash.h b/include/etl/hash.h index 8066a012..2397f025 100644 --- a/include/etl/hash.h +++ b/include/etl/hash.h @@ -159,8 +159,8 @@ namespace etl /// Specialisation for signed char. ///\ingroup hash //*************************************************************************** - template<> struct - hash + template <> + struct hash { ETL_STATIC_ASSERT(sizeof(size_t) >= sizeof(signed char), "size_t smaller than type"); diff --git a/include/etl/private/chrono/day.h b/include/etl/private/chrono/day.h new file mode 100644 index 00000000..b04d3898 --- /dev/null +++ b/include/etl/private/chrono/day.h @@ -0,0 +1,271 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CHRONO_DAY_INCLUDED +#define ETL_CHRONO_DAY_INCLUDED + +#include "../../platform.h" +#include "../../hash.h" + +#include "duration.h" + +#include + +namespace etl +{ + namespace chrono + { + //*********************************************************************** + /// day + //*********************************************************************** + class day + { + public: + + //*********************************************************************** + ETL_CONSTEXPR day() + : value(0) + { + } + + //*********************************************************************** + ETL_CONSTEXPR day(unsigned value_) + : value(value_) + { + } + + //*********************************************************************** + ETL_CONSTEXPR day(const etl::chrono::day& other) + : value(other.value) + { + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator =(const etl::chrono::day& rhs) + { + value = rhs.value; + + return *this; + } + + //*********************************************************************** + template + ETL_CONSTEXPR etl::chrono::day& operator =(const etl::chrono::duration& rhs) + { + value = etl::chrono::duration_cast(rhs); + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator ++() ETL_NOEXCEPT + { + ++value; + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::day operator ++(int) ETL_NOEXCEPT + { + const etl::chrono::day temp = *this; + ++value; + + return temp; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator --() ETL_NOEXCEPT + { + --value; + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::day operator --(int) ETL_NOEXCEPT + { + const etl::chrono::day temp = *this; + --value; + + return temp; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator +=(const etl::chrono::days& ds) ETL_NOEXCEPT + { + value += static_cast(ds.count()); + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator -=(const etl::chrono::days& ds) ETL_NOEXCEPT + { + value -= static_cast(ds.count()); + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + { + return (value >= 1U) && (value <= 31U); + } + + //*********************************************************************** + ETL_CONSTEXPR operator unsigned() const ETL_NOEXCEPT + { + return static_cast(value); + } + + private: + + unsigned char value; + }; + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day operator +(const etl::chrono::day& d, const etl::chrono::days& ds) ETL_NOEXCEPT + { + etl::chrono::day result(d); + + result += ds; + + return result; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day operator +(const etl::chrono::days& ds, const etl::chrono::day& d) ETL_NOEXCEPT + { + etl::chrono::day result(d); + + result += ds; + + return result; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day operator -(const etl::chrono::day& d, const etl::chrono::days& ds) ETL_NOEXCEPT + { + etl::chrono::day result(d); + + result -= ds; + + return result; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::days operator -(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return etl::chrono::days(static_cast(static_cast(d1)) - + static_cast(static_cast(d2))); + } + + //*********************************************************************** + ETL_CONSTEXPR bool operator ==(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) == static_cast(d2)); + } + + //*********************************************************************** + ETL_CONSTEXPR bool operator !=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return !(d1 == d2); + } + + //*********************************************************************** + ETL_CONSTEXPR bool operator <(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) < static_cast(d2)); + } + + //*********************************************************************** + ETL_CONSTEXPR bool operator <=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) <= static_cast(d2)); + } + + //*********************************************************************** + ETL_CONSTEXPR bool operator >(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) > static_cast(d2)); + } + + //*********************************************************************** + ETL_CONSTEXPR bool operator >=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) >= static_cast(d2)); + } + + //*********************************************************************** +#if ETL_USING_CPP20 + ETL_CONSTEXPR auto operator <=>(const etl::chrono::day& d1, const etl::chrono::day& d2) + { + return (static_cast(d1) <=> static_cast(d2)); + } +#endif + } + + //************************************************************************* + /// Hash function. + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::day& d) const + { + unsigned value = d; + const uint8_t* p = reinterpret_cast(&value); + + return etl::private_hash::generic_hash(p, p + sizeof(unsigned)); + } + }; +#endif +} + +#if ETL_USING_CPP11 +namespace etl +{ + namespace literals + { + namespace chrono_literals + { + //*********************************************************************** + /// Literal for days + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day operator ""_d(unsigned long long d) ETL_NOEXCEPT + { + return etl::chrono::day(d); + } + } + } +} +#endif + +#endif \ No newline at end of file diff --git a/include/etl/private/chrono/duration.h b/include/etl/private/chrono/duration.h new file mode 100644 index 00000000..3e4ec95e --- /dev/null +++ b/include/etl/private/chrono/duration.h @@ -0,0 +1,139 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CHRONO_DURATION_INCLUDED +#define ETL_CHRONO_DURATION_INCLUDED + +#include "../../platform.h" +#include "../../ratio.h" +#include "../../static_assert.h" +#include "../../limits.h" + +namespace etl +{ + namespace chrono + { + //*********************************************************************** + /// duration + //*********************************************************************** + template > + class duration + { + public: + + //*********************************************************************** + ETL_CONSTEXPR duration() ETL_NOEXCEPT + { + } + + //*********************************************************************** + ETL_CONSTEXPR duration(const etl::chrono::duration& other) ETL_NOEXCEPT + : value(other.value) + { + } + + //*********************************************************************** + template< typename TValue2 > + ETL_CONSTEXPR explicit duration(const TValue2& value_) ETL_NOEXCEPT + : value(static_cast(value_)) + { + } + + //*********************************************************************** + template< typename TValue2, typename TPeriod2 > + ETL_CONSTEXPR duration(const etl::chrono::duration& other) ETL_NOEXCEPT + : value(static_cast(other.value)) + { + ETL_STATIC_ASSERT(!(etl::is_integral::value && etl::is_floating_point::value), "Cannot convert duration from floating point to integral"); + } + + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::duration< TValue, TPeriod> zero() ETL_NOEXCEPT + { + return etl::chrono::duration{ 0, TPeriod()}; + } + + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::duration min() ETL_NOEXCEPT + { + return etl::chrono::duration { etl::numeric_limits::min() }; + } + + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::duration max() ETL_NOEXCEPT + { + return etl::chrono::duration{ etl::numeric_limits::max() }; + } + + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR TValue count() const + { + return value; + } + + private: + + TValue value; + //TPeriod period; + }; + + //*********************************************************************** + /// Duration types + //*********************************************************************** +#if (ETL_USING_64BIT_TYPES) + typedef etl::chrono::duration nanoseconds; + typedef etl::chrono::duration microseconds; + typedef etl::chrono::duration milliseconds; + typedef etl::chrono::duration > seconds; +#else + typedef etl::chrono::duration nanoseconds; + typedef etl::chrono::duration microseconds; + typedef etl::chrono::duration milliseconds; + typedef etl::chrono::duration > seconds; +#endif + typedef etl::chrono::duration > minutes; + typedef etl::chrono::duration > hours; + typedef etl::chrono::duration > days; + typedef etl::chrono::duration > weeks; + typedef etl::chrono::duration > months; + typedef etl::chrono::duration > years; + + //*********************************************************************** + /// duration_cast + //*********************************************************************** + template + ETL_CONSTEXPR TToDuration duration_cast(const etl::chrono::duration& d) + { + return TToDuration(); + } + } +} + +#endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cad0feae..d152f2d6 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -57,6 +57,9 @@ add_executable(etl_tests test_callback_timer_locked.cpp test_char_traits.cpp test_checksum.cpp + + test_chrono_day.cpp + test_circular_buffer.cpp test_circular_buffer_external_buffer.cpp test_circular_iterator.cpp diff --git a/test/test_chrono_day.cpp b/test/test_chrono_day.cpp new file mode 100644 index 00000000..e6de125c --- /dev/null +++ b/test/test_chrono_day.cpp @@ -0,0 +1,305 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#if ETL_USING_CPP20 + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include + +namespace +{ + SUITE(test_chrono_day) + { + //************************************************************************* + TEST(test_default_constructor) + { + std::chrono::day std_day; + etl::chrono::day day; + + CHECK_EQUAL(std_day.ok(), day.ok()); + } + + //************************************************************************* + TEST(test_constructor_in_range) + { + for (unsigned i = 0U; i < 256; ++i) + { + std::chrono::day std_day(i); + etl::chrono::day day(i); + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_pre_increment) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + for (int i = 0; i < 255; ++i) + { + ++std_day; + ++day; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_post_increment) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + for (int i = 0; i < 255; ++i) + { + std::chrono::day std_last_day = std_day++; + etl::chrono::day last_day = day++; + + CHECK_EQUAL(std_last_day.ok(), last_day.ok()); + CHECK_EQUAL(unsigned(std_last_day), unsigned(last_day)); + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_pre_decrement) + { + std::chrono::day std_day(256); + etl::chrono::day day(256); + + for (int i = 0; i < 255; ++i) + { + --std_day; + --day; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_post_decrement) + { + std::chrono::day std_day(256); + etl::chrono::day day(256); + + for (int i = 0; i < 255; ++i) + { + std::chrono::day std_last_day = std_day--; + etl::chrono::day last_day = day--; + + CHECK_EQUAL(std_last_day.ok(), last_day.ok()); + CHECK_EQUAL(unsigned(std_last_day), unsigned(last_day)); + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_plus_equal_days) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + std::chrono::days std_days(2); + etl::chrono::days days(2); + + for (int i = 0; i < 128; ++i) + { + std_day += std_days; + day += days; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_day_plus_days) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + std::chrono::days std_days(2); + etl::chrono::days days(2); + + for (int i = 0; i < 128; ++i) + { + std_day = std_day + std_days; + day = day + days; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_days_plus_day) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + std::chrono::days std_days(2); + etl::chrono::days days(2); + + for (int i = 0; i < 128; ++i) + { + std_day = std_days + std_day; + day = days + day; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_minus_equal_days) + { + std::chrono::day std_day(256); + etl::chrono::day day(256); + + std::chrono::days std_days(2); + etl::chrono::days days(2); + + for (int i = 0; i < 128; ++i) + { + std_day -= std_days; + day -= days; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_day_minus_days) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + std::chrono::days std_days(2); + etl::chrono::days days(2); + + for (int i = 0; i < 128; ++i) + { + std_day = std_day - std_days; + day = day - days; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_day_minus_day) + { + for (int i = 1; i < 31; ++i) + { + std::chrono::day std_day1(i); + std::chrono::day std_day2(31 - i); + + etl::chrono::day day1(i); + etl::chrono::day day2(31 - i); + + std::chrono::days std_days = std_day1 - std_day2; + etl::chrono::days days = day1 - day2; + + CHECK_EQUAL(std_days.count(), days.count()); + } + } + + //************************************************************************* + TEST(test_literal_days) + { + using namespace std::literals::chrono_literals; + using namespace etl::literals::chrono_literals; + + std::chrono::day std_day = 25d; + etl::chrono::day day = 25_d; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + + //************************************************************************* + TEST(test_day_comparison_operators) + { + etl::chrono::day day10(10); + etl::chrono::day day20(20); + + CHECK_TRUE(day10 == day10); + CHECK_FALSE(day10 != day10); + CHECK_TRUE(day10 < day20); + CHECK_FALSE(day10 < day10); + CHECK_FALSE(day20 < day10); + CHECK_TRUE(day10 <= day20); + CHECK_TRUE(day10 <= day10); + CHECK_FALSE(day20 <= day10); + CHECK_FALSE(day10 > day20); + CHECK_FALSE(day10 > day10); + CHECK_TRUE(day20 > day10); + CHECK_FALSE(day10 >= day20); + CHECK_TRUE(day10 >= day10); + CHECK_TRUE(day20 >= day10); + +#if ETL_USING_CPP20 + CHECK_TRUE((day10 <=> day10) == 0); + CHECK_TRUE((day10 <=> day20) < 0); + CHECK_TRUE((day20 <=> day10) > 0); +#endif + } + + //************************************************************************* + TEST(test_day_hash) + { + etl::chrono::day day(10); + + size_t h = 0; + + h = etl::hash()(day); + + CHECK_TRUE(h != 0); + } + }; +} + +#endif \ No newline at end of file diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index c0aa5d92..a75e23c5 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -3027,6 +3027,7 @@ + @@ -3091,6 +3092,7 @@ + @@ -7751,6 +7753,7 @@ + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 37ae37e6..1a3a341a 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -220,6 +220,12 @@ {c75cedd3-8b6c-4662-b965-aecbe7fd5d1c} + + {46e23f29-ce01-418f-8331-9c739774414c} + + + {1b1afa65-108a-4665-9e74-3c67a27ff917} + {6bbca8f0-f707-45ee-9dad-6d41d401bbaf} @@ -1371,6 +1377,12 @@ ETL\Utilities + + ETL\Utilities + + + ETL\Utilities + ETL\Codecs @@ -2486,6 +2498,9 @@ Tests\Misc + + Tests\Chrono + Tests\Syntax Checks\Source From a90d0f4a89f28ae972e877319e605ef5366dfd22 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 29 Aug 2024 09:45:58 +0100 Subject: [PATCH 04/33] Fixed value type --- include/etl/private/chrono/day.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/etl/private/chrono/day.h b/include/etl/private/chrono/day.h index b04d3898..8079680d 100644 --- a/include/etl/private/chrono/day.h +++ b/include/etl/private/chrono/day.h @@ -146,7 +146,7 @@ namespace etl private: - unsigned char value; + unsigned value; }; //*********************************************************************** From 10147a1868e404931ca1b8417b2430f35e74d41b Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 30 Aug 2024 19:59:16 +0100 Subject: [PATCH 05/33] Updates to weekday --- include/etl/private/chrono/day.h | 28 +-- include/etl/private/chrono/duration.h | 21 +- include/etl/private/chrono/month.h | 30 +-- include/etl/private/chrono/weekday.h | 87 ++++----- include/etl/private/chrono/year.h | 30 +-- test/test_chrono_weekday.cpp | 263 +++++++++++++------------- test/test_chrono_year.cpp | 18 +- 7 files changed, 238 insertions(+), 239 deletions(-) diff --git a/include/etl/private/chrono/day.h b/include/etl/private/chrono/day.h index 812ef06c..91557a95 100644 --- a/include/etl/private/chrono/day.h +++ b/include/etl/private/chrono/day.h @@ -55,7 +55,7 @@ namespace etl /// Construct from unsigned //*********************************************************************** ETL_CONSTEXPR explicit day(unsigned value_) ETL_NOEXCEPT - : value(value_) + : value(static_cast(value_)) { } @@ -83,6 +83,8 @@ namespace etl ETL_CONSTEXPR etl::chrono::day& operator =(const etl::chrono::duration& rhs) { value = etl::chrono::duration_cast(rhs); + + return *this; } //*********************************************************************** @@ -148,7 +150,7 @@ namespace etl //*********************************************************************** /// Returns true if the day is within the valid 1 to 31 range //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT { return (value >= 1U) && (value <= 31U); } @@ -164,7 +166,7 @@ namespace etl //*********************************************************************** /// The minimum day value for which ok() will return true //*********************************************************************** - static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::day min() ETL_NOEXCEPT + static ETL_CONSTEXPR etl::chrono::day min() ETL_NOEXCEPT { return etl::chrono::day(1); } @@ -172,7 +174,7 @@ namespace etl //*********************************************************************** /// The maximum day value for which ok() will return true //*********************************************************************** - static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::day max() ETL_NOEXCEPT + static ETL_CONSTEXPR etl::chrono::day max() ETL_NOEXCEPT { return etl::chrono::day(31); } @@ -185,7 +187,7 @@ namespace etl //*********************************************************************** /// Equality operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator ==(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator ==(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT { return (static_cast(d1) == static_cast(d2)); } @@ -193,7 +195,7 @@ namespace etl //*********************************************************************** /// Inequality operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator !=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator !=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT { return !(d1 == d2); } @@ -209,7 +211,7 @@ namespace etl //*********************************************************************** /// Less-than-or-equal operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator <=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator <=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT { return (static_cast(d1) <= static_cast(d2)); } @@ -217,7 +219,7 @@ namespace etl //*********************************************************************** /// Greater-than operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator >(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator >(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT { return (static_cast(d1) > static_cast(d2)); } @@ -225,7 +227,7 @@ namespace etl //*********************************************************************** /// Greater-than-or-equal operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator >=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator >=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT { return (static_cast(d1) >= static_cast(d2)); } @@ -244,7 +246,7 @@ namespace etl /// Add etl::chrono::days to etl::chrono::day ///\return etl::chrono::day //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR etl::chrono::day operator +(const etl::chrono::day& d, const etl::chrono::days& ds) ETL_NOEXCEPT + ETL_CONSTEXPR etl::chrono::day operator +(const etl::chrono::day& d, const etl::chrono::days& ds) ETL_NOEXCEPT { etl::chrono::day result(d); @@ -257,7 +259,7 @@ namespace etl /// Add etl::chrono::day to etl::chrono::days ///\return etl::chrono::day //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR etl::chrono::day operator +(const etl::chrono::days& ds, const etl::chrono::day& d) ETL_NOEXCEPT + ETL_CONSTEXPR etl::chrono::day operator +(const etl::chrono::days& ds, const etl::chrono::day& d) ETL_NOEXCEPT { etl::chrono::day result(d); @@ -270,7 +272,7 @@ namespace etl /// Subtract etl::chrono::days from etl::chrono::day ///\return etl::chrono::day //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR etl::chrono::day operator -(const etl::chrono::day& d, const etl::chrono::days& ds) ETL_NOEXCEPT + ETL_CONSTEXPR etl::chrono::day operator -(const etl::chrono::day& d, const etl::chrono::days& ds) ETL_NOEXCEPT { etl::chrono::day result(d); @@ -283,7 +285,7 @@ namespace etl /// Subtract etl::chrono::day from etl::chrono::day ///\return etl::chrono::days //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR etl::chrono::days operator -(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + ETL_CONSTEXPR etl::chrono::days operator -(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT { return etl::chrono::days(static_cast(static_cast(d1)) - static_cast(static_cast(d2))); diff --git a/include/etl/private/chrono/duration.h b/include/etl/private/chrono/duration.h index 553ba123..b499f0f4 100644 --- a/include/etl/private/chrono/duration.h +++ b/include/etl/private/chrono/duration.h @@ -76,25 +76,25 @@ namespace etl } //*********************************************************************** - static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::duration< TValue, TPeriod> zero() ETL_NOEXCEPT + static ETL_CONSTEXPR etl::chrono::duration< TValue, TPeriod> zero() ETL_NOEXCEPT { return etl::chrono::duration{ 0, TPeriod()}; } //*********************************************************************** - static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::duration min() ETL_NOEXCEPT + static ETL_CONSTEXPR etl::chrono::duration min() ETL_NOEXCEPT { return etl::chrono::duration { etl::numeric_limits::min() }; } //*********************************************************************** - static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::duration max() ETL_NOEXCEPT + static ETL_CONSTEXPR etl::chrono::duration max() ETL_NOEXCEPT { return etl::chrono::duration{ etl::numeric_limits::max() }; } //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR TValue count() const ETL_NOEXCEPT + ETL_CONSTEXPR TValue count() const ETL_NOEXCEPT { return value; } @@ -131,9 +131,16 @@ namespace etl template ETL_CONSTEXPR TToDuration duration_cast(const etl::chrono::duration& d) ETL_NOEXCEPT { - return TToDuration(); + using to_value_type = typename TToDuration::value_type; + using to_period = typename TToDuration::period; + + // Calculate the conversion factor between the periods + ETL_CONSTEXPR auto conversion_factor = (static_cast(TPeriod::num) / TPeriod::den) * (to_period::den / to_period::num); + + // Convert the value + to_value_type converted_value = static_cast(d.count() * conversion_factor); + + return TToDuration(converted_value); } } } - -#endif diff --git a/include/etl/private/chrono/month.h b/include/etl/private/chrono/month.h index 907b5d84..30653a58 100644 --- a/include/etl/private/chrono/month.h +++ b/include/etl/private/chrono/month.h @@ -150,7 +150,7 @@ namespace etl //*********************************************************************** /// Returns true if the month is within the valid 1 to 31 range //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT { return (value >= 1U) && (value <= 12U); } @@ -158,7 +158,7 @@ namespace etl //*********************************************************************** /// The minimum month value for which ok() will return true //*********************************************************************** - static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::month min() ETL_NOEXCEPT + static ETL_CONSTEXPR etl::chrono::month min() ETL_NOEXCEPT { return etl::chrono::month(1); } @@ -166,7 +166,7 @@ namespace etl //*********************************************************************** /// The maximum month value for which ok() will return true //*********************************************************************** - static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::month max() ETL_NOEXCEPT + static ETL_CONSTEXPR etl::chrono::month max() ETL_NOEXCEPT { return etl::chrono::month(12); } @@ -184,7 +184,7 @@ namespace etl //*********************************************************************** /// Normalise to a in-range month //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR void normalise() ETL_NOEXCEPT + ETL_CONSTEXPR void normalise() ETL_NOEXCEPT { value = ((value % 12U) == 0U) ? 12U : value; } @@ -195,7 +195,7 @@ namespace etl //*********************************************************************** /// Equality operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator ==(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator ==(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT { return (static_cast(d1) == static_cast(d2)); } @@ -203,7 +203,7 @@ namespace etl //*********************************************************************** /// Inequality operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator !=(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator !=(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT { return !(d1 == d2); } @@ -211,7 +211,7 @@ namespace etl //*********************************************************************** /// Less-than operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator <(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator <(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT { return (static_cast(d1) < static_cast(d2)); } @@ -219,7 +219,7 @@ namespace etl //*********************************************************************** /// Less-than-or-equal operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator <=(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator <=(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT { return (static_cast(d1) <= static_cast(d2)); } @@ -227,7 +227,7 @@ namespace etl //*********************************************************************** /// Greater-than operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator >(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator >(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT { return (static_cast(d1) > static_cast(d2)); } @@ -235,7 +235,7 @@ namespace etl //*********************************************************************** /// Greater-than-or-equal operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator >=(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator >=(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT { return (static_cast(d1) >= static_cast(d2)); } @@ -254,7 +254,7 @@ namespace etl /// Add etl::chrono::months to etl::chrono::month ///\return etl::chrono::month //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::month operator +(const etl::chrono::month& m, const etl::chrono::months& ms) ETL_NOEXCEPT + ETL_CONSTEXPR14 etl::chrono::month operator +(const etl::chrono::month& m, const etl::chrono::months& ms) ETL_NOEXCEPT { unsigned int value = static_cast(m); @@ -280,7 +280,7 @@ namespace etl /// Add etl::chrono::month to etl::chrono::months ///\return etl::chrono::month //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR etl::chrono::month operator +(const etl::chrono::months& ms, const etl::chrono::month& m) ETL_NOEXCEPT + ETL_CONSTEXPR etl::chrono::month operator +(const etl::chrono::months& ms, const etl::chrono::month& m) ETL_NOEXCEPT { return m + ms; } @@ -289,7 +289,7 @@ namespace etl /// Subtract etl::chrono::months from etl::chrono::month ///\return etl::chrono::month //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR etl::chrono::month operator -(const etl::chrono::month& m, const etl::chrono::months& ms) ETL_NOEXCEPT + ETL_CONSTEXPR etl::chrono::month operator -(const etl::chrono::month& m, const etl::chrono::months& ms) ETL_NOEXCEPT { return m + etl::chrono::months(-ms.count()); } @@ -298,7 +298,7 @@ namespace etl /// Subtract etl::chrono::month from etl::chrono::month ///\return etl::chrono::months //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::months operator -(const etl::chrono::month& m1, const etl::chrono::month& m2) ETL_NOEXCEPT + ETL_CONSTEXPR14 etl::chrono::months operator -(const etl::chrono::month& m1, const etl::chrono::month& m2) ETL_NOEXCEPT { if (m1.ok() && m2.ok()) { @@ -374,7 +374,7 @@ namespace etl //*********************************************************************** constexpr etl::chrono::month operator ""_month(unsigned long long m) noexcept { - return etl::chrono::month(m); + return etl::chrono::month(static_cast(m)); } } } diff --git a/include/etl/private/chrono/weekday.h b/include/etl/private/chrono/weekday.h index aafb8ee0..fc4df27f 100644 --- a/include/etl/private/chrono/weekday.h +++ b/include/etl/private/chrono/weekday.h @@ -64,7 +64,7 @@ namespace etl /// Construct from unsigned //*********************************************************************** ETL_CONSTEXPR explicit weekday(unsigned value_) ETL_NOEXCEPT - : value(value_) + : value(value_ == 7U ? 0U :value_) { } @@ -153,7 +153,7 @@ namespace etl //*********************************************************************** /// Returns true if the weekday is within the valid 1 to 31 range //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT { return (c_encoding() <= 6U); } @@ -161,7 +161,7 @@ namespace etl //*********************************************************************** /// The minimum weekday value for which ok() will return true //*********************************************************************** - static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::weekday min() ETL_NOEXCEPT + static ETL_CONSTEXPR etl::chrono::weekday min() ETL_NOEXCEPT { return etl::chrono::weekday(0); } @@ -169,7 +169,7 @@ namespace etl //*********************************************************************** /// The maximum weekday value for which ok() will return true //*********************************************************************** - static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::weekday max() ETL_NOEXCEPT + static ETL_CONSTEXPR etl::chrono::weekday max() ETL_NOEXCEPT { return etl::chrono::weekday(6); } @@ -177,15 +177,15 @@ namespace etl //*********************************************************************** /// Get the C encoding of the weekday //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR unsigned c_encoding() const ETL_NOEXCEPT + ETL_CONSTEXPR unsigned c_encoding() const ETL_NOEXCEPT { - return (value == 7U) ? 0U : value; + return value; } //*********************************************************************** /// Get the ISO encoding of the weekday //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR unsigned iso_encoding() const ETL_NOEXCEPT + ETL_CONSTEXPR unsigned iso_encoding() const ETL_NOEXCEPT { return (value == 0U) ? 7U : value; } @@ -203,7 +203,7 @@ namespace etl //*********************************************************************** /// Returns true if the day is a weekend. //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR14 bool is_weekend() ETL_NOEXCEPT + ETL_CONSTEXPR14 bool is_weekend() ETL_NOEXCEPT { return (c_encoding() == 0U) || (c_encoding() == 6U); } @@ -213,7 +213,7 @@ namespace etl //*********************************************************************** /// Normalise to a in-range weekday //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR void normalise() ETL_NOEXCEPT + ETL_CONSTEXPR void normalise() ETL_NOEXCEPT { value %= 7U; } @@ -224,7 +224,7 @@ namespace etl //*********************************************************************** /// Equality operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator ==(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator ==(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT { return (wd1.c_encoding() == wd2.c_encoding()); } @@ -232,7 +232,7 @@ namespace etl //*********************************************************************** /// Inequality operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator !=(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator !=(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT { return !(wd1 == wd2); } @@ -240,7 +240,7 @@ namespace etl //*********************************************************************** /// Less-than operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator <(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator <(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT { return (wd1.c_encoding() < wd2.c_encoding()); } @@ -248,7 +248,7 @@ namespace etl //*********************************************************************** /// Less-than-or-equal operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator <=(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator <=(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT { return (wd1.c_encoding() <= wd2.c_encoding()); } @@ -256,7 +256,7 @@ namespace etl //*********************************************************************** /// Greater-than operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator >(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator >(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT { return (wd1.c_encoding() > wd2.c_encoding()); } @@ -264,7 +264,7 @@ namespace etl //*********************************************************************** /// Greater-than-or-equal operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator >=(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator >=(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT { return (wd1.c_encoding() >= wd2.c_encoding()); } @@ -283,15 +283,14 @@ namespace etl /// Add etl::chrono::days to etl::chrono::weekday ///\return etl::chrono::weekday //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::weekday operator +(const etl::chrono::weekday& wd, const etl::chrono::days& ds) ETL_NOEXCEPT + ETL_CONSTEXPR14 etl::chrono::weekday operator +(const etl::chrono::weekday& wd, const etl::chrono::days& ds) ETL_NOEXCEPT { - unsigned int value = wd.c_encoding(); - - value = value % 7U; - int delta = ds.count() % 7; + unsigned int value = wd.c_encoding(); + // Adjust to allow a limited +-7 weekday delta + value %= 7U; value += 7U; value += delta; value %= 7U; @@ -303,7 +302,7 @@ namespace etl /// Add etl::chrono::weekday to etl::chrono::days ///\return etl::chrono::weekday //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR etl::chrono::weekday operator +(const etl::chrono::days& ds, const etl::chrono::weekday& wd) ETL_NOEXCEPT + ETL_CONSTEXPR etl::chrono::weekday operator +(const etl::chrono::days& ds, const etl::chrono::weekday& wd) ETL_NOEXCEPT { return wd + ds; } @@ -312,7 +311,7 @@ namespace etl /// Subtract etl::chrono::days from etl::chrono::weekday ///\return etl::chrono::weekday //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR etl::chrono::weekday operator -(const etl::chrono::weekday& m, const etl::chrono::days& ds) ETL_NOEXCEPT + ETL_CONSTEXPR etl::chrono::weekday operator -(const etl::chrono::weekday& m, const etl::chrono::days& ds) ETL_NOEXCEPT { return m + etl::chrono::days(-ds.count()); } @@ -321,38 +320,34 @@ namespace etl /// Subtract etl::chrono::weekday from etl::chrono::weekday ///\return etl::chrono::days //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR14 etl::chrono::days operator -(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + ETL_CONSTEXPR14 etl::chrono::days operator -(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT { if (wd1.ok() && wd2.ok()) { - etl::chrono::days ds(static_cast(wd1.c_encoding()) - - static_cast(wd2.c_encoding()) % 12); - - if (wd1 == (wd2 + ds)) - { - return ds; - } + int diff = static_cast(wd1.c_encoding()) - static_cast(wd2.c_encoding()); + + return etl::chrono::days((diff + 7) % 7); } - return etl::chrono::days(); + return etl::chrono::days(0); } #if ETL_USING_CPP17 - inline constexpr etl::chrono::weekday Sunday{ 0 }; - inline constexpr etl::chrono::weekday Monday{ 1 }; - inline constexpr etl::chrono::weekday Tuesday{ 2 }; - inline constexpr etl::chrono::weekday Wednesday{ 3 }; - inline constexpr etl::chrono::weekday Thursday{ 4 }; - inline constexpr etl::chrono::weekday Friday{ 5 }; - inline constexpr etl::chrono::weekday Saturday{ 6 }; + inline constexpr etl::chrono::weekday Sunday{ 0U }; + inline constexpr etl::chrono::weekday Monday{ 1U }; + inline constexpr etl::chrono::weekday Tuesday{ 2U }; + inline constexpr etl::chrono::weekday Wednesday{ 3U }; + inline constexpr etl::chrono::weekday Thursday{ 4U }; + inline constexpr etl::chrono::weekday Friday{ 5U }; + inline constexpr etl::chrono::weekday Saturday{ 6U }; #else - static ETL_CONSTANT etl::chrono::weekday Sunday{ 0 }; - static ETL_CONSTANT etl::chrono::weekday Monday{ 1 }; - static ETL_CONSTANT etl::chrono::weekday Tuesday{ 2 }; - static ETL_CONSTANT etl::chrono::weekday Wednesday{ 3 }; - static ETL_CONSTANT etl::chrono::weekday Thursday{ 4 }; - static ETL_CONSTANT etl::chrono::weekday Friday{ 5 }; - static ETL_CONSTANT etl::chrono::weekday Saturday{ 6 }; + static ETL_CONSTANT etl::chrono::weekday Sunday{ 0U }; + static ETL_CONSTANT etl::chrono::weekday Monday{ 1U }; + static ETL_CONSTANT etl::chrono::weekday Tuesday{ 2U }; + static ETL_CONSTANT etl::chrono::weekday Wednesday{ 3U }; + static ETL_CONSTANT etl::chrono::weekday Thursday{ 4U }; + static ETL_CONSTANT etl::chrono::weekday Friday{ 5U }; + static ETL_CONSTANT etl::chrono::weekday Saturday{ 6U }; #endif } @@ -387,7 +382,7 @@ namespace etl //*********************************************************************** constexpr etl::chrono::weekday operator ""_weekday(unsigned long long m) noexcept { - return etl::chrono::weekday(m); + return etl::chrono::weekday(static_cast(m)); } } } diff --git a/include/etl/private/chrono/year.h b/include/etl/private/chrono/year.h index 1b8cb517..ff873e37 100644 --- a/include/etl/private/chrono/year.h +++ b/include/etl/private/chrono/year.h @@ -142,15 +142,15 @@ namespace etl //*********************************************************************** /// Returns true if the year is within the valid -32767 to 32767 range //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT { - return (value >= -32767) && (value <= 32767); + return (value != -32768); } //*********************************************************************** /// The minimum year value for which ok() will return true //*********************************************************************** - static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::year min() ETL_NOEXCEPT + static ETL_CONSTEXPR etl::chrono::year min() ETL_NOEXCEPT { return etl::chrono::year(-32767); } @@ -158,7 +158,7 @@ namespace etl //*********************************************************************** /// The maximum year value for which ok() will return true //*********************************************************************** - static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::year max() ETL_NOEXCEPT + static ETL_CONSTEXPR etl::chrono::year max() ETL_NOEXCEPT { return etl::chrono::year(32767); } @@ -166,7 +166,7 @@ namespace etl //*********************************************************************** /// Returns true if the year is a leap year //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool is_leap() const ETL_NOEXCEPT + ETL_CONSTEXPR bool is_leap() const ETL_NOEXCEPT { return ((value % 4) == 0) && !((value % 400) == 0); } @@ -187,7 +187,7 @@ namespace etl //*********************************************************************** /// Equality operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator ==(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator ==(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { return (static_cast(y1) == static_cast(y2)); } @@ -195,7 +195,7 @@ namespace etl //*********************************************************************** /// Inequality operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator !=(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator !=(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { return !(y1 == y2); } @@ -203,7 +203,7 @@ namespace etl //*********************************************************************** /// Less-than operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator <(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator <(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { return (static_cast(y1) < static_cast(y2)); } @@ -211,7 +211,7 @@ namespace etl //*********************************************************************** /// Less-than-or-equal operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator <=(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator <=(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { return (static_cast(y1) <= static_cast(y2)); } @@ -219,7 +219,7 @@ namespace etl //*********************************************************************** /// Greater-than operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator >(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator >(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { return (static_cast(y1) > static_cast(y2)); } @@ -227,7 +227,7 @@ namespace etl //*********************************************************************** /// Greater-than-or-equal operator //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool operator >=(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + ETL_CONSTEXPR bool operator >=(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { return (static_cast(y1) >= static_cast(y2)); } @@ -246,7 +246,7 @@ namespace etl /// Add etl::chrono::years to etl::chrono::year ///\return etl::chrono::year //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR etl::chrono::year operator +(const etl::chrono::year& y, const etl::chrono::years& ys) ETL_NOEXCEPT + ETL_CONSTEXPR etl::chrono::year operator +(const etl::chrono::year& y, const etl::chrono::years& ys) ETL_NOEXCEPT { etl::chrono::year result(y); @@ -259,7 +259,7 @@ namespace etl /// Add etl::chrono::year to etl::chrono::years ///\return etl::chrono::year //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR etl::chrono::year operator +(const etl::chrono::years& ys, const etl::chrono::year& y) ETL_NOEXCEPT + ETL_CONSTEXPR etl::chrono::year operator +(const etl::chrono::years& ys, const etl::chrono::year& y) ETL_NOEXCEPT { etl::chrono::year result(y); @@ -272,7 +272,7 @@ namespace etl /// Subtract etl::chrono::years from etl::chrono::year ///\return etl::chrono::year //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR etl::chrono::year operator -(const etl::chrono::year& y, const etl::chrono::years& ys) ETL_NOEXCEPT + ETL_CONSTEXPR etl::chrono::year operator -(const etl::chrono::year& y, const etl::chrono::years& ys) ETL_NOEXCEPT { etl::chrono::year result(y); @@ -285,7 +285,7 @@ namespace etl /// Subtract etl::chrono::year from etl::chrono::year ///\return etl::chrono::years //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR etl::chrono::years operator -(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + ETL_CONSTEXPR etl::chrono::years operator -(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { return etl::chrono::years(static_cast(static_cast(y1)) - static_cast(static_cast(y2))); diff --git a/test/test_chrono_weekday.cpp b/test/test_chrono_weekday.cpp index 0594ea75..c4cbe05d 100644 --- a/test/test_chrono_weekday.cpp +++ b/test/test_chrono_weekday.cpp @@ -30,13 +30,12 @@ SOFTWARE. #include "etl/platform.h" -#if ETL_USING_CPP20 - #include "unit_test_framework.h" #include "etl/chrono.h" #include + #include #include @@ -47,129 +46,138 @@ namespace //************************************************************************* TEST(test_default_constructor) { - std::chrono::weekday std_weekday; etl::chrono::weekday weekday; - CHECK_EQUAL(std_weekday.ok(), weekday.ok()); + CHECK_FALSE(weekday.ok()); } //************************************************************************* TEST(test_constructor_in_range) { - for (unsigned i = 0U; i < 256U; ++i) + for (unsigned i = 0U; i < 7U; ++i) { - std::chrono::weekday std_weekday(i); etl::chrono::weekday weekday(i); - CHECK_EQUAL(std_weekday.ok(), weekday.ok()); - CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(i, weekday.c_encoding()); + CHECK_EQUAL((i == 0U) ? 7U : i, weekday.iso_encoding()); } } //************************************************************************* - TEST(test_encodings) + TEST(test_constructor_out_of_range) { - std::chrono::weekday std_weekday; - etl::chrono::weekday weekday; - - for (unsigned i = 0U; i < 256; ++i) + for (unsigned i = 8U; i < 256U; ++i) { - std_weekday = std::chrono::weekday(i); - weekday = etl::chrono::weekday(i); + etl::chrono::weekday weekday(i); - CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); - CHECK_EQUAL(std_weekday.iso_encoding(), weekday.iso_encoding()); + CHECK_FALSE(weekday.ok()); + CHECK_EQUAL(i, weekday.c_encoding()); + CHECK_EQUAL((i == 0U) ? 7U : i, weekday.iso_encoding()); } } //************************************************************************* TEST(test_pre_increment) { - std::chrono::weekday std_weekday(0); etl::chrono::weekday weekday(0); + unsigned count = 0; for (int i = 0; i < 255; ++i) { - ++std_weekday; ++weekday; + ++count; - CHECK_EQUAL(std_weekday.ok(), weekday.ok()); - CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(count % 7, weekday.c_encoding()); + CHECK_EQUAL((count % 7 == 0U) ? 7U : count % 7, weekday.iso_encoding()); } } //************************************************************************* TEST(test_post_increment) { - std::chrono::weekday std_weekday(0); etl::chrono::weekday weekday(0); + unsigned count = 0; - for (int i = 0; i < 256; ++i) + for (int i = 0; i < 255; ++i) { - std::chrono::weekday std_last_weekday = std_weekday++; - etl::chrono::weekday last_weekday = weekday++; + etl::chrono::weekday last_weekday = weekday++; + unsigned last_count = count++; - CHECK_EQUAL(std_last_weekday.ok(), last_weekday.ok()); - CHECK_EQUAL(std_last_weekday.c_encoding(), last_weekday.c_encoding()); + CHECK_TRUE(last_weekday.ok()); + CHECK_EQUAL(last_count % 7, last_weekday.c_encoding()); + CHECK_EQUAL((last_count % 7 == 0U) ? 7U : last_count % 7, last_weekday.iso_encoding()); - CHECK_EQUAL(std_weekday.ok(), weekday.ok()); - CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(count % 7, weekday.c_encoding()); + CHECK_EQUAL((count % 7 == 0U) ? 7U : count % 7, weekday.iso_encoding()); } } //************************************************************************* TEST(test_pre_decrement) { - std::chrono::weekday std_weekday(255); - etl::chrono::weekday weekday(255); + etl::chrono::weekday weekday(255U); + unsigned count = 255U; - for (int i = 0; i < 256; ++i) + for (int i = 0; i < 255; ++i) { - --std_weekday; --weekday; + --count; - CHECK_EQUAL(std_weekday.ok(), weekday.ok()); - CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(count % 7, weekday.c_encoding()); + CHECK_EQUAL((count % 7 == 0U) ? 7U : count % 7, weekday.iso_encoding()); } } //************************************************************************* TEST(test_post_decrement) { - std::chrono::weekday std_weekday(255); - etl::chrono::weekday weekday(255); + etl::chrono::weekday weekday(255U); + unsigned count = 255U; - for (int i = 0; i < 256; ++i) + for (int i = 0; i < 255; ++i) { - std::chrono::weekday std_last_weekday = std_weekday--; etl::chrono::weekday last_weekday = weekday--; + unsigned last_count = count--; - CHECK_EQUAL(std_last_weekday.ok(), last_weekday.ok()); - CHECK_EQUAL(std_last_weekday.c_encoding(), last_weekday.c_encoding()); + if (last_count == 255U) + { + CHECK_FALSE(last_weekday.ok()); + CHECK_EQUAL(255U, last_weekday.c_encoding()); + CHECK_EQUAL(255U, last_weekday.iso_encoding()); + } + else + { + CHECK_TRUE(last_weekday.ok()); + CHECK_EQUAL(last_count % 7, last_weekday.c_encoding()); + CHECK_EQUAL((last_count % 7 == 0U) ? 7U : last_count % 7, last_weekday.iso_encoding()); + } - CHECK_EQUAL(std_weekday.ok(), weekday.ok()); - CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(count % 7, weekday.c_encoding()); + CHECK_EQUAL((count % 7 == 0U) ? 7U : count % 7, weekday.iso_encoding()); } } //************************************************************************* TEST(test_plus_equal_days) { - for (int wd = 0; wd <= 6; ++wd) + for (unsigned wd = 0; wd <= 6; ++wd) { - for (int ds = 0; ds <= 14; ++ds) + for (unsigned ds = 0; ds <= 14; ++ds) { - std::chrono::weekday std_weekday(wd); etl::chrono::weekday weekday(wd); - - std::chrono::days std_days(ds); etl::chrono::days days(ds); + weekday += days; - std_weekday += std_days; - weekday += days; + unsigned expected = (wd + ds) % 7; - CHECK_EQUAL(std_weekday.ok(), weekday.ok()); - CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(expected, weekday.c_encoding()); + CHECK_EQUAL((expected == 0U) ? 7U : expected, weekday.iso_encoding()); } } } @@ -177,21 +185,19 @@ namespace //************************************************************************* TEST(test_weekday_plus_days) { - for (int wd = 0; wd <= 6; ++wd) + for (unsigned wd = 0; wd <= 6; ++wd) { - for (int ds = 0; ds <= 14; ++ds) + for (unsigned ds = 0; ds <= 14; ++ds) { - std::chrono::weekday std_weekday(wd); etl::chrono::weekday weekday(wd); - - std::chrono::days std_days(ds); etl::chrono::days days(ds); + weekday = weekday + days; - std_weekday = std_weekday + std_days; - weekday = weekday + days; + unsigned expected = (wd + ds) % 7; - CHECK_EQUAL(std_weekday.ok(), weekday.ok()); - CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(expected, weekday.c_encoding()); + CHECK_EQUAL((expected == 0U) ? 7U : expected, weekday.iso_encoding()); } } } @@ -199,21 +205,19 @@ namespace //************************************************************************* TEST(test_days_plus_weekday) { - for (int wd = 0; wd <= 6; ++wd) + for (unsigned wd = 0; wd <= 6; ++wd) { - for (int ds = 0; ds <= 14; ++ds) + for (unsigned ds = 0; ds <= 14; ++ds) { - std::chrono::weekday std_weekday(wd); etl::chrono::weekday weekday(wd); - - std::chrono::days std_days(ds); etl::chrono::days days(ds); + weekday = weekday + days; - std_weekday = std_days + std_weekday; - weekday = days + weekday; + unsigned expected = (ds + wd) % 7; - CHECK_EQUAL(std_weekday.ok(), weekday.ok()); - CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(expected, weekday.c_encoding()); + CHECK_EQUAL((expected == 0U) ? 7U : expected, weekday.iso_encoding()); } } } @@ -221,21 +225,19 @@ namespace //************************************************************************* TEST(test_minus_equal_days) { - for (int wd = 0; wd <= 6; ++wd) + for (unsigned wd = 0; wd <= 6; ++wd) { - for (int ds = 0; ds <= 14; ++ds) + for (unsigned ds = 0; ds <= 14; ++ds) { - std::chrono::weekday std_weekday(wd); etl::chrono::weekday weekday(wd); - - std::chrono::days std_days(ds); etl::chrono::days days(ds); + weekday -= days; - std_weekday -= std_days; - weekday -= days; + unsigned expected = ((wd + 7U) - (ds % 7U)) % 7U; - CHECK_EQUAL(std_weekday.ok(), weekday.ok()); - CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(expected, weekday.c_encoding()); + CHECK_EQUAL((expected == 0U) ? 7U : expected, weekday.iso_encoding()); } } } @@ -243,21 +245,19 @@ namespace //************************************************************************* TEST(test_weekday_minus_days) { - for (int wd = 0; wd <= 6; ++wd) + for (unsigned wd = 0; wd <= 6; ++wd) { - for (int ds = 0; ds <= 14; ++ds) + for (unsigned ds = 0; ds <= 14; ++ds) { - std::chrono::weekday std_weekday(wd); etl::chrono::weekday weekday(wd); - - std::chrono::days std_days(ds); etl::chrono::days days(ds); + weekday = weekday - days; - std_weekday = std_weekday - std_days; - weekday = weekday - days; + unsigned expected = ((wd + 7U) - (ds % 7U)) % 7U; - CHECK_EQUAL(std_weekday.ok(), weekday.ok()); - CHECK_EQUAL(std_weekday.c_encoding(), weekday.c_encoding()); + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(expected, weekday.c_encoding()); + CHECK_EQUAL((expected == 0U) ? 7U : expected, weekday.iso_encoding()); } } } @@ -265,20 +265,20 @@ namespace //************************************************************************* TEST(test_weekday_minus_weekday) { - for (int m = 0; m < 256; ++m) + for (int m = 0; m < 7; ++m) { + etl::chrono::weekday weekday1(m); + etl::chrono::weekday weekday2(7 - m); + std::chrono::weekday std_weekday1(m); - std::chrono::weekday std_weekday2(255 - m); - - std::chrono::weekday weekday1(m); - std::chrono::weekday weekday2(255 - m); - - auto std_days12 = std_weekday1 - std_weekday2; - auto std_days21 = std_weekday2 - std_weekday1; + std::chrono::weekday std_weekday2(7 - m); auto days12 = weekday1 - weekday2; auto days21 = weekday2 - weekday1; + auto std_days12 = std_weekday1 - std_weekday2; + auto std_days21 = std_weekday2 - std_weekday1; + CHECK_EQUAL(std_days12.count(), days12.count()); CHECK_EQUAL(std_days21.count(), days21.count()); } @@ -292,7 +292,19 @@ namespace } //************************************************************************* - TEST(test_literal_weekday) + TEST(test_weekday_constants) + { + CHECK_EQUAL(0U, etl::chrono::Sunday.c_encoding()); + CHECK_EQUAL(1U, etl::chrono::Monday.c_encoding()); + CHECK_EQUAL(2U, etl::chrono::Tuesday.c_encoding()); + CHECK_EQUAL(3U, etl::chrono::Wednesday.c_encoding()); + CHECK_EQUAL(4U, etl::chrono::Thursday.c_encoding()); + CHECK_EQUAL(5U, etl::chrono::Friday.c_encoding()); + CHECK_EQUAL(6U, etl::chrono::Saturday.c_encoding()); + } + + //************************************************************************* + TEST(test_weekday_literals) { using namespace etl::literals::chrono_literals; @@ -324,28 +336,28 @@ namespace //************************************************************************* TEST(test_weekday_comparison_operators) { - etl::chrono::weekday weekday1(1); - etl::chrono::weekday weekday2(2); + etl::chrono::weekday weekday1(1); + etl::chrono::weekday weekday2(2); - CHECK_TRUE(weekday1 == weekday1); - CHECK_FALSE(weekday1 != weekday1); - CHECK_TRUE(weekday1 < weekday2); - CHECK_FALSE(weekday1 < weekday1); - CHECK_FALSE(weekday2 < weekday1); - CHECK_TRUE(weekday1 <= weekday2); - CHECK_TRUE(weekday1 <= weekday1); - CHECK_FALSE(weekday2 <= weekday1); - CHECK_FALSE(weekday1 > weekday2); - CHECK_FALSE(weekday1 > weekday1); - CHECK_TRUE(weekday2 > weekday1); - CHECK_FALSE(weekday1 >= weekday2); - CHECK_TRUE(weekday1 >= weekday1); - CHECK_TRUE(weekday2 >= weekday1); + CHECK_TRUE(weekday1 == weekday1); + CHECK_FALSE(weekday1 != weekday1); + CHECK_TRUE(weekday1 < weekday2); + CHECK_FALSE(weekday1 < weekday1); + CHECK_FALSE(weekday2 < weekday1); + CHECK_TRUE(weekday1 <= weekday2); + CHECK_TRUE(weekday1 <= weekday1); + CHECK_FALSE(weekday2 <= weekday1); + CHECK_FALSE(weekday1 > weekday2); + CHECK_FALSE(weekday1 > weekday1); + CHECK_TRUE(weekday2 > weekday1); + CHECK_FALSE(weekday1 >= weekday2); + CHECK_TRUE(weekday1 >= weekday1); + CHECK_TRUE(weekday2 >= weekday1); #if ETL_USING_CPP20 - CHECK_TRUE((weekday1 <=> weekday1) == 0); - CHECK_TRUE((weekday1 <=> weekday2) < 0); - CHECK_TRUE((weekday2 <=> weekday1) > 0); + CHECK_TRUE((weekday1 <=> weekday1) == 0); + CHECK_TRUE((weekday1 <=> weekday2) < 0); + CHECK_TRUE((weekday2 <=> weekday1) > 0); #endif } @@ -363,24 +375,5 @@ namespace (void)std::unique(hashes.begin(), hashes.end()); CHECK_EQUAL(256U, hashes.size()); } - - //************************************************************************* - TEST(test_weekday_types) - { - CHECK_EQUAL(static_cast(std::chrono::January), static_cast(etl::chrono::January)); - CHECK_EQUAL(static_cast(std::chrono::February), static_cast(etl::chrono::February)); - CHECK_EQUAL(static_cast(std::chrono::March), static_cast(etl::chrono::March)); - CHECK_EQUAL(static_cast(std::chrono::April), static_cast(etl::chrono::April)); - CHECK_EQUAL(static_cast(std::chrono::May), static_cast(etl::chrono::May)); - CHECK_EQUAL(static_cast(std::chrono::June), static_cast(etl::chrono::June)); - CHECK_EQUAL(static_cast(std::chrono::July), static_cast(etl::chrono::July)); - CHECK_EQUAL(static_cast(std::chrono::August), static_cast(etl::chrono::August)); - CHECK_EQUAL(static_cast(std::chrono::September), static_cast(etl::chrono::September)); - CHECK_EQUAL(static_cast(std::chrono::October), static_cast(etl::chrono::October)); - CHECK_EQUAL(static_cast(std::chrono::November), static_cast(etl::chrono::November)); - CHECK_EQUAL(static_cast(std::chrono::December), static_cast(etl::chrono::December)); - } }; } - -#endif \ No newline at end of file diff --git a/test/test_chrono_year.cpp b/test/test_chrono_year.cpp index e927668f..dacb9c06 100644 --- a/test/test_chrono_year.cpp +++ b/test/test_chrono_year.cpp @@ -37,6 +37,7 @@ SOFTWARE. #include "etl/chrono.h" #include +#include namespace { @@ -59,24 +60,25 @@ namespace std::chrono::year std_year(i); etl::chrono::year year(i); - CHECK_EQUAL(std_year.ok(), year.ok()); - CHECK_EQUAL(int(std_year), int(year)); + CHECK_TRUE(year.ok()); + CHECK_EQUAL(i, int(year)); } } //************************************************************************* TEST(test_pre_increment) { - std::chrono::year std_year(-32767); etl::chrono::year year(-32767); + int count = int(year); - for (int32_t i = 0; i < 65536; ++i) + for (int32_t i = 0; i < 65534; ++i) { - ++std_year; - ++year; + ++count; + etl::chrono::year this_year = ++year; - CHECK_EQUAL(std_year.ok(), year.ok()); - CHECK_EQUAL(int(std_year), int(year)); + CHECK_TRUE(year.ok()); + CHECK_EQUAL(count, year); + CHECK_EQUAL(this_year, year); } } From b532aa685f924fee30f1f6b4f014488ed32ab7b4 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 11 Sep 2023 11:15:49 +0100 Subject: [PATCH 06/33] Work in progress --- include/etl/chrono.h | 39 ++++ include/etl/hash.h | 4 +- include/etl/private/chrono/day.h | 271 +++++++++++++++++++++++ include/etl/private/chrono/duration.h | 139 ++++++++++++ test/CMakeLists.txt | 3 + test/test_chrono_day.cpp | 305 ++++++++++++++++++++++++++ test/vs2022/etl.vcxproj | 3 + test/vs2022/etl.vcxproj.filters | 15 ++ 8 files changed, 777 insertions(+), 2 deletions(-) create mode 100644 include/etl/chrono.h create mode 100644 include/etl/private/chrono/day.h create mode 100644 include/etl/private/chrono/duration.h create mode 100644 test/test_chrono_day.cpp diff --git a/include/etl/chrono.h b/include/etl/chrono.h new file mode 100644 index 00000000..0cf26e5b --- /dev/null +++ b/include/etl/chrono.h @@ -0,0 +1,39 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CHRONO_INCLUDED +#define ETL_CHRONO_INCLUDED + +#include "platform.h" + +#include "private/chrono/duration.h" +#include "private/chrono/day.h" + +#endif diff --git a/include/etl/hash.h b/include/etl/hash.h index 8066a012..2397f025 100644 --- a/include/etl/hash.h +++ b/include/etl/hash.h @@ -159,8 +159,8 @@ namespace etl /// Specialisation for signed char. ///\ingroup hash //*************************************************************************** - template<> struct - hash + template <> + struct hash { ETL_STATIC_ASSERT(sizeof(size_t) >= sizeof(signed char), "size_t smaller than type"); diff --git a/include/etl/private/chrono/day.h b/include/etl/private/chrono/day.h new file mode 100644 index 00000000..b04d3898 --- /dev/null +++ b/include/etl/private/chrono/day.h @@ -0,0 +1,271 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CHRONO_DAY_INCLUDED +#define ETL_CHRONO_DAY_INCLUDED + +#include "../../platform.h" +#include "../../hash.h" + +#include "duration.h" + +#include + +namespace etl +{ + namespace chrono + { + //*********************************************************************** + /// day + //*********************************************************************** + class day + { + public: + + //*********************************************************************** + ETL_CONSTEXPR day() + : value(0) + { + } + + //*********************************************************************** + ETL_CONSTEXPR day(unsigned value_) + : value(value_) + { + } + + //*********************************************************************** + ETL_CONSTEXPR day(const etl::chrono::day& other) + : value(other.value) + { + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator =(const etl::chrono::day& rhs) + { + value = rhs.value; + + return *this; + } + + //*********************************************************************** + template + ETL_CONSTEXPR etl::chrono::day& operator =(const etl::chrono::duration& rhs) + { + value = etl::chrono::duration_cast(rhs); + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator ++() ETL_NOEXCEPT + { + ++value; + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::day operator ++(int) ETL_NOEXCEPT + { + const etl::chrono::day temp = *this; + ++value; + + return temp; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator --() ETL_NOEXCEPT + { + --value; + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::day operator --(int) ETL_NOEXCEPT + { + const etl::chrono::day temp = *this; + --value; + + return temp; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator +=(const etl::chrono::days& ds) ETL_NOEXCEPT + { + value += static_cast(ds.count()); + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day& operator -=(const etl::chrono::days& ds) ETL_NOEXCEPT + { + value -= static_cast(ds.count()); + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + { + return (value >= 1U) && (value <= 31U); + } + + //*********************************************************************** + ETL_CONSTEXPR operator unsigned() const ETL_NOEXCEPT + { + return static_cast(value); + } + + private: + + unsigned char value; + }; + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day operator +(const etl::chrono::day& d, const etl::chrono::days& ds) ETL_NOEXCEPT + { + etl::chrono::day result(d); + + result += ds; + + return result; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day operator +(const etl::chrono::days& ds, const etl::chrono::day& d) ETL_NOEXCEPT + { + etl::chrono::day result(d); + + result += ds; + + return result; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day operator -(const etl::chrono::day& d, const etl::chrono::days& ds) ETL_NOEXCEPT + { + etl::chrono::day result(d); + + result -= ds; + + return result; + } + + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::days operator -(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return etl::chrono::days(static_cast(static_cast(d1)) - + static_cast(static_cast(d2))); + } + + //*********************************************************************** + ETL_CONSTEXPR bool operator ==(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) == static_cast(d2)); + } + + //*********************************************************************** + ETL_CONSTEXPR bool operator !=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return !(d1 == d2); + } + + //*********************************************************************** + ETL_CONSTEXPR bool operator <(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) < static_cast(d2)); + } + + //*********************************************************************** + ETL_CONSTEXPR bool operator <=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) <= static_cast(d2)); + } + + //*********************************************************************** + ETL_CONSTEXPR bool operator >(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) > static_cast(d2)); + } + + //*********************************************************************** + ETL_CONSTEXPR bool operator >=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) >= static_cast(d2)); + } + + //*********************************************************************** +#if ETL_USING_CPP20 + ETL_CONSTEXPR auto operator <=>(const etl::chrono::day& d1, const etl::chrono::day& d2) + { + return (static_cast(d1) <=> static_cast(d2)); + } +#endif + } + + //************************************************************************* + /// Hash function. + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::day& d) const + { + unsigned value = d; + const uint8_t* p = reinterpret_cast(&value); + + return etl::private_hash::generic_hash(p, p + sizeof(unsigned)); + } + }; +#endif +} + +#if ETL_USING_CPP11 +namespace etl +{ + namespace literals + { + namespace chrono_literals + { + //*********************************************************************** + /// Literal for days + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::day operator ""_d(unsigned long long d) ETL_NOEXCEPT + { + return etl::chrono::day(d); + } + } + } +} +#endif + +#endif \ No newline at end of file diff --git a/include/etl/private/chrono/duration.h b/include/etl/private/chrono/duration.h new file mode 100644 index 00000000..3e4ec95e --- /dev/null +++ b/include/etl/private/chrono/duration.h @@ -0,0 +1,139 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_CHRONO_DURATION_INCLUDED +#define ETL_CHRONO_DURATION_INCLUDED + +#include "../../platform.h" +#include "../../ratio.h" +#include "../../static_assert.h" +#include "../../limits.h" + +namespace etl +{ + namespace chrono + { + //*********************************************************************** + /// duration + //*********************************************************************** + template > + class duration + { + public: + + //*********************************************************************** + ETL_CONSTEXPR duration() ETL_NOEXCEPT + { + } + + //*********************************************************************** + ETL_CONSTEXPR duration(const etl::chrono::duration& other) ETL_NOEXCEPT + : value(other.value) + { + } + + //*********************************************************************** + template< typename TValue2 > + ETL_CONSTEXPR explicit duration(const TValue2& value_) ETL_NOEXCEPT + : value(static_cast(value_)) + { + } + + //*********************************************************************** + template< typename TValue2, typename TPeriod2 > + ETL_CONSTEXPR duration(const etl::chrono::duration& other) ETL_NOEXCEPT + : value(static_cast(other.value)) + { + ETL_STATIC_ASSERT(!(etl::is_integral::value && etl::is_floating_point::value), "Cannot convert duration from floating point to integral"); + } + + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::duration< TValue, TPeriod> zero() ETL_NOEXCEPT + { + return etl::chrono::duration{ 0, TPeriod()}; + } + + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::duration min() ETL_NOEXCEPT + { + return etl::chrono::duration { etl::numeric_limits::min() }; + } + + //*********************************************************************** + static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::duration max() ETL_NOEXCEPT + { + return etl::chrono::duration{ etl::numeric_limits::max() }; + } + + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR TValue count() const + { + return value; + } + + private: + + TValue value; + //TPeriod period; + }; + + //*********************************************************************** + /// Duration types + //*********************************************************************** +#if (ETL_USING_64BIT_TYPES) + typedef etl::chrono::duration nanoseconds; + typedef etl::chrono::duration microseconds; + typedef etl::chrono::duration milliseconds; + typedef etl::chrono::duration > seconds; +#else + typedef etl::chrono::duration nanoseconds; + typedef etl::chrono::duration microseconds; + typedef etl::chrono::duration milliseconds; + typedef etl::chrono::duration > seconds; +#endif + typedef etl::chrono::duration > minutes; + typedef etl::chrono::duration > hours; + typedef etl::chrono::duration > days; + typedef etl::chrono::duration > weeks; + typedef etl::chrono::duration > months; + typedef etl::chrono::duration > years; + + //*********************************************************************** + /// duration_cast + //*********************************************************************** + template + ETL_CONSTEXPR TToDuration duration_cast(const etl::chrono::duration& d) + { + return TToDuration(); + } + } +} + +#endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index ce9e2a66..029c0443 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -58,6 +58,9 @@ add_executable(etl_tests test_callback_timer_locked.cpp test_char_traits.cpp test_checksum.cpp + + test_chrono_day.cpp + test_circular_buffer.cpp test_circular_buffer_external_buffer.cpp test_circular_iterator.cpp diff --git a/test/test_chrono_day.cpp b/test/test_chrono_day.cpp new file mode 100644 index 00000000..e6de125c --- /dev/null +++ b/test/test_chrono_day.cpp @@ -0,0 +1,305 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#if ETL_USING_CPP20 + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include + +namespace +{ + SUITE(test_chrono_day) + { + //************************************************************************* + TEST(test_default_constructor) + { + std::chrono::day std_day; + etl::chrono::day day; + + CHECK_EQUAL(std_day.ok(), day.ok()); + } + + //************************************************************************* + TEST(test_constructor_in_range) + { + for (unsigned i = 0U; i < 256; ++i) + { + std::chrono::day std_day(i); + etl::chrono::day day(i); + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_pre_increment) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + for (int i = 0; i < 255; ++i) + { + ++std_day; + ++day; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_post_increment) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + for (int i = 0; i < 255; ++i) + { + std::chrono::day std_last_day = std_day++; + etl::chrono::day last_day = day++; + + CHECK_EQUAL(std_last_day.ok(), last_day.ok()); + CHECK_EQUAL(unsigned(std_last_day), unsigned(last_day)); + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_pre_decrement) + { + std::chrono::day std_day(256); + etl::chrono::day day(256); + + for (int i = 0; i < 255; ++i) + { + --std_day; + --day; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_post_decrement) + { + std::chrono::day std_day(256); + etl::chrono::day day(256); + + for (int i = 0; i < 255; ++i) + { + std::chrono::day std_last_day = std_day--; + etl::chrono::day last_day = day--; + + CHECK_EQUAL(std_last_day.ok(), last_day.ok()); + CHECK_EQUAL(unsigned(std_last_day), unsigned(last_day)); + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_plus_equal_days) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + std::chrono::days std_days(2); + etl::chrono::days days(2); + + for (int i = 0; i < 128; ++i) + { + std_day += std_days; + day += days; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_day_plus_days) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + std::chrono::days std_days(2); + etl::chrono::days days(2); + + for (int i = 0; i < 128; ++i) + { + std_day = std_day + std_days; + day = day + days; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_days_plus_day) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + std::chrono::days std_days(2); + etl::chrono::days days(2); + + for (int i = 0; i < 128; ++i) + { + std_day = std_days + std_day; + day = days + day; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_minus_equal_days) + { + std::chrono::day std_day(256); + etl::chrono::day day(256); + + std::chrono::days std_days(2); + etl::chrono::days days(2); + + for (int i = 0; i < 128; ++i) + { + std_day -= std_days; + day -= days; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_day_minus_days) + { + std::chrono::day std_day(0); + etl::chrono::day day(0); + + std::chrono::days std_days(2); + etl::chrono::days days(2); + + for (int i = 0; i < 128; ++i) + { + std_day = std_day - std_days; + day = day - days; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + } + + //************************************************************************* + TEST(test_day_minus_day) + { + for (int i = 1; i < 31; ++i) + { + std::chrono::day std_day1(i); + std::chrono::day std_day2(31 - i); + + etl::chrono::day day1(i); + etl::chrono::day day2(31 - i); + + std::chrono::days std_days = std_day1 - std_day2; + etl::chrono::days days = day1 - day2; + + CHECK_EQUAL(std_days.count(), days.count()); + } + } + + //************************************************************************* + TEST(test_literal_days) + { + using namespace std::literals::chrono_literals; + using namespace etl::literals::chrono_literals; + + std::chrono::day std_day = 25d; + etl::chrono::day day = 25_d; + + CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_EQUAL(unsigned(std_day), unsigned(day)); + } + + //************************************************************************* + TEST(test_day_comparison_operators) + { + etl::chrono::day day10(10); + etl::chrono::day day20(20); + + CHECK_TRUE(day10 == day10); + CHECK_FALSE(day10 != day10); + CHECK_TRUE(day10 < day20); + CHECK_FALSE(day10 < day10); + CHECK_FALSE(day20 < day10); + CHECK_TRUE(day10 <= day20); + CHECK_TRUE(day10 <= day10); + CHECK_FALSE(day20 <= day10); + CHECK_FALSE(day10 > day20); + CHECK_FALSE(day10 > day10); + CHECK_TRUE(day20 > day10); + CHECK_FALSE(day10 >= day20); + CHECK_TRUE(day10 >= day10); + CHECK_TRUE(day20 >= day10); + +#if ETL_USING_CPP20 + CHECK_TRUE((day10 <=> day10) == 0); + CHECK_TRUE((day10 <=> day20) < 0); + CHECK_TRUE((day20 <=> day10) > 0); +#endif + } + + //************************************************************************* + TEST(test_day_hash) + { + etl::chrono::day day(10); + + size_t h = 0; + + h = etl::hash()(day); + + CHECK_TRUE(h != 0); + } + }; +} + +#endif \ No newline at end of file diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 7506cfa1..8c675a44 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -3027,6 +3027,7 @@ + @@ -3091,6 +3092,7 @@ + @@ -7947,6 +7949,7 @@ + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 2da095b9..470fb776 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -220,6 +220,12 @@ {c75cedd3-8b6c-4662-b965-aecbe7fd5d1c} + + {46e23f29-ce01-418f-8331-9c739774414c} + + + {1b1afa65-108a-4665-9e74-3c67a27ff917} + {6bbca8f0-f707-45ee-9dad-6d41d401bbaf} @@ -1371,6 +1377,12 @@ ETL\Utilities + + ETL\Utilities + + + ETL\Utilities + ETL\Codecs @@ -2486,6 +2498,9 @@ Tests\Misc + + Tests\Chrono + Tests\Syntax Checks\Source From bfa5f391fbe482ccc6afd9410fc240beeee8139e Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 29 Aug 2024 09:45:58 +0100 Subject: [PATCH 07/33] Fixed value type --- include/etl/private/chrono/day.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/etl/private/chrono/day.h b/include/etl/private/chrono/day.h index b04d3898..8079680d 100644 --- a/include/etl/private/chrono/day.h +++ b/include/etl/private/chrono/day.h @@ -146,7 +146,7 @@ namespace etl private: - unsigned char value; + unsigned value; }; //*********************************************************************** From ae31d581e2ea1d807aca4c8dbee5d3871e4b0be6 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 11 Sep 2023 11:15:49 +0100 Subject: [PATCH 08/33] Work in progress --- .gitignore | 1 + include/etl/private/chrono/day.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 8f313ddb..ab33079c 100644 --- a/.gitignore +++ b/.gitignore @@ -388,3 +388,4 @@ support/time remaining test.xlsx test/vs2022/Debug MSVC C++20 - Force C++03 test/vs2022/Release MSVC C++20 - No STL - Optimised -O2 - Sanitiser test/test_file_list.txt +test/reflog.txt diff --git a/include/etl/private/chrono/day.h b/include/etl/private/chrono/day.h index 8079680d..b04d3898 100644 --- a/include/etl/private/chrono/day.h +++ b/include/etl/private/chrono/day.h @@ -146,7 +146,7 @@ namespace etl private: - unsigned value; + unsigned char value; }; //*********************************************************************** From d15f35c78fea39eeef880ad93580394cf07d6843 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 11 Sep 2023 11:15:49 +0100 Subject: [PATCH 09/33] Work in progress --- include/etl/private/chrono/day.h | 51 +------------- test/test_chrono_day.cpp | 117 ++++--------------------------- 2 files changed, 16 insertions(+), 152 deletions(-) diff --git a/include/etl/private/chrono/day.h b/include/etl/private/chrono/day.h index b04d3898..61d19e8b 100644 --- a/include/etl/private/chrono/day.h +++ b/include/etl/private/chrono/day.h @@ -182,53 +182,10 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR etl::chrono::days operator -(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT { - return etl::chrono::days(static_cast(static_cast(d1)) - - static_cast(static_cast(d2))); - } + etl::chrono::days result; - //*********************************************************************** - ETL_CONSTEXPR bool operator ==(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT - { - return (static_cast(d1) == static_cast(d2)); + return etl::chrono::days(static_cast(d1) - static_cast(d2)); } - - //*********************************************************************** - ETL_CONSTEXPR bool operator !=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT - { - return !(d1 == d2); - } - - //*********************************************************************** - ETL_CONSTEXPR bool operator <(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT - { - return (static_cast(d1) < static_cast(d2)); - } - - //*********************************************************************** - ETL_CONSTEXPR bool operator <=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT - { - return (static_cast(d1) <= static_cast(d2)); - } - - //*********************************************************************** - ETL_CONSTEXPR bool operator >(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT - { - return (static_cast(d1) > static_cast(d2)); - } - - //*********************************************************************** - ETL_CONSTEXPR bool operator >=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT - { - return (static_cast(d1) >= static_cast(d2)); - } - - //*********************************************************************** -#if ETL_USING_CPP20 - ETL_CONSTEXPR auto operator <=>(const etl::chrono::day& d1, const etl::chrono::day& d2) - { - return (static_cast(d1) <=> static_cast(d2)); - } -#endif } //************************************************************************* @@ -249,15 +206,12 @@ namespace etl #endif } -#if ETL_USING_CPP11 namespace etl { namespace literals { namespace chrono_literals { - //*********************************************************************** - /// Literal for days //*********************************************************************** ETL_CONSTEXPR etl::chrono::day operator ""_d(unsigned long long d) ETL_NOEXCEPT { @@ -266,6 +220,5 @@ namespace etl } } } -#endif #endif \ No newline at end of file diff --git a/test/test_chrono_day.cpp b/test/test_chrono_day.cpp index e6de125c..f8a3d453 100644 --- a/test/test_chrono_day.cpp +++ b/test/test_chrono_day.cpp @@ -154,40 +154,28 @@ namespace } //************************************************************************* - TEST(test_day_plus_days) + TEST(test_plus_days) { - std::chrono::day std_day(0); - etl::chrono::day day(0); + std::chrono::day std_day1(0); + std::chrono::day std_day2(0); + etl::chrono::day day1(0); + etl::chrono::day day2(0); std::chrono::days std_days(2); etl::chrono::days days(2); for (int i = 0; i < 128; ++i) { - std_day = std_day + std_days; - day = day + days; + std_day1 = std_days + std_day1; + std_day2 = std_day2 + std_days; + + day1 = days + day1; + day2 = day2 + days; - CHECK_EQUAL(std_day.ok(), day.ok()); - CHECK_EQUAL(unsigned(std_day), unsigned(day)); - } - } - - //************************************************************************* - TEST(test_days_plus_day) - { - std::chrono::day std_day(0); - etl::chrono::day day(0); - - std::chrono::days std_days(2); - etl::chrono::days days(2); - - for (int i = 0; i < 128; ++i) - { - std_day = std_days + std_day; - day = days + day; - - CHECK_EQUAL(std_day.ok(), day.ok()); - CHECK_EQUAL(unsigned(std_day), unsigned(day)); + CHECK_EQUAL(std_day1.ok(), day1.ok()); + CHECK_EQUAL(std_day2.ok(), day2.ok()); + CHECK_EQUAL(unsigned(std_day1), unsigned(day1)); + CHECK_EQUAL(unsigned(std_day2), unsigned(day2)); } } @@ -210,43 +198,6 @@ namespace } } - //************************************************************************* - TEST(test_day_minus_days) - { - std::chrono::day std_day(0); - etl::chrono::day day(0); - - std::chrono::days std_days(2); - etl::chrono::days days(2); - - for (int i = 0; i < 128; ++i) - { - std_day = std_day - std_days; - day = day - days; - - CHECK_EQUAL(std_day.ok(), day.ok()); - CHECK_EQUAL(unsigned(std_day), unsigned(day)); - } - } - - //************************************************************************* - TEST(test_day_minus_day) - { - for (int i = 1; i < 31; ++i) - { - std::chrono::day std_day1(i); - std::chrono::day std_day2(31 - i); - - etl::chrono::day day1(i); - etl::chrono::day day2(31 - i); - - std::chrono::days std_days = std_day1 - std_day2; - etl::chrono::days days = day1 - day2; - - CHECK_EQUAL(std_days.count(), days.count()); - } - } - //************************************************************************* TEST(test_literal_days) { @@ -259,46 +210,6 @@ namespace CHECK_EQUAL(std_day.ok(), day.ok()); CHECK_EQUAL(unsigned(std_day), unsigned(day)); } - - //************************************************************************* - TEST(test_day_comparison_operators) - { - etl::chrono::day day10(10); - etl::chrono::day day20(20); - - CHECK_TRUE(day10 == day10); - CHECK_FALSE(day10 != day10); - CHECK_TRUE(day10 < day20); - CHECK_FALSE(day10 < day10); - CHECK_FALSE(day20 < day10); - CHECK_TRUE(day10 <= day20); - CHECK_TRUE(day10 <= day10); - CHECK_FALSE(day20 <= day10); - CHECK_FALSE(day10 > day20); - CHECK_FALSE(day10 > day10); - CHECK_TRUE(day20 > day10); - CHECK_FALSE(day10 >= day20); - CHECK_TRUE(day10 >= day10); - CHECK_TRUE(day20 >= day10); - -#if ETL_USING_CPP20 - CHECK_TRUE((day10 <=> day10) == 0); - CHECK_TRUE((day10 <=> day20) < 0); - CHECK_TRUE((day20 <=> day10) > 0); -#endif - } - - //************************************************************************* - TEST(test_day_hash) - { - etl::chrono::day day(10); - - size_t h = 0; - - h = etl::hash()(day); - - CHECK_TRUE(h != 0); - } }; } From e732f205acb530617cddd6e1d2480934a1014b62 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 30 Aug 2024 19:59:16 +0100 Subject: [PATCH 10/33] Updates to weekday --- include/etl/private/chrono/day.h | 96 ++++++- include/etl/private/chrono/duration.h | 21 +- include/etl/private/chrono/month.h | 383 +++++++++++++++++++++++++ include/etl/private/chrono/weekday.h | 391 ++++++++++++++++++++++++++ include/etl/private/chrono/year.h | 332 ++++++++++++++++++++++ test/test_chrono_weekday.cpp | 379 +++++++++++++++++++++++++ test/test_chrono_year.cpp | 317 +++++++++++++++++++++ 7 files changed, 1910 insertions(+), 9 deletions(-) create mode 100644 include/etl/private/chrono/month.h create mode 100644 include/etl/private/chrono/weekday.h create mode 100644 include/etl/private/chrono/year.h create mode 100644 test/test_chrono_weekday.cpp create mode 100644 test/test_chrono_year.cpp diff --git a/include/etl/private/chrono/day.h b/include/etl/private/chrono/day.h index 61d19e8b..e2118172 100644 --- a/include/etl/private/chrono/day.h +++ b/include/etl/private/chrono/day.h @@ -56,8 +56,10 @@ namespace etl } //*********************************************************************** - ETL_CONSTEXPR day(unsigned value_) - : value(value_) + /// Construct from unsigned + //*********************************************************************** + ETL_CONSTEXPR explicit day(unsigned value_) ETL_NOEXCEPT + : value(static_cast(value_)) { } @@ -80,6 +82,8 @@ namespace etl ETL_CONSTEXPR etl::chrono::day& operator =(const etl::chrono::duration& rhs) { value = etl::chrono::duration_cast(rhs); + + return *this; } //*********************************************************************** @@ -132,6 +136,8 @@ namespace etl return *this; } + //*********************************************************************** + /// Returns true if the day is within the valid 1 to 31 range //*********************************************************************** ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT { @@ -144,11 +150,88 @@ namespace etl return static_cast(value); } + //*********************************************************************** + /// The minimum day value for which ok() will return true + //*********************************************************************** + static ETL_CONSTEXPR etl::chrono::day min() ETL_NOEXCEPT + { + return etl::chrono::day(1); + } + + //*********************************************************************** + /// The maximum day value for which ok() will return true + //*********************************************************************** + static ETL_CONSTEXPR etl::chrono::day max() ETL_NOEXCEPT + { + return etl::chrono::day(31); + } + private: unsigned char value; }; + //*********************************************************************** + /// Equality operator + //*********************************************************************** + ETL_CONSTEXPR bool operator ==(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) == static_cast(d2)); + } + + //*********************************************************************** + /// Inequality operator + //*********************************************************************** + ETL_CONSTEXPR bool operator !=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return !(d1 == d2); + } + + //*********************************************************************** + /// Less-than operator + //*********************************************************************** + ETL_CONSTEXPR bool operator <(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) < static_cast(d2)); + } + + //*********************************************************************** + /// Less-than-or-equal operator + //*********************************************************************** + ETL_CONSTEXPR bool operator <=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) <= static_cast(d2)); + } + + //*********************************************************************** + /// Greater-than operator + //*********************************************************************** + ETL_CONSTEXPR bool operator >(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) > static_cast(d2)); + } + + //*********************************************************************** + /// Greater-than-or-equal operator + //*********************************************************************** + ETL_CONSTEXPR bool operator >=(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT + { + return (static_cast(d1) >= static_cast(d2)); + } + + //*********************************************************************** + /// Spaceship operator + //*********************************************************************** +#if ETL_USING_CPP20 + [[nodiscard]] constexpr auto operator <=>(const etl::chrono::day& d1, const etl::chrono::day& d2) noexcept + { + return (static_cast(d1) <=> static_cast(d2)); + } +#endif + + //*********************************************************************** + /// Add etl::chrono::days to etl::chrono::day + ///\return etl::chrono::day //*********************************************************************** ETL_CONSTEXPR etl::chrono::day operator +(const etl::chrono::day& d, const etl::chrono::days& ds) ETL_NOEXCEPT { @@ -159,6 +242,9 @@ namespace etl return result; } + //*********************************************************************** + /// Add etl::chrono::day to etl::chrono::days + ///\return etl::chrono::day //*********************************************************************** ETL_CONSTEXPR etl::chrono::day operator +(const etl::chrono::days& ds, const etl::chrono::day& d) ETL_NOEXCEPT { @@ -169,6 +255,9 @@ namespace etl return result; } + //*********************************************************************** + /// Subtract etl::chrono::days from etl::chrono::day + ///\return etl::chrono::day //*********************************************************************** ETL_CONSTEXPR etl::chrono::day operator -(const etl::chrono::day& d, const etl::chrono::days& ds) ETL_NOEXCEPT { @@ -179,6 +268,9 @@ namespace etl return result; } + //*********************************************************************** + /// Subtract etl::chrono::day from etl::chrono::day + ///\return etl::chrono::days //*********************************************************************** ETL_CONSTEXPR etl::chrono::days operator -(const etl::chrono::day& d1, const etl::chrono::day& d2) ETL_NOEXCEPT { diff --git a/include/etl/private/chrono/duration.h b/include/etl/private/chrono/duration.h index 3e4ec95e..fdb8d9b5 100644 --- a/include/etl/private/chrono/duration.h +++ b/include/etl/private/chrono/duration.h @@ -75,25 +75,25 @@ namespace etl } //*********************************************************************** - static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::duration< TValue, TPeriod> zero() ETL_NOEXCEPT + static ETL_CONSTEXPR etl::chrono::duration< TValue, TPeriod> zero() ETL_NOEXCEPT { return etl::chrono::duration{ 0, TPeriod()}; } //*********************************************************************** - static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::duration min() ETL_NOEXCEPT + static ETL_CONSTEXPR etl::chrono::duration min() ETL_NOEXCEPT { return etl::chrono::duration { etl::numeric_limits::min() }; } //*********************************************************************** - static ETL_NODISCARD ETL_CONSTEXPR etl::chrono::duration max() ETL_NOEXCEPT + static ETL_CONSTEXPR etl::chrono::duration max() ETL_NOEXCEPT { return etl::chrono::duration{ etl::numeric_limits::max() }; } //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR TValue count() const + ETL_CONSTEXPR TValue count() const ETL_NOEXCEPT { return value; } @@ -131,9 +131,16 @@ namespace etl template ETL_CONSTEXPR TToDuration duration_cast(const etl::chrono::duration& d) { - return TToDuration(); + using to_value_type = typename TToDuration::value_type; + using to_period = typename TToDuration::period; + + // Calculate the conversion factor between the periods + ETL_CONSTEXPR auto conversion_factor = (static_cast(TPeriod::num) / TPeriod::den) * (to_period::den / to_period::num); + + // Convert the value + to_value_type converted_value = static_cast(d.count() * conversion_factor); + + return TToDuration(converted_value); } } } - -#endif diff --git a/include/etl/private/chrono/month.h b/include/etl/private/chrono/month.h new file mode 100644 index 00000000..30653a58 --- /dev/null +++ b/include/etl/private/chrono/month.h @@ -0,0 +1,383 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +namespace etl +{ + namespace chrono + { + class month; + + ETL_CONSTEXPR etl::chrono::month operator +(const etl::chrono::month& m, const etl::chrono::months& ms) ETL_NOEXCEPT; + ETL_CONSTEXPR etl::chrono::month operator +(const etl::chrono::months& ms, const etl::chrono::month& m) ETL_NOEXCEPT; + ETL_CONSTEXPR etl::chrono::month operator -(const etl::chrono::month& m, const etl::chrono::months& ms) ETL_NOEXCEPT; + + //*********************************************************************** + /// month + //*********************************************************************** + class month + { + public: + + //*********************************************************************** + /// Default constructor + //*********************************************************************** + ETL_CONSTEXPR month() ETL_NOEXCEPT + : value(0) + { + } + + //*********************************************************************** + /// Construct from unsigned + //*********************************************************************** + ETL_CONSTEXPR explicit month(unsigned value_) ETL_NOEXCEPT + : value(value_) + { + } + + //*********************************************************************** + /// Copy constructor + //*********************************************************************** + ETL_CONSTEXPR month(const etl::chrono::month& other) ETL_NOEXCEPT + : value(other.value) + { + } + + //*********************************************************************** + /// Assignment operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::month& operator =(const etl::chrono::month& rhs) ETL_NOEXCEPT + { + value = rhs.value; + + return *this; + } + + //*********************************************************************** + /// Pre-increment operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::month& operator ++() ETL_NOEXCEPT + { + *this += etl::chrono::months(1); + + return *this; + } + + //*********************************************************************** + /// Post-increment operator + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::month operator ++(int) ETL_NOEXCEPT + { + const etl::chrono::month temp = *this; + + *this += etl::chrono::months(1); + + return temp; + } + + //*********************************************************************** + /// Pre-decrement operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::month& operator --() ETL_NOEXCEPT + { + *this -= etl::chrono::months(1); + + return *this; + } + + //*********************************************************************** + /// Post-decrement operator + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::month operator --(int) ETL_NOEXCEPT + { + etl::chrono::month temp = *this; + + *this -= etl::chrono::months(1); + + return temp; + } + + //*********************************************************************** + /// Plus-equals operator adding etl::chrono::months + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::month& operator +=(const etl::chrono::months& ms) ETL_NOEXCEPT + { + *this = *this + ms; + + return *this; + } + + //*********************************************************************** + /// Minus-equals operator subtracting etl::chrono::months + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::month& operator -=(const etl::chrono::months& ms) ETL_NOEXCEPT + { + *this = *this - ms; + + return *this; + } + + //*********************************************************************** + /// Returns true if the month is within the valid 1 to 31 range + //*********************************************************************** + ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + { + return (value >= 1U) && (value <= 12U); + } + + //*********************************************************************** + /// The minimum month value for which ok() will return true + //*********************************************************************** + static ETL_CONSTEXPR etl::chrono::month min() ETL_NOEXCEPT + { + return etl::chrono::month(1); + } + + //*********************************************************************** + /// The maximum month value for which ok() will return true + //*********************************************************************** + static ETL_CONSTEXPR etl::chrono::month max() ETL_NOEXCEPT + { + return etl::chrono::month(12); + } + + //*********************************************************************** + /// Conversion operator to unsigned int + //*********************************************************************** + ETL_CONSTEXPR operator unsigned() const ETL_NOEXCEPT + { + return static_cast(value); + } + + private: + + //*********************************************************************** + /// Normalise to a in-range month + //*********************************************************************** + ETL_CONSTEXPR void normalise() ETL_NOEXCEPT + { + value = ((value % 12U) == 0U) ? 12U : value; + } + + unsigned char value; + }; + + //*********************************************************************** + /// Equality operator + //*********************************************************************** + ETL_CONSTEXPR bool operator ==(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT + { + return (static_cast(d1) == static_cast(d2)); + } + + //*********************************************************************** + /// Inequality operator + //*********************************************************************** + ETL_CONSTEXPR bool operator !=(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT + { + return !(d1 == d2); + } + + //*********************************************************************** + /// Less-than operator + //*********************************************************************** + ETL_CONSTEXPR bool operator <(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT + { + return (static_cast(d1) < static_cast(d2)); + } + + //*********************************************************************** + /// Less-than-or-equal operator + //*********************************************************************** + ETL_CONSTEXPR bool operator <=(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT + { + return (static_cast(d1) <= static_cast(d2)); + } + + //*********************************************************************** + /// Greater-than operator + //*********************************************************************** + ETL_CONSTEXPR bool operator >(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT + { + return (static_cast(d1) > static_cast(d2)); + } + + //*********************************************************************** + /// Greater-than-or-equal operator + //*********************************************************************** + ETL_CONSTEXPR bool operator >=(const etl::chrono::month& d1, const etl::chrono::month& d2) ETL_NOEXCEPT + { + return (static_cast(d1) >= static_cast(d2)); + } + + //*********************************************************************** + /// Spaceship operator + //*********************************************************************** +#if ETL_USING_CPP20 + [[nodiscard]] constexpr auto operator <=>(const etl::chrono::month& d1, const etl::chrono::month& d2) noexcept + { + return (static_cast(d1) <=> static_cast(d2)); + } +#endif + + //*********************************************************************** + /// Add etl::chrono::months to etl::chrono::month + ///\return etl::chrono::month + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::month operator +(const etl::chrono::month& m, const etl::chrono::months& ms) ETL_NOEXCEPT + { + unsigned int value = static_cast(m); + + value = value % 12U; + + if (value == 0U) + { + value = 12U; + } + + int delta = ms.count() % 12; + + // Adjust to allow a limited +-11 month delta + value += 11U; + value += delta; + value %= 12U; + ++value; + + return etl::chrono::month(value); + } + + //*********************************************************************** + /// Add etl::chrono::month to etl::chrono::months + ///\return etl::chrono::month + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::month operator +(const etl::chrono::months& ms, const etl::chrono::month& m) ETL_NOEXCEPT + { + return m + ms; + } + + //*********************************************************************** + /// Subtract etl::chrono::months from etl::chrono::month + ///\return etl::chrono::month + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::month operator -(const etl::chrono::month& m, const etl::chrono::months& ms) ETL_NOEXCEPT + { + return m + etl::chrono::months(-ms.count()); + } + + //*********************************************************************** + /// Subtract etl::chrono::month from etl::chrono::month + ///\return etl::chrono::months + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::months operator -(const etl::chrono::month& m1, const etl::chrono::month& m2) ETL_NOEXCEPT + { + if (m1.ok() && m2.ok()) + { + etl::chrono::months ms(static_cast(static_cast(m1)) - + static_cast(static_cast(m2)) % 12); + + if (m1 == (m2 + ms)) + { + return ms; + } + } + + return etl::chrono::months(); + } + +#if ETL_USING_CPP17 + inline constexpr etl::chrono::month January{ 1 }; + inline constexpr etl::chrono::month February{ 2 }; + inline constexpr etl::chrono::month March{ 3 }; + inline constexpr etl::chrono::month April{ 4 }; + inline constexpr etl::chrono::month May{ 5 }; + inline constexpr etl::chrono::month June{ 6 }; + inline constexpr etl::chrono::month July{ 7 }; + inline constexpr etl::chrono::month August{ 8 }; + inline constexpr etl::chrono::month September{ 9 }; + inline constexpr etl::chrono::month October{ 10 }; + inline constexpr etl::chrono::month November{ 11 }; + inline constexpr etl::chrono::month December{ 12 }; +#else + static ETL_CONSTANT etl::chrono::month January{ 1 }; + static ETL_CONSTANT etl::chrono::month February{ 2 }; + static ETL_CONSTANT etl::chrono::month March{ 3 }; + static ETL_CONSTANT etl::chrono::month April{ 4 }; + static ETL_CONSTANT etl::chrono::month May{ 5 }; + static ETL_CONSTANT etl::chrono::month June{ 6 }; + static ETL_CONSTANT etl::chrono::month July{ 7 }; + static ETL_CONSTANT etl::chrono::month August{ 8 }; + static ETL_CONSTANT etl::chrono::month September{ 9 }; + static ETL_CONSTANT etl::chrono::month October{ 10 }; + static ETL_CONSTANT etl::chrono::month November{ 11 }; + static ETL_CONSTANT etl::chrono::month December{ 12 }; +#endif + } + + //************************************************************************* + /// Hash function for etl::chrono::month + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::month& m) const + { + unsigned value = m; + const uint8_t* p = reinterpret_cast(&value); + + return etl::private_hash::generic_hash(p, p + sizeof(unsigned)); + } + }; +#endif +} + +#if ETL_HAS_CHRONO_LITERALS_MONTH +#if ETL_USING_CPP11 +namespace etl +{ + namespace literals + { + namespace chrono_literals + { + //*********************************************************************** + /// Literal for months + //*********************************************************************** + constexpr etl::chrono::month operator ""_month(unsigned long long m) noexcept + { + return etl::chrono::month(static_cast(m)); + } + } + } +} +#endif +#endif diff --git a/include/etl/private/chrono/weekday.h b/include/etl/private/chrono/weekday.h new file mode 100644 index 00000000..fc4df27f --- /dev/null +++ b/include/etl/private/chrono/weekday.h @@ -0,0 +1,391 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +namespace etl +{ + namespace chrono + { + class weekday; + class weekday_indexed; + class weekday_last; + struct last_spec; + + ETL_CONSTEXPR etl::chrono::weekday operator +(const etl::chrono::weekday& m, const etl::chrono::days& ds) ETL_NOEXCEPT; + ETL_CONSTEXPR etl::chrono::weekday operator +(const etl::chrono::days& ds, const etl::chrono::weekday& m) ETL_NOEXCEPT; + ETL_CONSTEXPR etl::chrono::weekday operator -(const etl::chrono::weekday& m, const etl::chrono::days& ds) ETL_NOEXCEPT; + + //*********************************************************************** + /// weekday + //*********************************************************************** + class weekday + { + public: + + //*********************************************************************** + /// Default constructor + //*********************************************************************** + ETL_CONSTEXPR weekday() ETL_NOEXCEPT + : value(255U) + { + } + + //*********************************************************************** + /// Construct from unsigned + //*********************************************************************** + ETL_CONSTEXPR explicit weekday(unsigned value_) ETL_NOEXCEPT + : value(value_ == 7U ? 0U :value_) + { + } + + //*********************************************************************** + /// Copy constructor + //*********************************************************************** + ETL_CONSTEXPR weekday(const etl::chrono::weekday& other) ETL_NOEXCEPT + : value(other.value) + { + } + + //*********************************************************************** + /// Assignment operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday& operator =(const etl::chrono::weekday& rhs) ETL_NOEXCEPT + { + value = rhs.value; + + return *this; + } + + //*********************************************************************** + /// Pre-increment operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday& operator ++() ETL_NOEXCEPT + { + *this += etl::chrono::days(1); + + return *this; + } + + //*********************************************************************** + /// Post-increment operator + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::weekday operator ++(int) ETL_NOEXCEPT + { + const etl::chrono::weekday temp = *this; + + *this += etl::chrono::days(1); + + return temp; + } + + //*********************************************************************** + /// Pre-decrement operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday& operator --() ETL_NOEXCEPT + { + *this -= etl::chrono::days(1); + + return *this; + } + + //*********************************************************************** + /// Post-decrement operator + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::weekday operator --(int) ETL_NOEXCEPT + { + etl::chrono::weekday temp = *this; + + *this -= etl::chrono::days(1); + + return temp; + } + + //*********************************************************************** + /// Plus-equals operator adding etl::chrono::days + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday& operator +=(const etl::chrono::days& ds) ETL_NOEXCEPT + { + *this = *this + ds; + + return *this; + } + + //*********************************************************************** + /// Minus-equals operator subtracting etl::chrono::days + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday& operator -=(const etl::chrono::days& ds) ETL_NOEXCEPT + { + *this = *this - ds; + + return *this; + } + + //*********************************************************************** + /// Returns true if the weekday is within the valid 1 to 31 range + //*********************************************************************** + ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + { + return (c_encoding() <= 6U); + } + + //*********************************************************************** + /// The minimum weekday value for which ok() will return true + //*********************************************************************** + static ETL_CONSTEXPR etl::chrono::weekday min() ETL_NOEXCEPT + { + return etl::chrono::weekday(0); + } + + //*********************************************************************** + /// The maximum weekday value for which ok() will return true + //*********************************************************************** + static ETL_CONSTEXPR etl::chrono::weekday max() ETL_NOEXCEPT + { + return etl::chrono::weekday(6); + } + + //*********************************************************************** + /// Get the C encoding of the weekday + //*********************************************************************** + ETL_CONSTEXPR unsigned c_encoding() const ETL_NOEXCEPT + { + return value; + } + + //*********************************************************************** + /// Get the ISO encoding of the weekday + //*********************************************************************** + ETL_CONSTEXPR unsigned iso_encoding() const ETL_NOEXCEPT + { + return (value == 0U) ? 7U : value; + } + + //*********************************************************************** + /// Index operator from index + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday_indexed operator[](unsigned index) const ETL_NOEXCEPT; + + //*********************************************************************** + /// Index operator from etl::chrono::last_spec + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday_last operator[](etl::chrono::last_spec) const ETL_NOEXCEPT; + + //*********************************************************************** + /// Returns true if the day is a weekend. + //*********************************************************************** + ETL_CONSTEXPR14 bool is_weekend() ETL_NOEXCEPT + { + return (c_encoding() == 0U) || (c_encoding() == 6U); + } + + private: + + //*********************************************************************** + /// Normalise to a in-range weekday + //*********************************************************************** + ETL_CONSTEXPR void normalise() ETL_NOEXCEPT + { + value %= 7U; + } + + unsigned char value; + }; + + //*********************************************************************** + /// Equality operator + //*********************************************************************** + ETL_CONSTEXPR bool operator ==(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + { + return (wd1.c_encoding() == wd2.c_encoding()); + } + + //*********************************************************************** + /// Inequality operator + //*********************************************************************** + ETL_CONSTEXPR bool operator !=(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + { + return !(wd1 == wd2); + } + + //*********************************************************************** + /// Less-than operator + //*********************************************************************** + ETL_CONSTEXPR bool operator <(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + { + return (wd1.c_encoding() < wd2.c_encoding()); + } + + //*********************************************************************** + /// Less-than-or-equal operator + //*********************************************************************** + ETL_CONSTEXPR bool operator <=(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + { + return (wd1.c_encoding() <= wd2.c_encoding()); + } + + //*********************************************************************** + /// Greater-than operator + //*********************************************************************** + ETL_CONSTEXPR bool operator >(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + { + return (wd1.c_encoding() > wd2.c_encoding()); + } + + //*********************************************************************** + /// Greater-than-or-equal operator + //*********************************************************************** + ETL_CONSTEXPR bool operator >=(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + { + return (wd1.c_encoding() >= wd2.c_encoding()); + } + + //*********************************************************************** + /// Spaceship operator + //*********************************************************************** +#if ETL_USING_CPP20 + [[nodiscard]] constexpr auto operator <=>(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) noexcept + { + return (wd1.c_encoding() <=> wd2.c_encoding()); + } +#endif + + //*********************************************************************** + /// Add etl::chrono::days to etl::chrono::weekday + ///\return etl::chrono::weekday + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::weekday operator +(const etl::chrono::weekday& wd, const etl::chrono::days& ds) ETL_NOEXCEPT + { + int delta = ds.count() % 7; + + unsigned int value = wd.c_encoding(); + + // Adjust to allow a limited +-7 weekday delta + value %= 7U; + value += 7U; + value += delta; + value %= 7U; + + return etl::chrono::weekday(value); + } + + //*********************************************************************** + /// Add etl::chrono::weekday to etl::chrono::days + ///\return etl::chrono::weekday + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday operator +(const etl::chrono::days& ds, const etl::chrono::weekday& wd) ETL_NOEXCEPT + { + return wd + ds; + } + + //*********************************************************************** + /// Subtract etl::chrono::days from etl::chrono::weekday + ///\return etl::chrono::weekday + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday operator -(const etl::chrono::weekday& m, const etl::chrono::days& ds) ETL_NOEXCEPT + { + return m + etl::chrono::days(-ds.count()); + } + + //*********************************************************************** + /// Subtract etl::chrono::weekday from etl::chrono::weekday + ///\return etl::chrono::days + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::days operator -(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT + { + if (wd1.ok() && wd2.ok()) + { + int diff = static_cast(wd1.c_encoding()) - static_cast(wd2.c_encoding()); + + return etl::chrono::days((diff + 7) % 7); + } + + return etl::chrono::days(0); + } + +#if ETL_USING_CPP17 + inline constexpr etl::chrono::weekday Sunday{ 0U }; + inline constexpr etl::chrono::weekday Monday{ 1U }; + inline constexpr etl::chrono::weekday Tuesday{ 2U }; + inline constexpr etl::chrono::weekday Wednesday{ 3U }; + inline constexpr etl::chrono::weekday Thursday{ 4U }; + inline constexpr etl::chrono::weekday Friday{ 5U }; + inline constexpr etl::chrono::weekday Saturday{ 6U }; +#else + static ETL_CONSTANT etl::chrono::weekday Sunday{ 0U }; + static ETL_CONSTANT etl::chrono::weekday Monday{ 1U }; + static ETL_CONSTANT etl::chrono::weekday Tuesday{ 2U }; + static ETL_CONSTANT etl::chrono::weekday Wednesday{ 3U }; + static ETL_CONSTANT etl::chrono::weekday Thursday{ 4U }; + static ETL_CONSTANT etl::chrono::weekday Friday{ 5U }; + static ETL_CONSTANT etl::chrono::weekday Saturday{ 6U }; +#endif + } + + //************************************************************************* + /// Hash function for etl::chrono::weekday + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::weekday& wd) const + { + unsigned value = wd.c_encoding(); + const uint8_t* p = reinterpret_cast(&value); + + return etl::private_hash::generic_hash(p, p + sizeof(unsigned)); + } + }; +#endif +} + +#if ETL_HAS_CHRONO_LITERALS_WEEKDAY +#if ETL_USING_CPP11 +namespace etl +{ + namespace literals + { + namespace chrono_literals + { + //*********************************************************************** + /// Literal for weekdays + //*********************************************************************** + constexpr etl::chrono::weekday operator ""_weekday(unsigned long long m) noexcept + { + return etl::chrono::weekday(static_cast(m)); + } + } + } +} +#endif +#endif diff --git a/include/etl/private/chrono/year.h b/include/etl/private/chrono/year.h new file mode 100644 index 00000000..ff873e37 --- /dev/null +++ b/include/etl/private/chrono/year.h @@ -0,0 +1,332 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +namespace etl +{ + namespace chrono + { + //*********************************************************************** + /// year + //*********************************************************************** + class year + { + public: + + //*********************************************************************** + /// Default constructor + //*********************************************************************** + ETL_CONSTEXPR year() ETL_NOEXCEPT + : value(0) + { + } + + //*********************************************************************** + /// Construct from unsigned + //*********************************************************************** + ETL_CONSTEXPR explicit year(unsigned value_) ETL_NOEXCEPT + : value(value_) + { + } + + //*********************************************************************** + /// Copy constructor + //*********************************************************************** + ETL_CONSTEXPR year(const etl::chrono::year& other) ETL_NOEXCEPT + : value(other.value) + { + } + + //*********************************************************************** + /// Assignment operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::year& operator =(const etl::chrono::year& rhs) ETL_NOEXCEPT + { + value = rhs.value; + + return *this; + } + + //*********************************************************************** + /// Pre-increment operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::year& operator ++() ETL_NOEXCEPT + { + ++value; + + return *this; + } + + //*********************************************************************** + /// Post-increment operator + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::year operator ++(int) ETL_NOEXCEPT + { + const etl::chrono::year temp = *this; + ++value; + + return temp; + } + + //*********************************************************************** + /// Pre-decrement operator + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::year& operator --() ETL_NOEXCEPT + { + --value; + + return *this; + } + + //*********************************************************************** + /// Post-decrement operator + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::year operator --(int) ETL_NOEXCEPT + { + const etl::chrono::year temp = *this; + --value; + + return temp; + } + + //*********************************************************************** + /// Plus-equals operator adding etl::chrono::years + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::year& operator +=(const etl::chrono::years& ys) ETL_NOEXCEPT + { + value += static_cast(ys.count()); + + return *this; + } + + //*********************************************************************** + /// Minus-equals operator subtracting etl::chrono::years + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::year& operator -=(const etl::chrono::years& ys) ETL_NOEXCEPT + { + value -= static_cast(ys.count()); + + return *this; + } + + //*********************************************************************** + /// Returns true if the year is within the valid -32767 to 32767 range + //*********************************************************************** + ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + { + return (value != -32768); + } + + //*********************************************************************** + /// The minimum year value for which ok() will return true + //*********************************************************************** + static ETL_CONSTEXPR etl::chrono::year min() ETL_NOEXCEPT + { + return etl::chrono::year(-32767); + } + + //*********************************************************************** + /// The maximum year value for which ok() will return true + //*********************************************************************** + static ETL_CONSTEXPR etl::chrono::year max() ETL_NOEXCEPT + { + return etl::chrono::year(32767); + } + + //*********************************************************************** + /// Returns true if the year is a leap year + //*********************************************************************** + ETL_CONSTEXPR bool is_leap() const ETL_NOEXCEPT + { + return ((value % 4) == 0) && !((value % 400) == 0); + } + + //*********************************************************************** + /// Conversion operator to unsigned int + //*********************************************************************** + ETL_CONSTEXPR operator int() const ETL_NOEXCEPT + { + return static_cast(value); + } + + private: + + int16_t value; + }; + + //*********************************************************************** + /// Equality operator + //*********************************************************************** + ETL_CONSTEXPR bool operator ==(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + { + return (static_cast(y1) == static_cast(y2)); + } + + //*********************************************************************** + /// Inequality operator + //*********************************************************************** + ETL_CONSTEXPR bool operator !=(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + { + return !(y1 == y2); + } + + //*********************************************************************** + /// Less-than operator + //*********************************************************************** + ETL_CONSTEXPR bool operator <(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + { + return (static_cast(y1) < static_cast(y2)); + } + + //*********************************************************************** + /// Less-than-or-equal operator + //*********************************************************************** + ETL_CONSTEXPR bool operator <=(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + { + return (static_cast(y1) <= static_cast(y2)); + } + + //*********************************************************************** + /// Greater-than operator + //*********************************************************************** + ETL_CONSTEXPR bool operator >(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + { + return (static_cast(y1) > static_cast(y2)); + } + + //*********************************************************************** + /// Greater-than-or-equal operator + //*********************************************************************** + ETL_CONSTEXPR bool operator >=(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + { + return (static_cast(y1) >= static_cast(y2)); + } + + //*********************************************************************** + /// Spaceship operator + //*********************************************************************** +#if ETL_USING_CPP20 + [[nodiscard]] constexpr auto operator <=>(const etl::chrono::year& y1, const etl::chrono::year& y2) noexcept + { + return (static_cast(y1) <=> static_cast(y2)); + } +#endif + + //*********************************************************************** + /// Add etl::chrono::years to etl::chrono::year + ///\return etl::chrono::year + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::year operator +(const etl::chrono::year& y, const etl::chrono::years& ys) ETL_NOEXCEPT + { + etl::chrono::year result(y); + + result += ys; + + return result; + } + + //*********************************************************************** + /// Add etl::chrono::year to etl::chrono::years + ///\return etl::chrono::year + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::year operator +(const etl::chrono::years& ys, const etl::chrono::year& y) ETL_NOEXCEPT + { + etl::chrono::year result(y); + + result += ys; + + return result; + } + + //*********************************************************************** + /// Subtract etl::chrono::years from etl::chrono::year + ///\return etl::chrono::year + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::year operator -(const etl::chrono::year& y, const etl::chrono::years& ys) ETL_NOEXCEPT + { + etl::chrono::year result(y); + + result -= ys; + + return result; + } + + //*********************************************************************** + /// Subtract etl::chrono::year from etl::chrono::year + ///\return etl::chrono::years + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::years operator -(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT + { + return etl::chrono::years(static_cast(static_cast(y1)) - + static_cast(static_cast(y2))); + } + } + + //************************************************************************* + /// Hash function for etl::chrono::year + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::year& y) const + { + int value = y; + const uint8_t* p = reinterpret_cast(&value); + + return etl::private_hash::generic_hash(p, p + sizeof(int)); + } + }; +#endif +} + +#if ETL_HAS_CHRONO_LITERALS_YEAR +#if ETL_USING_CPP11 +namespace etl +{ + namespace literals + { + namespace chrono_literals + { + //*********************************************************************** + /// Literal for years + //*********************************************************************** + constexpr etl::chrono::year operator ""_year(unsigned long long y) noexcept + { + return etl::chrono::year(static_cast(y)); + } + } + } +} +#endif +#endif diff --git a/test/test_chrono_weekday.cpp b/test/test_chrono_weekday.cpp new file mode 100644 index 00000000..c4cbe05d --- /dev/null +++ b/test/test_chrono_weekday.cpp @@ -0,0 +1,379 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include + +#include +#include + +namespace +{ + SUITE(test_chrono_weekday) + { + //************************************************************************* + TEST(test_default_constructor) + { + etl::chrono::weekday weekday; + + CHECK_FALSE(weekday.ok()); + } + + //************************************************************************* + TEST(test_constructor_in_range) + { + for (unsigned i = 0U; i < 7U; ++i) + { + etl::chrono::weekday weekday(i); + + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(i, weekday.c_encoding()); + CHECK_EQUAL((i == 0U) ? 7U : i, weekday.iso_encoding()); + } + } + + //************************************************************************* + TEST(test_constructor_out_of_range) + { + for (unsigned i = 8U; i < 256U; ++i) + { + etl::chrono::weekday weekday(i); + + CHECK_FALSE(weekday.ok()); + CHECK_EQUAL(i, weekday.c_encoding()); + CHECK_EQUAL((i == 0U) ? 7U : i, weekday.iso_encoding()); + } + } + + //************************************************************************* + TEST(test_pre_increment) + { + etl::chrono::weekday weekday(0); + unsigned count = 0; + + for (int i = 0; i < 255; ++i) + { + ++weekday; + ++count; + + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(count % 7, weekday.c_encoding()); + CHECK_EQUAL((count % 7 == 0U) ? 7U : count % 7, weekday.iso_encoding()); + } + } + + //************************************************************************* + TEST(test_post_increment) + { + etl::chrono::weekday weekday(0); + unsigned count = 0; + + for (int i = 0; i < 255; ++i) + { + etl::chrono::weekday last_weekday = weekday++; + unsigned last_count = count++; + + CHECK_TRUE(last_weekday.ok()); + CHECK_EQUAL(last_count % 7, last_weekday.c_encoding()); + CHECK_EQUAL((last_count % 7 == 0U) ? 7U : last_count % 7, last_weekday.iso_encoding()); + + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(count % 7, weekday.c_encoding()); + CHECK_EQUAL((count % 7 == 0U) ? 7U : count % 7, weekday.iso_encoding()); + } + } + + //************************************************************************* + TEST(test_pre_decrement) + { + etl::chrono::weekday weekday(255U); + unsigned count = 255U; + + for (int i = 0; i < 255; ++i) + { + --weekday; + --count; + + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(count % 7, weekday.c_encoding()); + CHECK_EQUAL((count % 7 == 0U) ? 7U : count % 7, weekday.iso_encoding()); + } + } + + //************************************************************************* + TEST(test_post_decrement) + { + etl::chrono::weekday weekday(255U); + unsigned count = 255U; + + for (int i = 0; i < 255; ++i) + { + etl::chrono::weekday last_weekday = weekday--; + unsigned last_count = count--; + + if (last_count == 255U) + { + CHECK_FALSE(last_weekday.ok()); + CHECK_EQUAL(255U, last_weekday.c_encoding()); + CHECK_EQUAL(255U, last_weekday.iso_encoding()); + } + else + { + CHECK_TRUE(last_weekday.ok()); + CHECK_EQUAL(last_count % 7, last_weekday.c_encoding()); + CHECK_EQUAL((last_count % 7 == 0U) ? 7U : last_count % 7, last_weekday.iso_encoding()); + } + + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(count % 7, weekday.c_encoding()); + CHECK_EQUAL((count % 7 == 0U) ? 7U : count % 7, weekday.iso_encoding()); + } + } + + //************************************************************************* + TEST(test_plus_equal_days) + { + for (unsigned wd = 0; wd <= 6; ++wd) + { + for (unsigned ds = 0; ds <= 14; ++ds) + { + etl::chrono::weekday weekday(wd); + etl::chrono::days days(ds); + weekday += days; + + unsigned expected = (wd + ds) % 7; + + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(expected, weekday.c_encoding()); + CHECK_EQUAL((expected == 0U) ? 7U : expected, weekday.iso_encoding()); + } + } + } + + //************************************************************************* + TEST(test_weekday_plus_days) + { + for (unsigned wd = 0; wd <= 6; ++wd) + { + for (unsigned ds = 0; ds <= 14; ++ds) + { + etl::chrono::weekday weekday(wd); + etl::chrono::days days(ds); + weekday = weekday + days; + + unsigned expected = (wd + ds) % 7; + + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(expected, weekday.c_encoding()); + CHECK_EQUAL((expected == 0U) ? 7U : expected, weekday.iso_encoding()); + } + } + } + + //************************************************************************* + TEST(test_days_plus_weekday) + { + for (unsigned wd = 0; wd <= 6; ++wd) + { + for (unsigned ds = 0; ds <= 14; ++ds) + { + etl::chrono::weekday weekday(wd); + etl::chrono::days days(ds); + weekday = weekday + days; + + unsigned expected = (ds + wd) % 7; + + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(expected, weekday.c_encoding()); + CHECK_EQUAL((expected == 0U) ? 7U : expected, weekday.iso_encoding()); + } + } + } + + //************************************************************************* + TEST(test_minus_equal_days) + { + for (unsigned wd = 0; wd <= 6; ++wd) + { + for (unsigned ds = 0; ds <= 14; ++ds) + { + etl::chrono::weekday weekday(wd); + etl::chrono::days days(ds); + weekday -= days; + + unsigned expected = ((wd + 7U) - (ds % 7U)) % 7U; + + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(expected, weekday.c_encoding()); + CHECK_EQUAL((expected == 0U) ? 7U : expected, weekday.iso_encoding()); + } + } + } + + //************************************************************************* + TEST(test_weekday_minus_days) + { + for (unsigned wd = 0; wd <= 6; ++wd) + { + for (unsigned ds = 0; ds <= 14; ++ds) + { + etl::chrono::weekday weekday(wd); + etl::chrono::days days(ds); + weekday = weekday - days; + + unsigned expected = ((wd + 7U) - (ds % 7U)) % 7U; + + CHECK_TRUE(weekday.ok()); + CHECK_EQUAL(expected, weekday.c_encoding()); + CHECK_EQUAL((expected == 0U) ? 7U : expected, weekday.iso_encoding()); + } + } + } + + //************************************************************************* + TEST(test_weekday_minus_weekday) + { + for (int m = 0; m < 7; ++m) + { + etl::chrono::weekday weekday1(m); + etl::chrono::weekday weekday2(7 - m); + + std::chrono::weekday std_weekday1(m); + std::chrono::weekday std_weekday2(7 - m); + + auto days12 = weekday1 - weekday2; + auto days21 = weekday2 - weekday1; + + auto std_days12 = std_weekday1 - std_weekday2; + auto std_days21 = std_weekday2 - std_weekday1; + + CHECK_EQUAL(std_days12.count(), days12.count()); + CHECK_EQUAL(std_days21.count(), days21.count()); + } + } + + //************************************************************************* + TEST(test_min_max_weekday) + { + CHECK_EQUAL(etl::chrono::Sunday.c_encoding(), etl::chrono::weekday::min().c_encoding()); + CHECK_EQUAL(etl::chrono::Saturday.c_encoding(), etl::chrono::weekday::max().c_encoding()); + } + + //************************************************************************* + TEST(test_weekday_constants) + { + CHECK_EQUAL(0U, etl::chrono::Sunday.c_encoding()); + CHECK_EQUAL(1U, etl::chrono::Monday.c_encoding()); + CHECK_EQUAL(2U, etl::chrono::Tuesday.c_encoding()); + CHECK_EQUAL(3U, etl::chrono::Wednesday.c_encoding()); + CHECK_EQUAL(4U, etl::chrono::Thursday.c_encoding()); + CHECK_EQUAL(5U, etl::chrono::Friday.c_encoding()); + CHECK_EQUAL(6U, etl::chrono::Saturday.c_encoding()); + } + + //************************************************************************* + TEST(test_weekday_literals) + { + using namespace etl::literals::chrono_literals; + + etl::chrono::weekday weekday0 = 0_weekday; + etl::chrono::weekday weekday1 = 1_weekday; + etl::chrono::weekday weekday2 = 2_weekday; + etl::chrono::weekday weekday3 = 3_weekday; + etl::chrono::weekday weekday4 = 4_weekday; + etl::chrono::weekday weekday5 = 5_weekday; + etl::chrono::weekday weekday6 = 6_weekday; + + CHECK_TRUE(weekday0.ok()); + CHECK_TRUE(weekday1.ok()); + CHECK_TRUE(weekday2.ok()); + CHECK_TRUE(weekday3.ok()); + CHECK_TRUE(weekday4.ok()); + CHECK_TRUE(weekday5.ok()); + CHECK_TRUE(weekday6.ok()); + + CHECK_EQUAL(0U, weekday0.c_encoding()); + CHECK_EQUAL(1U, weekday1.c_encoding()); + CHECK_EQUAL(2U, weekday2.c_encoding()); + CHECK_EQUAL(3U, weekday3.c_encoding()); + CHECK_EQUAL(4U, weekday4.c_encoding()); + CHECK_EQUAL(5U, weekday5.c_encoding()); + CHECK_EQUAL(6U, weekday6.c_encoding()); + } + + //************************************************************************* + TEST(test_weekday_comparison_operators) + { + etl::chrono::weekday weekday1(1); + etl::chrono::weekday weekday2(2); + + CHECK_TRUE(weekday1 == weekday1); + CHECK_FALSE(weekday1 != weekday1); + CHECK_TRUE(weekday1 < weekday2); + CHECK_FALSE(weekday1 < weekday1); + CHECK_FALSE(weekday2 < weekday1); + CHECK_TRUE(weekday1 <= weekday2); + CHECK_TRUE(weekday1 <= weekday1); + CHECK_FALSE(weekday2 <= weekday1); + CHECK_FALSE(weekday1 > weekday2); + CHECK_FALSE(weekday1 > weekday1); + CHECK_TRUE(weekday2 > weekday1); + CHECK_FALSE(weekday1 >= weekday2); + CHECK_TRUE(weekday1 >= weekday1); + CHECK_TRUE(weekday2 >= weekday1); + +#if ETL_USING_CPP20 + CHECK_TRUE((weekday1 <=> weekday1) == 0); + CHECK_TRUE((weekday1 <=> weekday2) < 0); + CHECK_TRUE((weekday2 <=> weekday1) > 0); +#endif + } + + //************************************************************************* + TEST(test_weekday_hashes_are_unique) + { + std::vector hashes; + + for (int i = 0; i < 256; ++i) + { + hashes.push_back(etl::hash()(etl::chrono::weekday(i))); + } + + std::sort(hashes.begin(), hashes.end()); + (void)std::unique(hashes.begin(), hashes.end()); + CHECK_EQUAL(256U, hashes.size()); + } + }; +} diff --git a/test/test_chrono_year.cpp b/test/test_chrono_year.cpp new file mode 100644 index 00000000..dacb9c06 --- /dev/null +++ b/test/test_chrono_year.cpp @@ -0,0 +1,317 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#if ETL_USING_CPP20 + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include +#include + +namespace +{ + SUITE(test_chrono_year) + { + //************************************************************************* + TEST(test_default_constructor) + { + std::chrono::year std_year; + etl::chrono::year year; + + CHECK_EQUAL(std_year.ok(), year.ok()); + } + + //************************************************************************* + TEST(test_constructor_in_range) + { + for (int32_t i = -32767; i <= 32767; ++i) + { + std::chrono::year std_year(i); + etl::chrono::year year(i); + + CHECK_TRUE(year.ok()); + CHECK_EQUAL(i, int(year)); + } + } + + //************************************************************************* + TEST(test_pre_increment) + { + etl::chrono::year year(-32767); + int count = int(year); + + for (int32_t i = 0; i < 65534; ++i) + { + ++count; + etl::chrono::year this_year = ++year; + + CHECK_TRUE(year.ok()); + CHECK_EQUAL(count, year); + CHECK_EQUAL(this_year, year); + } + } + + //************************************************************************* + TEST(test_post_increment) + { + std::chrono::year std_year(-32767); + etl::chrono::year year(-32767); + + for (int32_t i = 0; i < 65536; ++i) + { + std::chrono::year std_last_year = std_year++; + etl::chrono::year last_year = year++; + + CHECK_EQUAL(std_last_year.ok(), last_year.ok()); + CHECK_EQUAL(int(std_last_year), int(last_year)); + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + } + + //************************************************************************* + TEST(test_pre_decrement) + { + std::chrono::year std_year(256); + etl::chrono::year year(256); + + for (int i = 0; i < 255; ++i) + { + --std_year; + --year; + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + } + + //************************************************************************* + TEST(test_post_decrement) + { + std::chrono::year std_year(256); + etl::chrono::year year(256); + + for (int i = 0; i < 255; ++i) + { + std::chrono::year std_last_year = std_year--; + etl::chrono::year last_year = year--; + + CHECK_EQUAL(std_last_year.ok(), last_year.ok()); + CHECK_EQUAL(int(std_last_year), int(last_year)); + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + } + + //************************************************************************* + TEST(test_plus_equal_years) + { + std::chrono::year std_year(0); + etl::chrono::year year(0); + + std::chrono::years std_years(2); + etl::chrono::years years(2); + + for (int i = 0; i < 128; ++i) + { + std_year += std_years; + year += years; + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + } + + //************************************************************************* + TEST(test_year_plus_years) + { + std::chrono::year std_year(0); + etl::chrono::year year(0); + + std::chrono::years std_years(2); + etl::chrono::years years(2); + + for (int i = 0; i < 128; ++i) + { + std_year = std_year + std_years; + year = year + years; + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + } + + //************************************************************************* + TEST(test_years_plus_year) + { + std::chrono::year std_year(0); + etl::chrono::year year(0); + + std::chrono::years std_years(2); + etl::chrono::years years(2); + + for (int i = 0; i < 128; ++i) + { + std_year = std_years + std_year; + year = years + year; + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + } + + //************************************************************************* + TEST(test_minus_equal_years) + { + std::chrono::year std_year(256); + etl::chrono::year year(256); + + std::chrono::years std_years(2); + etl::chrono::years years(2); + + for (int i = 0; i < 128; ++i) + { + std_year -= std_years; + year -= years; + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + } + + //************************************************************************* + TEST(test_year_minus_years) + { + std::chrono::year std_year(0); + etl::chrono::year year(0); + + std::chrono::years std_years(2); + etl::chrono::years years(2); + + for (int i = 0; i < 128; ++i) + { + std_year = std_year - std_years; + year = year - years; + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + } + + //************************************************************************* + TEST(test_year_minus_year) + { + for (int i = 1; i < 31; ++i) + { + std::chrono::year std_year1(i); + std::chrono::year std_year2(31 - i); + + etl::chrono::year year1(i); + etl::chrono::year year2(31 - i); + + std::chrono::years std_years = std_year1 - std_year2; + etl::chrono::years years = year1 - year2; + + CHECK_EQUAL(std_years.count(), years.count()); + } + } + + //************************************************************************* + TEST(test_min_max_year) + { + CHECK_EQUAL(-32767, etl::chrono::year::min()); + CHECK_EQUAL(32767, etl::chrono::year::max()); + } + + //************************************************************************* + TEST(test_literal_year) + { + using namespace std::literals::chrono_literals; + using namespace etl::literals::chrono_literals; + + std::chrono::year std_year = 25y; + etl::chrono::year year = 25_year; + + CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_EQUAL(int(std_year), int(year)); + } + + //************************************************************************* + TEST(test_year_comparison_operators) + { + etl::chrono::year year10(10); + etl::chrono::year year20(20); + + CHECK_TRUE(year10 == year10); + CHECK_FALSE(year10 != year10); + CHECK_TRUE(year10 < year20); + CHECK_FALSE(year10 < year10); + CHECK_FALSE(year20 < year10); + CHECK_TRUE(year10 <= year20); + CHECK_TRUE(year10 <= year10); + CHECK_FALSE(year20 <= year10); + CHECK_FALSE(year10 > year20); + CHECK_FALSE(year10 > year10); + CHECK_TRUE(year20 > year10); + CHECK_FALSE(year10 >= year20); + CHECK_TRUE(year10 >= year10); + CHECK_TRUE(year20 >= year10); + +#if ETL_USING_CPP20 + CHECK_TRUE((year10 <=> year10) == 0); + CHECK_TRUE((year10 <=> year20) < 0); + CHECK_TRUE((year20 <=> year10) > 0); +#endif + } + + //************************************************************************* + TEST(test_year_hashes_are_unique) + { + std::vector hashes; + + for (int32_t i = -32767; i < 32768; ++i) + { + hashes.push_back(etl::hash()(etl::chrono::year(i))); + } + + std::sort(hashes.begin(), hashes.end()); + (void)std::unique(hashes.begin(), hashes.end()); + CHECK_EQUAL(65535U, hashes.size()); + } + }; +} + +#endif \ No newline at end of file From e6c47a198cfdd04d65e7acb3f7e5cdb81b0ca3e2 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 8 Sep 2024 17:28:52 +0100 Subject: [PATCH 11/33] Added tests for weekday_indexed and weekday_last --- include/etl/private/chrono/weekday_indexed.h | 6 +- include/etl/private/chrono/weekday_last.h | 25 +--- test/test_chrono_weekday_indexed.cpp | 149 +++++++++++++++++++ test/test_chrono_weekday_last.cpp | 120 +++++++++++++++ test/vs2022/etl.vcxproj | 2 + 5 files changed, 276 insertions(+), 26 deletions(-) create mode 100644 test/test_chrono_weekday_indexed.cpp create mode 100644 test/test_chrono_weekday_last.cpp diff --git a/include/etl/private/chrono/weekday_indexed.h b/include/etl/private/chrono/weekday_indexed.h index 6c2f37e3..46bc2354 100644 --- a/include/etl/private/chrono/weekday_indexed.h +++ b/include/etl/private/chrono/weekday_indexed.h @@ -47,11 +47,13 @@ namespace etl /// Default constructor //*********************************************************************** ETL_CONSTEXPR weekday_indexed() ETL_NOEXCEPT + : wd() + , i() { } //*********************************************************************** - /// Construct from unsigned + /// Construct from weekday and index //*********************************************************************** ETL_CONSTEXPR weekday_indexed(const etl::chrono::weekday& wd_, unsigned index_) ETL_NOEXCEPT : wd(wd_) @@ -100,7 +102,7 @@ namespace etl //*********************************************************************** ETL_NODISCARD ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT { - return wd.ok() && (i >= 1U) && (i <= 5); + return wd.ok() && (i >= 1U) && (i <= 5U); } private: diff --git a/include/etl/private/chrono/weekday_last.h b/include/etl/private/chrono/weekday_last.h index e61890f9..62dc337a 100644 --- a/include/etl/private/chrono/weekday_last.h +++ b/include/etl/private/chrono/weekday_last.h @@ -43,17 +43,10 @@ namespace etl { public: - //*********************************************************************** - /// Default constructor - //*********************************************************************** - ETL_CONSTEXPR weekday_last() ETL_NOEXCEPT - { - } - //*********************************************************************** /// Construct from unsigned //*********************************************************************** - ETL_CONSTEXPR weekday_last(const etl::chrono::weekday& wd_) ETL_NOEXCEPT + ETL_CONSTEXPR explicit weekday_last(const etl::chrono::weekday& wd_) ETL_NOEXCEPT : wd(wd_) { } @@ -104,22 +97,6 @@ namespace etl { return (wd1.weekday() == wd2.weekday()); } - - //*********************************************************************** - /// Inequality operator - //*********************************************************************** - ETL_CONSTEXPR bool operator !=(const etl::chrono::weekday_last& wd1, const etl::chrono::weekday_last& wd2) ETL_NOEXCEPT - { - return !(wd1 == wd2); - } - - //*********************************************************************** - /// weekday index operator from index - //*********************************************************************** - ETL_CONSTEXPR etl::chrono::weekday_last etl::chrono::weekday::operator[](etl::chrono::last_spec) const ETL_NOEXCEPT - { - return etl::chrono::weekday_last(*this); - } } //************************************************************************* diff --git a/test/test_chrono_weekday_indexed.cpp b/test/test_chrono_weekday_indexed.cpp new file mode 100644 index 00000000..faa55596 --- /dev/null +++ b/test/test_chrono_weekday_indexed.cpp @@ -0,0 +1,149 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2024 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include + +#include +#include + +namespace +{ + SUITE(test_chrono_weekday_indexed) + { + //************************************************************************* + TEST(test_default_constructor) + { + etl::chrono::weekday_indexed weekday_indexed; + + CHECK_FALSE(weekday_indexed.ok()); + } + + //************************************************************************* + TEST(test_constructor_in_range) + { + for (unsigned i = 1U; i < 5U; ++i) + { + etl::chrono::weekday_indexed weekday_indexed_monday(etl::chrono::Monday, i); + etl::chrono::weekday_indexed weekday_indexed_tuesday(etl::chrono::Tuesday, i); + etl::chrono::weekday_indexed weekday_indexed_wednesday(etl::chrono::Wednesday, i); + etl::chrono::weekday_indexed weekday_indexed_thursday(etl::chrono::Thursday, i); + etl::chrono::weekday_indexed weekday_indexed_friday(etl::chrono::Friday, i); + etl::chrono::weekday_indexed weekday_indexed_saturday(etl::chrono::Saturday, i); + etl::chrono::weekday_indexed weekday_indexed_sunday(etl::chrono::Sunday, i); + + CHECK_TRUE(weekday_indexed_monday.ok()); + CHECK_TRUE(weekday_indexed_tuesday.ok()); + CHECK_TRUE(weekday_indexed_wednesday.ok()); + CHECK_TRUE(weekday_indexed_thursday.ok()); + CHECK_TRUE(weekday_indexed_friday.ok()); + CHECK_TRUE(weekday_indexed_saturday.ok()); + CHECK_TRUE(weekday_indexed_sunday.ok()); + + CHECK_EQUAL(etl::chrono::Monday.c_encoding(), weekday_indexed_monday.weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::Tuesday.c_encoding(), weekday_indexed_tuesday.weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::Wednesday.c_encoding(), weekday_indexed_wednesday.weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::Thursday.c_encoding(), weekday_indexed_thursday.weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::Friday.c_encoding(), weekday_indexed_friday.weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::Saturday.c_encoding(), weekday_indexed_saturday.weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::Sunday.c_encoding(), weekday_indexed_sunday.weekday().c_encoding()); + + CHECK_EQUAL(i, weekday_indexed_monday.index()); + CHECK_EQUAL(i, weekday_indexed_tuesday.index()); + CHECK_EQUAL(i, weekday_indexed_wednesday.index()); + CHECK_EQUAL(i, weekday_indexed_thursday.index()); + CHECK_EQUAL(i, weekday_indexed_friday.index()); + CHECK_EQUAL(i, weekday_indexed_saturday.index()); + CHECK_EQUAL(i, weekday_indexed_sunday.index()); + } + } + + //************************************************************************* + TEST(test_constructor_out_of_range) + { + for (unsigned i = 6U; i < 256U; ++i) + { + etl::chrono::weekday_indexed weekday_indexed_monday(etl::chrono::Monday, i); + etl::chrono::weekday_indexed weekday_indexed_tuesday(etl::chrono::Tuesday, i); + etl::chrono::weekday_indexed weekday_indexed_wednesday(etl::chrono::Wednesday, i); + etl::chrono::weekday_indexed weekday_indexed_thursday(etl::chrono::Thursday, i); + etl::chrono::weekday_indexed weekday_indexed_friday(etl::chrono::Friday, i); + etl::chrono::weekday_indexed weekday_indexed_saturday(etl::chrono::Saturday, i); + etl::chrono::weekday_indexed weekday_indexed_sunday(etl::chrono::Sunday, i); + + CHECK_FALSE(weekday_indexed_monday.ok()); + CHECK_FALSE(weekday_indexed_tuesday.ok()); + CHECK_FALSE(weekday_indexed_wednesday.ok()); + CHECK_FALSE(weekday_indexed_thursday.ok()); + CHECK_FALSE(weekday_indexed_friday.ok()); + CHECK_FALSE(weekday_indexed_saturday.ok()); + CHECK_FALSE(weekday_indexed_sunday.ok()); + } + } + + //************************************************************************* + TEST(test_weekday_indexed_comparison_operators) + { + etl::chrono::weekday_indexed weekday_indexed1(etl::chrono::Monday, 1); + etl::chrono::weekday_indexed weekday_indexed2(etl::chrono::Monday, 1); + etl::chrono::weekday_indexed weekday_indexed3(etl::chrono::Monday, 2); + etl::chrono::weekday_indexed weekday_indexed4(etl::chrono::Tuesday, 1); + + CHECK_TRUE(weekday_indexed1 == weekday_indexed2); + CHECK_FALSE(weekday_indexed1 == weekday_indexed3); + CHECK_FALSE(weekday_indexed1 == weekday_indexed4); + } + + //************************************************************************* + TEST(test_weekday_indexed_hashes_are_unique) + { + std::vector hashes; + + for (int i = 0; i < 6; ++i) + { + hashes.push_back(etl::hash()(etl::chrono::weekday_indexed(etl::chrono::Monday, i))); + hashes.push_back(etl::hash()(etl::chrono::weekday_indexed(etl::chrono::Tuesday, i))); + hashes.push_back(etl::hash()(etl::chrono::weekday_indexed(etl::chrono::Wednesday, i))); + hashes.push_back(etl::hash()(etl::chrono::weekday_indexed(etl::chrono::Thursday, i))); + hashes.push_back(etl::hash()(etl::chrono::weekday_indexed(etl::chrono::Friday, i))); + hashes.push_back(etl::hash()(etl::chrono::weekday_indexed(etl::chrono::Saturday, i))); + hashes.push_back(etl::hash()(etl::chrono::weekday_indexed(etl::chrono::Sunday, i))); + } + + std::sort(hashes.begin(), hashes.end()); + (void)std::unique(hashes.begin(), hashes.end()); + } + }; +} diff --git a/test/test_chrono_weekday_last.cpp b/test/test_chrono_weekday_last.cpp new file mode 100644 index 00000000..09c8f8d6 --- /dev/null +++ b/test/test_chrono_weekday_last.cpp @@ -0,0 +1,120 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2024 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include + +#include +#include + +namespace +{ + SUITE(test_chrono_weekday_last) + { + //************************************************************************* + TEST(test_constructor_in_range) + { + for (unsigned i = 1U; i < 5U; ++i) + { + etl::chrono::weekday_last weekday_last_monday(etl::chrono::Monday); + etl::chrono::weekday_last weekday_last_tuesday(etl::chrono::Tuesday); + etl::chrono::weekday_last weekday_last_wednesday(etl::chrono::Wednesday); + etl::chrono::weekday_last weekday_last_thursday(etl::chrono::Thursday); + etl::chrono::weekday_last weekday_last_friday(etl::chrono::Friday); + etl::chrono::weekday_last weekday_last_saturday(etl::chrono::Saturday); + etl::chrono::weekday_last weekday_last_sunday(etl::chrono::Sunday); + + CHECK_TRUE(weekday_last_monday.ok()); + CHECK_TRUE(weekday_last_tuesday.ok()); + CHECK_TRUE(weekday_last_wednesday.ok()); + CHECK_TRUE(weekday_last_thursday.ok()); + CHECK_TRUE(weekday_last_friday.ok()); + CHECK_TRUE(weekday_last_saturday.ok()); + CHECK_TRUE(weekday_last_sunday.ok()); + + CHECK_EQUAL(etl::chrono::Monday.c_encoding(), weekday_last_monday.weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::Tuesday.c_encoding(), weekday_last_tuesday.weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::Wednesday.c_encoding(), weekday_last_wednesday.weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::Thursday.c_encoding(), weekday_last_thursday.weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::Friday.c_encoding(), weekday_last_friday.weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::Saturday.c_encoding(), weekday_last_saturday.weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::Sunday.c_encoding(), weekday_last_sunday.weekday().c_encoding()); + } + } + + //************************************************************************* + TEST(test_constructor_out_of_range) + { + for (unsigned i = 8U; i < 256U; ++i) + { + auto wd = etl::chrono::weekday(i); + etl::chrono::weekday_last weekday_last(wd); + + CHECK_FALSE(weekday_last.ok()); + } + } + + //************************************************************************* + TEST(test_weekday_last_comparison_operators) + { + etl::chrono::weekday_last weekday_last1(etl::chrono::Monday); + etl::chrono::weekday_last weekday_last2(etl::chrono::Monday); + etl::chrono::weekday_last weekday_last3(etl::chrono::Tuesday); + + CHECK_TRUE(weekday_last1 == weekday_last2); + CHECK_FALSE(weekday_last1 == weekday_last3); + } + + //************************************************************************* + TEST(test_weekday_last_hashes_are_unique) + { + std::vector hashes; + + for (int i = 0; i < 6; ++i) + { + hashes.push_back(etl::hash()(etl::chrono::weekday_last(etl::chrono::Monday))); + hashes.push_back(etl::hash()(etl::chrono::weekday_last(etl::chrono::Tuesday))); + hashes.push_back(etl::hash()(etl::chrono::weekday_last(etl::chrono::Wednesday))); + hashes.push_back(etl::hash()(etl::chrono::weekday_last(etl::chrono::Thursday))); + hashes.push_back(etl::hash()(etl::chrono::weekday_last(etl::chrono::Friday))); + hashes.push_back(etl::hash()(etl::chrono::weekday_last(etl::chrono::Saturday))); + hashes.push_back(etl::hash()(etl::chrono::weekday_last(etl::chrono::Sunday))); + } + + std::sort(hashes.begin(), hashes.end()); + (void)std::unique(hashes.begin(), hashes.end()); + } + }; +} diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 20c4b6d4..01e8ce6e 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -7959,6 +7959,8 @@ + + From 4942ff840e27580b9a12ad5b4e65bf5c72e76fe6 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 12 Sep 2024 14:03:05 +0100 Subject: [PATCH 12/33] etl::duration work in progress --- include/etl/private/chrono/duration.h | 242 ++++++++++++++++++++++---- include/etl/ratio.h | 70 +++++++- test/test_chrono_duration.cpp | 209 ++++++++++++++++++++++ test/vs2022/etl.vcxproj | 1 + test/vs2022/etl.vcxproj.filters | 9 + 5 files changed, 486 insertions(+), 45 deletions(-) create mode 100644 test/test_chrono_duration.cpp diff --git a/include/etl/private/chrono/duration.h b/include/etl/private/chrono/duration.h index b499f0f4..2163b925 100644 --- a/include/etl/private/chrono/duration.h +++ b/include/etl/private/chrono/duration.h @@ -40,14 +40,65 @@ namespace etl { namespace chrono { + namespace private_chrono + { + // Helper to find the greatest common divisor + template + struct gcd + { + static ETL_CONSTANT intmax_t value = gcd::value; + }; + + template + struct gcd + { + static ETL_CONSTANT intmax_t value = A; + }; + + // Helper to find the least common multiple + template + struct lcm + { + static ETL_CONSTANT intmax_t value = (A / gcd::value) * B; + }; + } + + //*********************************************************************** + /// duration_values + //*********************************************************************** + template + struct duration_values + { + //*********************************************************************** + static ETL_CONSTEXPR TRep zero() + { + return TRep(0); + } + + //*********************************************************************** + static ETL_CONSTEXPR TRep min() + { + return etl::numeric_limits::min(); + } + + //*********************************************************************** + static ETL_CONSTEXPR TRep max() + { + return etl::numeric_limits::max(); + } + }; + //*********************************************************************** /// duration //*********************************************************************** - template > + template > class duration { public: + typedef TRep rep; + typedef TPeriod period; + //*********************************************************************** ETL_CONSTEXPR duration() ETL_NOEXCEPT : value(0) @@ -55,53 +106,53 @@ namespace etl } //*********************************************************************** - ETL_CONSTEXPR duration(const etl::chrono::duration& other) ETL_NOEXCEPT + ETL_CONSTEXPR duration(const etl::chrono::duration& other) ETL_NOEXCEPT : value(other.value) { } //*********************************************************************** - template< typename TValue2 > - ETL_CONSTEXPR explicit duration(const TValue2& value_) ETL_NOEXCEPT - : value(static_cast(value_)) + template + ETL_CONSTEXPR explicit duration(const TRep2& value_) ETL_NOEXCEPT + : value(static_cast(value_)) { } //*********************************************************************** - template< typename TValue2, typename TPeriod2 > - ETL_CONSTEXPR duration(const etl::chrono::duration& other) ETL_NOEXCEPT - : value(static_cast(other.value)) + template + ETL_CONSTEXPR duration(const etl::chrono::duration& other) ETL_NOEXCEPT + : value(static_cast(other.count())) { - ETL_STATIC_ASSERT(!(etl::is_integral::value && etl::is_floating_point::value), "Cannot convert duration from floating point to integral"); + ETL_STATIC_ASSERT(!(etl::is_integral::value && etl::is_floating_point::value), "Cannot convert duration from floating point to integral"); } //*********************************************************************** - static ETL_CONSTEXPR etl::chrono::duration< TValue, TPeriod> zero() ETL_NOEXCEPT - { - return etl::chrono::duration{ 0, TPeriod()}; - } - - //*********************************************************************** - static ETL_CONSTEXPR etl::chrono::duration min() ETL_NOEXCEPT - { - return etl::chrono::duration { etl::numeric_limits::min() }; - } - - //*********************************************************************** - static ETL_CONSTEXPR etl::chrono::duration max() ETL_NOEXCEPT - { - return etl::chrono::duration{ etl::numeric_limits::max() }; - } - - //*********************************************************************** - ETL_CONSTEXPR TValue count() const ETL_NOEXCEPT + ETL_CONSTEXPR TRep count() const ETL_NOEXCEPT { return value; } + //*********************************************************************** + static ETL_CONSTEXPR etl::chrono::duration zero() ETL_NOEXCEPT + { + return etl::chrono::duration(etl::chrono::duration_values::zero()); + } + + //*********************************************************************** + static ETL_CONSTEXPR etl::chrono::duration min() ETL_NOEXCEPT + { + return etl::chrono::duration(etl::chrono::duration_values::min()); + } + + //*********************************************************************** + static ETL_CONSTEXPR etl::chrono::duration max() ETL_NOEXCEPT + { + return etl::chrono::duration(etl::chrono::duration_values::max()); + } + private: - TValue value; + TRep value; }; //*********************************************************************** @@ -128,19 +179,134 @@ namespace etl //*********************************************************************** /// duration_cast //*********************************************************************** - template - ETL_CONSTEXPR TToDuration duration_cast(const etl::chrono::duration& d) ETL_NOEXCEPT + template + ETL_CONSTEXPR TToDuration duration_cast(const etl::chrono::duration& d) ETL_NOEXCEPT { - using to_value_type = typename TToDuration::value_type; - using to_period = typename TToDuration::period; + typedef TRep from_rep; + typedef TPeriod from_period; - // Calculate the conversion factor between the periods - ETL_CONSTEXPR auto conversion_factor = (static_cast(TPeriod::num) / TPeriod::den) * (to_period::den / to_period::num); + typedef typename TToDuration::rep to_rep; + typedef typename TToDuration::period to_period; - // Convert the value - to_value_type converted_value = static_cast(d.count() * conversion_factor); + typedef typename etl::ratio_divide::type ratio_divide_t; + typedef typename etl::common_type::type common_t; - return TToDuration(converted_value); + common_t ct_count = static_cast(d.count()); + common_t ct_num = static_cast(ratio_divide_t::type::num); + common_t ct_den = static_cast(ratio_divide_t::type::den); + + if ETL_IF_CONSTEXPR((from_period::num == to_period::num) && (from_period::den == to_period::den)) + { + return TToDuration(static_cast(d.count())); + } + else if ETL_IF_CONSTEXPR(ratio_divide_t::num == 1) + { + return TToDuration(static_cast(ct_count / ct_den)); + } + else if ETL_IF_CONSTEXPR(ratio_divide_t::den == 1) + { + return TToDuration(static_cast(ct_count * ct_num)); + } + else + { + return TToDuration(static_cast((ct_count * ct_num) / ct_den)); + } + } + } + + //************************************************************************* + /// Hash function for etl::chrono::duration + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template + struct hash > + { + size_t operator()(const etl::chrono::duration& d) const + { + TRep value = d.count(); + size_t num = TPeriod::num; + size_t den = TPeriod::den; + + return 0; //etl::private_hash::generic_hash(p, p + sizeof(unsigned)); + } + }; +#endif + + //*********************************************************************** + /// Find the common type of two duration types. + //*********************************************************************** + template + struct common_type, etl::chrono::duration > + { + private: + + typedef typename etl::common_type::type value_type; + typedef etl::ratio::value, + etl::chrono::private_chrono::lcm::value> period_type; + + public: + + using type = etl::chrono::duration; + }; +} + +#if ETL_HAS_CHRONO_LITERALS_DAY +#if ETL_USING_CPP11 +namespace etl +{ + namespace literals + { + namespace chrono_literals + { + //*********************************************************************** + /// Literal for hours duration + //*********************************************************************** + ETL_IF_CONSTEXPR etl::chrono::hours operator ""_hours(unsigned long long h) noexcept + { + return etl::chrono::hours(static_cast(h)); + } + + //*********************************************************************** + /// Literal for minutes duration + //*********************************************************************** + ETL_IF_CONSTEXPR etl::chrono::hours operator ""_minutes(unsigned long long m) noexcept + { + return etl::chrono::minutes(static_cast(m)); + } + + //*********************************************************************** + /// Literal for seconds duration + //*********************************************************************** + ETL_IF_CONSTEXPR etl::chrono::seconds operator ""_seconds(unsigned long long s) noexcept + { + return etl::chrono::seconds(static_cast(s)); + } + + //*********************************************************************** + /// Literal for milliseconds duration + //*********************************************************************** + ETL_IF_CONSTEXPR etl::chrono::milliseconds operator ""_milliseconds(unsigned long long s) noexcept + { + return etl::chrono::milliseconds(static_cast(s)); + } + + //*********************************************************************** + /// Literal for microseconds duration + //*********************************************************************** + ETL_IF_CONSTEXPR etl::chrono::microseconds operator ""_microseconds(unsigned long long s) noexcept + { + return etl::chrono::microseconds(static_cast(s)); + } + + //*********************************************************************** + /// Literal for nanoseconds duration + //*********************************************************************** + ETL_IF_CONSTEXPR etl::chrono::nanoseconds operator ""_nanoseconds(unsigned long long s) noexcept + { + return etl::chrono::nanoseconds(static_cast(s)); + } } } } +#endif +#endif diff --git a/include/etl/ratio.h b/include/etl/ratio.h index 8c7fa81d..b5034c3f 100644 --- a/include/etl/ratio.h +++ b/include/etl/ratio.h @@ -41,19 +41,72 @@ SOFTWARE. namespace etl { - template + namespace private_ratio + { + // Helper to find the greatest common divisor + template + struct gcd + { + static ETL_CONSTANT intmax_t value = gcd::value; + }; + + template + struct gcd + { + static ETL_CONSTANT intmax_t value = A; + }; + + // Helper to find the least common multiple + template + struct lcm + { + static ETL_CONSTANT intmax_t value = (A / gcd::value) * B; + }; + } + + //*********************************************************************** + /// ratio + //*********************************************************************** + template struct ratio { - static ETL_CONSTANT intmax_t num = NUM; - static ETL_CONSTANT intmax_t den = DEN; + ETL_STATIC_ASSERT(Num != 0, "Numerator cannot be zero"); + + static ETL_CONSTANT intmax_t num = Num / private_ratio::gcd::value; + static ETL_CONSTANT intmax_t den = Den / private_ratio::gcd::value; + + typedef etl::ratio type; }; - template - ETL_CONSTANT intmax_t ratio::num; + template + ETL_CONSTANT intmax_t ratio::num; - template - ETL_CONSTANT intmax_t ratio::den; + template + ETL_CONSTANT intmax_t ratio::den; + //*********************************************************************** + /// ratio_divide + //*********************************************************************** + template + struct ratio_divide + { + private: + + static ETL_CONSTANT intmax_t N = TRatio1::num * TRatio2::den; + static ETL_CONSTANT intmax_t D = TRatio1::den * TRatio2::num; + + static ETL_CONSTANT intmax_t Num = N / private_ratio::gcd::value; + static ETL_CONSTANT intmax_t Den = D / private_ratio::gcd::value; + + public: + + typedef etl::ratio type; + }; + + + //*********************************************************************** + /// Predefined ration types. + //*********************************************************************** #if INT_MAX > INT32_MAX typedef ratio<1, 1000000000000000000000000> yocto; typedef ratio<1, 1000000000000000000000> zepto; @@ -95,6 +148,9 @@ namespace etl /// An approximation of root 2. typedef ratio<239, 169> ratio_root2; + /// An approximation of 1 over root 2. + typedef ratio<169, 239> ratio_1_over_root2; + /// An approximation of e. typedef ratio<326, 120> ratio_e; } diff --git a/test/test_chrono_duration.cpp b/test/test_chrono_duration.cpp new file mode 100644 index 00000000..e8eddac8 --- /dev/null +++ b/test/test_chrono_duration.cpp @@ -0,0 +1,209 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2024 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include +#include +#include +#include + +namespace +{ + SUITE(test_chrono_duration) + { + //************************************************************************* + TEST(test_default_constructor) + { + using duration_type = etl::chrono::duration; + + duration_type duration; + + CHECK_TRUE((etl::is_same::value)); + CHECK_TRUE((etl::is_same::value)); + CHECK_EQUAL(0, duration.count()); + } + + //************************************************************************* + TEST(test_duration_values_zero_min_max) + { + using duration_values_type = etl::chrono::duration_values; + + CHECK_EQUAL(size_t(0), duration_values_type::zero()); + CHECK_EQUAL(std::numeric_limits::min(), duration_values_type::min()); + CHECK_EQUAL(std::numeric_limits::max(), duration_values_type::max()); + } + + //************************************************************************* + TEST(test_duration_zero_min_max) + { + using duration_type = etl::chrono::duration; + + //CHECK_EQUAL(duration_type(0), duration_type::zero()); + //CHECK_EQUAL(duration_type(std::numeric_limits::min()), duration_type::min()); + //CHECK_EQUAL(duration_type(std::numeric_limits::max()), duration_type::max()); + } + + //************************************************************************* + TEST(test_predefined_duration_types) + { + CHECK_EQUAL((etl::ratio<1U, 1000000000U>::type::num), etl::chrono::nanoseconds::period::num); + CHECK_EQUAL((etl::ratio<1U, 1000000000U>::type::den), etl::chrono::nanoseconds::period::den); + + CHECK_EQUAL((etl::ratio<1U, 1000000U>::type::num), etl::chrono::microseconds::period::num); + CHECK_EQUAL((etl::ratio<1U, 1000000U>::type::den), etl::chrono::microseconds::period::den); + + CHECK_EQUAL((etl::ratio<1U, 1000U>::type::num), etl::chrono::milliseconds::period::num); + CHECK_EQUAL((etl::ratio<1U, 1000U>::type::den), etl::chrono::milliseconds::period::den); + + CHECK_EQUAL(etl::ratio<1U>::type::num, etl::chrono::seconds::period::num); + CHECK_EQUAL(etl::ratio<1U>::type::den, etl::chrono::seconds::period::den); + + CHECK_EQUAL(etl::ratio<60U>::type::num, etl::chrono::minutes::period::num); + CHECK_EQUAL(etl::ratio<60U>::type::den, etl::chrono::minutes::period::den); + + CHECK_EQUAL(etl::ratio<3600U>::type::num, etl::chrono::hours::period::num); + CHECK_EQUAL(etl::ratio<3600U>::type::den, etl::chrono::hours::period::den); + + CHECK_EQUAL(etl::ratio<86400U>::type::num, etl::chrono::days::period::num); + CHECK_EQUAL(etl::ratio<86400U>::type::den, etl::chrono::days::period::den); + + CHECK_EQUAL(etl::ratio<604800U>::type::num, etl::chrono::weeks::period::num); + CHECK_EQUAL(etl::ratio<604800U>::type::den, etl::chrono::weeks::period::den); + + CHECK_EQUAL(etl::ratio<604800U>::type::num, etl::chrono::weeks::period::num); + CHECK_EQUAL(etl::ratio<604800U>::type::den, etl::chrono::weeks::period::den); + + CHECK_EQUAL(etl::ratio<2629746U>::type::num, etl::chrono::months::period::num); + CHECK_EQUAL(etl::ratio<2629746U>::type::den, etl::chrono::months::period::den); + + CHECK_EQUAL(etl::ratio<31556952U>::type::num, etl::chrono::years::period::num); + CHECK_EQUAL(etl::ratio<31556952U>::type::den, etl::chrono::years::period::den); + } + + //************************************************************************* + TEST(test_duration_common_type) + { + using duration_type1 = etl::chrono::duration; + using duration_type2 = etl::chrono::duration; + + using duration_type = etl::common_type::type; + + CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); + } + + //************************************************************************* + TEST(test_duration_cast_with_same_rep_and_period_for_duration_type1_and_duration_type2) + { + using duration_type1 = etl::chrono::duration; + using duration_type2 = etl::chrono::duration>; + + duration_type1 dur1(245); + duration_type2 dur2 = etl::chrono::duration_cast(dur1); + + CHECK_EQUAL(duration_type1::period::num, duration_type2::period::num); + CHECK_EQUAL(duration_type1::period::den, duration_type2::period::den); + CHECK_EQUAL(dur1.count(), dur2.count()); + } + + //************************************************************************* + TEST(test_duration_cast_where_ratio_divide_of_periods_num_is_1) + { + using duration_type1 = etl::chrono::duration; + using duration_type2 = etl::chrono::duration; + + duration_type1 dur1(245000); + duration_type2 dur2 = etl::chrono::duration_cast(dur1); + + typedef typename etl::ratio_divide::type ratio_divide_t; + + int multiplier = duration_type1::period::den / duration_type2::period::den; + + CHECK_EQUAL(1, ratio_divide_t::num); + CHECK_EQUAL(dur1.count(), dur2.count() * multiplier); + } + + //************************************************************************* + TEST(test_duration_cast_where_ratio_divide_of_periods_den_is_1) + { + using duration_type1 = etl::chrono::duration; + using duration_type2 = etl::chrono::duration; + + duration_type1 dur1(245); + duration_type2 dur2 = etl::chrono::duration_cast(dur1); + + typedef typename etl::ratio_divide::type ratio_divide_t; + + int multiplier = duration_type2::period::den / duration_type1::period::den; + + CHECK_EQUAL(1, ratio_divide_t::den); + CHECK_EQUAL(dur1.count() * multiplier, dur2.count()); + } + + //************************************************************************* + TEST(test_duration_cast_when_rep_and_period_are_not_equal_and_ratio_divide_of_periods_num_and_den_are_not_1) + { + using duration_type1 = etl::chrono::duration>; + using duration_type2 = etl::chrono::duration>; + + duration_type1 dur1(245); + duration_type2 dur2 = etl::chrono::duration_cast(dur1); + + typedef typename etl::ratio_divide::type ratio_divide_t; + + CHECK_FALSE((duration_type1::period::num == duration_type2::period::num) && (duration_type1::period::den == duration_type2::period::den)); + CHECK_FALSE(1 == ratio_divide_t::num); + CHECK_FALSE(1 == ratio_divide_t::den); + CHECK_EQUAL(dur1.count(), (dur2.count() * duration_type2::period::num) / duration_type1::period::num); + } + + //************************************************************************* + TEST(test_duration_hashes_are_unique) + { + using duration_type = etl::chrono::duration; + + std::vector hashes; + + for (int i = 0; i < 256; ++i) + { + hashes.push_back(etl::hash()(duration_type(i))); + } + + std::sort(hashes.begin(), hashes.end()); + (void)std::unique(hashes.begin(), hashes.end()); + CHECK_EQUAL(256U, hashes.size()); + } + }; +} diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 01e8ce6e..1d21befc 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -7957,6 +7957,7 @@ + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 6ab086e7..d0b88961 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -3434,6 +3434,15 @@ Tests\Syntax Checks\Source + + Tests\Chrono + + + Tests\Chrono + + + Tests\Chrono + From 0d0b9be310725beb13b5a6001e6e6ee2d619082b Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 13 Sep 2024 19:55:18 +0100 Subject: [PATCH 13/33] etl::duration work in progress --- include/etl/private/chrono/duration.h | 115 ++++++++++++++++++++++++-- test/test_chrono_duration.cpp | 105 +++++++++++++++++++++-- 2 files changed, 204 insertions(+), 16 deletions(-) diff --git a/include/etl/private/chrono/duration.h b/include/etl/private/chrono/duration.h index 2163b925..9cc58ea9 100644 --- a/include/etl/private/chrono/duration.h +++ b/include/etl/private/chrono/duration.h @@ -35,6 +35,7 @@ SOFTWARE. #include "../../ratio.h" #include "../../static_assert.h" #include "../../limits.h" +#include "../../type_traits.h" namespace etl { @@ -88,6 +89,12 @@ namespace etl } }; + template + class duration; + + template + ETL_CONSTEXPR14 TToDuration duration_cast(const etl::chrono::duration& d) ETL_NOEXCEPT; + //*********************************************************************** /// duration //*********************************************************************** @@ -96,8 +103,8 @@ namespace etl { public: - typedef TRep rep; - typedef TPeriod period; + typedef TRep rep; + typedef typename TPeriod::type period; //*********************************************************************** ETL_CONSTEXPR duration() ETL_NOEXCEPT @@ -119,19 +126,47 @@ namespace etl } //*********************************************************************** - template + template ::type::den == 1, int>::type = 0> ETL_CONSTEXPR duration(const etl::chrono::duration& other) ETL_NOEXCEPT - : value(static_cast(other.count())) + : value(etl::chrono::duration_cast >(other).count()) { + + bool b = etl::ratio_divide::type::den == 1; + ETL_STATIC_ASSERT(!(etl::is_integral::value && etl::is_floating_point::value), "Cannot convert duration from floating point to integral"); } + //*********************************************************************** + template + ETL_CONSTEXPR14 + typename etl::enable_if::type::den == 1, etl::chrono::duration&>::type + operator =(const etl::chrono::duration& other) ETL_NOEXCEPT + { + bool b = etl::ratio_divide::type::den == 1; + + value = etl::chrono::duration_cast >(other).count(); + + return *this; + } + //*********************************************************************** ETL_CONSTEXPR TRep count() const ETL_NOEXCEPT { return value; } + //*********************************************************************** + ETL_CONSTEXPR etl::common_type_t operator +() const + { + return etl::common_type_t(*this); + } + + //*********************************************************************** + ETL_CONSTEXPR etl::common_type_t operator -() const + { + return etl::common_type_t(-value); + } + //*********************************************************************** static ETL_CONSTEXPR etl::chrono::duration zero() ETL_NOEXCEPT { @@ -152,7 +187,7 @@ namespace etl private: - TRep value; + TRep value; }; //*********************************************************************** @@ -180,7 +215,7 @@ namespace etl /// duration_cast //*********************************************************************** template - ETL_CONSTEXPR TToDuration duration_cast(const etl::chrono::duration& d) ETL_NOEXCEPT + ETL_CONSTEXPR14 TToDuration duration_cast(const etl::chrono::duration& d) ETL_NOEXCEPT { typedef TRep from_rep; typedef TPeriod from_period; @@ -221,7 +256,7 @@ namespace etl template struct hash > { - size_t operator()(const etl::chrono::duration& d) const + ETL_CONSTEXPR14 size_t operator()(const etl::chrono::duration& d) const { TRep value = d.count(); size_t num = TPeriod::num; @@ -248,6 +283,70 @@ namespace etl using type = etl::chrono::duration; }; + + //*********************************************************************** + /// Check equality. + //*********************************************************************** + template + ETL_CONSTEXPR14 bool operator ==(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + { + typedef typename etl::common_type, etl::chrono::duration >::type common_t; + + common_t l = etl::chrono::duration_cast(lhs); + common_t r = etl::chrono::duration_cast(rhs); + + return l.count() == r.count(); + } + + //*********************************************************************** + /// Check inequality. + //*********************************************************************** + template + ETL_CONSTEXPR14 bool operator !=(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + { + return !(lhs == rhs); + } + + //*********************************************************************** + /// Less-than. + //*********************************************************************** + template + ETL_CONSTEXPR14 bool operator <(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + { + typedef typename etl::common_type, etl::chrono::duration >::type common_t; + + common_t l = etl::chrono::duration_cast(lhs); + common_t r = etl::chrono::duration_cast(rhs); + + return l.count() < r.count(); + } + + //*********************************************************************** + /// Less-than-or-equal. + //*********************************************************************** + template + ETL_CONSTEXPR14 bool operator <=(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + { + return !(rhs < lhs); + } + + //*********************************************************************** + /// Greater-than. + //*********************************************************************** + template + ETL_CONSTEXPR14 bool operator >(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + { + return rhs < lhs; + } + + //*********************************************************************** + /// Greater-than-or-equal. + //*********************************************************************** + template + ETL_CONSTEXPR14 bool operator >=(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + { + return !(lhs < rhs); + } } #if ETL_HAS_CHRONO_LITERALS_DAY @@ -269,7 +368,7 @@ namespace etl //*********************************************************************** /// Literal for minutes duration //*********************************************************************** - ETL_IF_CONSTEXPR etl::chrono::hours operator ""_minutes(unsigned long long m) noexcept + ETL_IF_CONSTEXPR etl::chrono::minutes operator ""_minutes(unsigned long long m) noexcept { return etl::chrono::minutes(static_cast(m)); } diff --git a/test/test_chrono_duration.cpp b/test/test_chrono_duration.cpp index e8eddac8..f20ed3fc 100644 --- a/test/test_chrono_duration.cpp +++ b/test/test_chrono_duration.cpp @@ -38,6 +38,7 @@ SOFTWARE. #include #include #include +#include namespace { @@ -70,13 +71,13 @@ namespace { using duration_type = etl::chrono::duration; - //CHECK_EQUAL(duration_type(0), duration_type::zero()); - //CHECK_EQUAL(duration_type(std::numeric_limits::min()), duration_type::min()); - //CHECK_EQUAL(duration_type(std::numeric_limits::max()), duration_type::max()); + CHECK_EQUAL(duration_type(0).count(), duration_type::zero().count()); + CHECK_EQUAL(duration_type(std::numeric_limits::min()).count(), duration_type::min().count()); + CHECK_EQUAL(duration_type(std::numeric_limits::max()).count(), duration_type::max().count()); } //************************************************************************* - TEST(test_predefined_duration_types) + TEST(test_predefined_duration_periods) { CHECK_EQUAL((etl::ratio<1U, 1000000000U>::type::num), etl::chrono::nanoseconds::period::num); CHECK_EQUAL((etl::ratio<1U, 1000000000U>::type::den), etl::chrono::nanoseconds::period::den); @@ -149,10 +150,10 @@ namespace typedef typename etl::ratio_divide::type ratio_divide_t; - int multiplier = duration_type1::period::den / duration_type2::period::den; + int microseonds_per_millisecond = duration_type1::period::den / duration_type2::period::den; CHECK_EQUAL(1, ratio_divide_t::num); - CHECK_EQUAL(dur1.count(), dur2.count() * multiplier); + CHECK_EQUAL(dur1.count(), dur2.count() * microseonds_per_millisecond); } //************************************************************************* @@ -166,10 +167,10 @@ namespace typedef typename etl::ratio_divide::type ratio_divide_t; - int multiplier = duration_type2::period::den / duration_type1::period::den; + int microseonds_per_millisecond = duration_type2::period::den / duration_type1::period::den; CHECK_EQUAL(1, ratio_divide_t::den); - CHECK_EQUAL(dur1.count() * multiplier, dur2.count()); + CHECK_EQUAL(dur1.count() * microseonds_per_millisecond, dur2.count()); } //************************************************************************* @@ -189,6 +190,94 @@ namespace CHECK_EQUAL(dur1.count(), (dur2.count() * duration_type2::period::num) / duration_type1::period::num); } + //************************************************************************* + TEST(test_duration_assignment) + { + int Two_Hours = 2; + int Four_Hours = 4; + + etl::chrono::hours hours1(Two_Hours); + etl::chrono::hours hours2(Four_Hours); + etl::chrono::seconds seconds(0); + + seconds = hours1; + int seconds_per_hour = etl::chrono::hours::period::num / etl::chrono::seconds::period::num; + CHECK_EQUAL(seconds.count(), hours1.count() * seconds_per_hour); + CHECK_EQUAL(Two_Hours, hours1.count()); + + hours1 = hours2; + CHECK_EQUAL(Four_Hours, hours1.count()); + CHECK_EQUAL(Four_Hours, hours2.count()); + } + + //************************************************************************* + TEST(test_duration_comparison_operators) + { + using duration_type1 = etl::chrono::duration; + using duration_type2 = etl::chrono::duration; + + duration_type1 dur1a(245); + duration_type1 dur1b(245); + duration_type1 dur1c(246); + duration_type2 dur2b(245000); + duration_type2 dur2c(245001); + + // Same duration types + CHECK_TRUE(dur1a == dur1b); + CHECK_TRUE(dur1a != dur1c); + CHECK_FALSE(dur1a < dur1b); + CHECK_TRUE(dur1a <= dur1b); + CHECK_FALSE(dur1a > dur1b); + CHECK_TRUE(dur1a >= dur1b); + + CHECK_TRUE(dur1a < dur1c); + CHECK_FALSE(dur1c < dur1a); + CHECK_TRUE(dur1a <= dur1c); + CHECK_FALSE(dur1c <= dur1a); + CHECK_FALSE(dur1a > dur1c); + CHECK_TRUE(dur1c > dur1a); + CHECK_FALSE(dur1a >= dur1c); + CHECK_TRUE(dur1c >= dur1a); + + // Different duration types + CHECK_TRUE(dur1a == dur2b); + CHECK_TRUE(dur2b == dur1a); + CHECK_TRUE(dur2c != dur1a); + CHECK_TRUE(dur1a != dur2c); + + CHECK_FALSE(dur1a < dur2b); + CHECK_FALSE(dur2b < dur1a); + CHECK_TRUE(dur1a <= dur2b); + CHECK_TRUE(dur2b <= dur1a); + CHECK_FALSE(dur1a > dur2b); + CHECK_FALSE(dur2b > dur1a); + CHECK_TRUE(dur1a >= dur2b); + CHECK_TRUE(dur2b >= dur1a); + + CHECK_TRUE(dur1a < dur2c); + CHECK_FALSE(dur2c < dur1a); + CHECK_TRUE(dur1a <= dur2c); + CHECK_FALSE(dur2c <= dur1a); + CHECK_FALSE(dur1a > dur2c); + CHECK_TRUE(dur2c > dur1a); + CHECK_FALSE(dur1a >= dur2c); + CHECK_TRUE(dur2c >= dur1a); + } + + //************************************************************************* + TEST(test_duration_unary_operators) + { + using duration_type = etl::chrono::duration; + + duration_type dur(245); + + duration_type positive = +dur; + duration_type negative = -dur; + + CHECK_EQUAL(245, positive.count()); + CHECK_EQUAL(-245, negative.count()); + } + //************************************************************************* TEST(test_duration_hashes_are_unique) { From 4741c71e340888c4dff8488f546fca8ddc554cd4 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 14 Sep 2024 20:02:25 +0100 Subject: [PATCH 14/33] etl::ratio work-in-progress --- include/etl/ratio.h | 62 +++++++++++++++++++-- test/test_ratio.cpp | 133 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 191 insertions(+), 4 deletions(-) create mode 100644 test/test_ratio.cpp diff --git a/include/etl/ratio.h b/include/etl/ratio.h index b5034c3f..77a89093 100644 --- a/include/etl/ratio.h +++ b/include/etl/ratio.h @@ -32,6 +32,7 @@ SOFTWARE. #define ETL_RATIO_INCLUDED #include "platform.h" +#include "static_assert.h" #include #include @@ -71,6 +72,7 @@ namespace etl struct ratio { ETL_STATIC_ASSERT(Num != 0, "Numerator cannot be zero"); + ETL_STATIC_ASSERT(Den != 0, "Denominator cannot be zero"); static ETL_CONSTANT intmax_t num = Num / private_ratio::gcd::value; static ETL_CONSTANT intmax_t den = Den / private_ratio::gcd::value; @@ -103,13 +105,67 @@ namespace etl typedef etl::ratio type; }; + //*********************************************************************** + /// ratio_multiply + //*********************************************************************** + template + struct ratio_multiply + { + private: + + static ETL_CONSTANT intmax_t N = TRatio1::num * TRatio2::num; + static ETL_CONSTANT intmax_t D = TRatio1::den * TRatio2::den; + + static ETL_CONSTANT intmax_t Num = N / private_ratio::gcd::value; + static ETL_CONSTANT intmax_t Den = D / private_ratio::gcd::value; + + public: + + typedef etl::ratio type; + }; + + //*********************************************************************** + /// ratio_add + //*********************************************************************** + template + struct ratio_add + { + private: + + static ETL_CONSTANT intmax_t N = (TRatio1::num * TRatio2::den) + (TRatio2::num * TRatio1::den); + static ETL_CONSTANT intmax_t D = TRatio1::den * TRatio2::den;; + + static ETL_CONSTANT intmax_t Num = N / private_ratio::gcd::value; + static ETL_CONSTANT intmax_t Den = D / private_ratio::gcd::value; + + public: + + typedef etl::ratio type; + }; + + //*********************************************************************** + /// ratio_subtract + //*********************************************************************** + template + struct ratio_subtract + { + private: + + static ETL_CONSTANT intmax_t N = (TRatio1::num * TRatio2::den) - (TRatio2::num * TRatio1::den); + static ETL_CONSTANT intmax_t D = TRatio1::den * TRatio2::den;; + + static ETL_CONSTANT intmax_t Num = N / private_ratio::gcd::value; + static ETL_CONSTANT intmax_t Den = D / private_ratio::gcd::value; + + public: + + typedef etl::ratio type; + }; //*********************************************************************** /// Predefined ration types. //*********************************************************************** #if INT_MAX > INT32_MAX - typedef ratio<1, 1000000000000000000000000> yocto; - typedef ratio<1, 1000000000000000000000> zepto; typedef ratio<1, 1000000000000000000> atto; typedef ratio<1, 1000000000000000> femto; typedef ratio<1, 1000000000000> pico; @@ -138,8 +194,6 @@ namespace etl typedef ratio<1000000000000, 1> tera; typedef ratio<1000000000000000, 1> peta; typedef ratio<1000000000000000000, 1> exa; - typedef ratio<1000000000000000000000, 1> zetta; - typedef ratio<1000000000000000000000000, 1> yotta; #endif /// An approximation of PI to 6 digits. diff --git a/test/test_ratio.cpp b/test/test_ratio.cpp new file mode 100644 index 00000000..7f061d49 --- /dev/null +++ b/test/test_ratio.cpp @@ -0,0 +1,133 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2024 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/ratio.h" + +namespace +{ + // Helper to find the greatest common divisor + template + struct gcd + { + static ETL_CONSTANT intmax_t value = gcd::value; + }; + + template + struct gcd + { + static ETL_CONSTANT intmax_t value = A; + }; + + // Helper to find the least common multiple + template + struct lcm + { + static ETL_CONSTANT intmax_t value = (A / gcd::value) * B; + }; + + SUITE(test_ratio) + { + //************************************************************************* + TEST(test_constructor) + { + constexpr intmax_t Num = 20; + constexpr intmax_t Den = 600; + + intmax_t N = Num / gcd::value; + intmax_t D = Den / gcd::value; + + using ratio = etl::ratio; + using ratio_type = ratio::type; + + CHECK_FALSE((std::is_same::value)); + + CHECK_EQUAL(N, ratio::num); + CHECK_EQUAL(D, ratio::den); + + CHECK_EQUAL(N, ratio_type::num); + CHECK_EQUAL(D, ratio_type::den); + } + + //************************************************************************* + TEST(test_predefined_ratios) + { +#if INT_MAX > INT32_MAX + CHECK_EQUAL(etl::atto::num, 1); + CHECK_EQUAL(etl::atto::den, 1000000000000000000); + CHECK_EQUAL(etl::femto::num, 1); + CHECK_EQUAL(etl::femto::den, 1000000000000000); + CHECK_EQUAL(etl::pico::num, 1); + CHECK_EQUAL(etl::pico::den, 1000000000000); +#endif +#if (INT_MAX >= INT32_MAX) + CHECK_EQUAL(etl::nano::num, 1); + CHECK_EQUAL(etl::nano::den, 1000000000); + CHECK_EQUAL(etl::micro::num, 1); + CHECK_EQUAL(etl::micro::den, 1000000); +#endif +#if (INT_MAX >= INT16_MAX) + CHECK_EQUAL(etl::milli::num, 1); + CHECK_EQUAL(etl::milli::den, 1000); + CHECK_EQUAL(etl::centi::num, 1); + CHECK_EQUAL(etl::centi::den, 100); + CHECK_EQUAL(etl::deci::num, 1); + CHECK_EQUAL(etl::deci::den, 10); + CHECK_EQUAL(etl::deca::num, 10); + CHECK_EQUAL(etl::deca::den, 1); + CHECK_EQUAL(etl::hecto::num, 100); + CHECK_EQUAL(etl::hecto::den, 1); + CHECK_EQUAL(etl::kilo::num, 1000); + CHECK_EQUAL(etl::kilo::den, 1); +#endif +#if (INT_MAX >= INT32_MAX) + CHECK_EQUAL(etl::mega::num, 1000000); + CHECK_EQUAL(etl::mega::den, 1); + CHECK_EQUAL(etl::giga::num, 1000000000); + CHECK_EQUAL(etl::giga::den, 1); +#endif + +#if INT_MAX > INT32_MAX + CHECK_EQUAL(etl::tera::num, 1000000000000); + CHECK_EQUAL(etl::tera::den, 1); + CHECK_EQUAL(etl::peta::num, 1000000000000000); + CHECK_EQUAL(etl::peta::den, 1); + CHECK_EQUAL(etl::exa::num, 1000000000000000000); + CHECK_EQUAL(etl::exa::den, 1); +#endif + + double expected_pi = 3.1415926535897931; + double actual_pi = double(etl::ratio_pi::num) / double(etl::ratio_pi::den); + + CHECK_CLOSE(expected_pi, actual_pi, 0.0000003); + } + }; +} From bec9f4a2dffd1a89778b3bd0d0f41061ab2b3c5c Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 15 Sep 2024 14:12:40 +0100 Subject: [PATCH 15/33] Added etl::ratio tests --- include/etl/chrono.h | 9 +- include/etl/gcd.h | 16 +++ include/etl/lcm.h | 10 ++ include/etl/private/chrono/duration.h | 10 +- include/etl/ratio.h | 150 +++++++++++--------------- test/test_ratio.cpp | 136 +++++++++++++++++++++-- test/vs2022/etl.vcxproj | 1 + test/vs2022/etl.vcxproj.filters | 3 + 8 files changed, 232 insertions(+), 103 deletions(-) diff --git a/include/etl/chrono.h b/include/etl/chrono.h index 8972d49e..51fd1fd8 100644 --- a/include/etl/chrono.h +++ b/include/etl/chrono.h @@ -34,6 +34,10 @@ SOFTWARE. #define ETL_IN_CHRONO_H #include "platform.h" + +#if ETL_NOT_USING_CPP11 + #error NOT SUPPORTED FOR C++03 OR BELOW +#else #include "hash.h" #include @@ -45,8 +49,9 @@ SOFTWARE. #include "private/chrono/weekday_indexed.h" #include "private/chrono/weekday_last.h" #include "private/chrono/month.h" -#include "private/chrono/year.h" - +#include "private/chrono/year.h" +#endif + #undef ETL_IN_CHRONO_H #endif diff --git a/include/etl/gcd.h b/include/etl/gcd.h index aea495e5..77df935c 100644 --- a/include/etl/gcd.h +++ b/include/etl/gcd.h @@ -37,6 +37,22 @@ SOFTWARE. namespace etl { + //*************************************************************************** + // Greatest Common Divisor. + // Compile time. + //*************************************************************************** + template + struct gcd_const + { + static ETL_CONSTANT intmax_t value = gcd_const::value; + }; + + template + struct gcd_const + { + static ETL_CONSTANT intmax_t value = A; + }; + //*************************************************************************** // Greatest Common Divisor. // For unsigned types. diff --git a/include/etl/lcm.h b/include/etl/lcm.h index 43bb0021..575ff576 100644 --- a/include/etl/lcm.h +++ b/include/etl/lcm.h @@ -38,6 +38,16 @@ SOFTWARE. namespace etl { + //*************************************************************************** + // Least Common Multiple. + // Compile time. + //*************************************************************************** + template + struct lcm_const + { + static ETL_CONSTANT intmax_t value = (A / gcd_const::value) * B; + }; + //*************************************************************************** // Least Common Multiple. // For unsigned types. diff --git a/include/etl/private/chrono/duration.h b/include/etl/private/chrono/duration.h index 9cc58ea9..6d4a5334 100644 --- a/include/etl/private/chrono/duration.h +++ b/include/etl/private/chrono/duration.h @@ -126,12 +126,12 @@ namespace etl } //*********************************************************************** - template ::type::den == 1, int>::type = 0> + template ::den == 1, int>::type = 0> ETL_CONSTEXPR duration(const etl::chrono::duration& other) ETL_NOEXCEPT : value(etl::chrono::duration_cast >(other).count()) { - bool b = etl::ratio_divide::type::den == 1; + bool b = etl::ratio_divide::den == 1; ETL_STATIC_ASSERT(!(etl::is_integral::value && etl::is_floating_point::value), "Cannot convert duration from floating point to integral"); } @@ -139,10 +139,10 @@ namespace etl //*********************************************************************** template ETL_CONSTEXPR14 - typename etl::enable_if::type::den == 1, etl::chrono::duration&>::type + typename etl::enable_if::den == 1, etl::chrono::duration&>::type operator =(const etl::chrono::duration& other) ETL_NOEXCEPT { - bool b = etl::ratio_divide::type::den == 1; + bool b = etl::ratio_divide::den == 1; value = etl::chrono::duration_cast >(other).count(); @@ -223,7 +223,7 @@ namespace etl typedef typename TToDuration::rep to_rep; typedef typename TToDuration::period to_period; - typedef typename etl::ratio_divide::type ratio_divide_t; + typedef typename etl::ratio_divide ratio_divide_t; typedef typename etl::common_type::type common_t; common_t ct_count = static_cast(d.count()); diff --git a/include/etl/ratio.h b/include/etl/ratio.h index 77a89093..f2bc38e9 100644 --- a/include/etl/ratio.h +++ b/include/etl/ratio.h @@ -33,6 +33,7 @@ SOFTWARE. #include "platform.h" #include "static_assert.h" +#include "gcd.h" #include #include @@ -42,29 +43,6 @@ SOFTWARE. namespace etl { - namespace private_ratio - { - // Helper to find the greatest common divisor - template - struct gcd - { - static ETL_CONSTANT intmax_t value = gcd::value; - }; - - template - struct gcd - { - static ETL_CONSTANT intmax_t value = A; - }; - - // Helper to find the least common multiple - template - struct lcm - { - static ETL_CONSTANT intmax_t value = (A / gcd::value) * B; - }; - } - //*********************************************************************** /// ratio //*********************************************************************** @@ -74,8 +52,8 @@ namespace etl ETL_STATIC_ASSERT(Num != 0, "Numerator cannot be zero"); ETL_STATIC_ASSERT(Den != 0, "Denominator cannot be zero"); - static ETL_CONSTANT intmax_t num = Num / private_ratio::gcd::value; - static ETL_CONSTANT intmax_t den = Den / private_ratio::gcd::value; + static ETL_CONSTANT intmax_t num = Num / etl::gcd_const::value; + static ETL_CONSTANT intmax_t den = Den / etl::gcd_const::value; typedef etl::ratio type; }; @@ -86,80 +64,78 @@ namespace etl template ETL_CONSTANT intmax_t ratio::den; - //*********************************************************************** - /// ratio_divide - //*********************************************************************** - template - struct ratio_divide - { - private: - - static ETL_CONSTANT intmax_t N = TRatio1::num * TRatio2::den; - static ETL_CONSTANT intmax_t D = TRatio1::den * TRatio2::num; - - static ETL_CONSTANT intmax_t Num = N / private_ratio::gcd::value; - static ETL_CONSTANT intmax_t Den = D / private_ratio::gcd::value; - - public: - - typedef etl::ratio type; - }; - - //*********************************************************************** - /// ratio_multiply - //*********************************************************************** - template - struct ratio_multiply - { - private: - - static ETL_CONSTANT intmax_t N = TRatio1::num * TRatio2::num; - static ETL_CONSTANT intmax_t D = TRatio1::den * TRatio2::den; - - static ETL_CONSTANT intmax_t Num = N / private_ratio::gcd::value; - static ETL_CONSTANT intmax_t Den = D / private_ratio::gcd::value; - - public: - - typedef etl::ratio type; - }; - +#if ETL_USING_CPP11 //*********************************************************************** /// ratio_add //*********************************************************************** template - struct ratio_add - { - private: - - static ETL_CONSTANT intmax_t N = (TRatio1::num * TRatio2::den) + (TRatio2::num * TRatio1::den); - static ETL_CONSTANT intmax_t D = TRatio1::den * TRatio2::den;; - - static ETL_CONSTANT intmax_t Num = N / private_ratio::gcd::value; - static ETL_CONSTANT intmax_t Den = D / private_ratio::gcd::value; - - public: - - typedef etl::ratio type; - }; + using ratio_add = etl::ratio<(TRatio1::num * TRatio2::den) + (TRatio2::num * TRatio1::den), TRatio1::den * TRatio2::den>; //*********************************************************************** /// ratio_subtract //*********************************************************************** template - struct ratio_subtract + using ratio_subtract = etl::ratio<(TRatio1::num * TRatio2::den) - (TRatio2::num * TRatio1::den), TRatio1::den * TRatio2::den>; + + //*********************************************************************** + /// ratio_multiply + //*********************************************************************** + template + using ratio_multiply = etl::ratio; + + //*********************************************************************** + /// ratio_divide + //*********************************************************************** + template + using ratio_divide = etl::ratio; +#endif + + //*********************************************************************** + /// ratio_equal + //*********************************************************************** + template + struct ratio_equal : etl::bool_constant<(TRatio1::num == TRatio2::num) && (TRatio1::den == TRatio2::den)> { - private: + }; - static ETL_CONSTANT intmax_t N = (TRatio1::num * TRatio2::den) - (TRatio2::num * TRatio1::den); - static ETL_CONSTANT intmax_t D = TRatio1::den * TRatio2::den;; + //*********************************************************************** + /// ratio_not_equal + //*********************************************************************** + template + struct ratio_not_equal : etl::bool_constant::value> + { + }; - static ETL_CONSTANT intmax_t Num = N / private_ratio::gcd::value; - static ETL_CONSTANT intmax_t Den = D / private_ratio::gcd::value; + //*********************************************************************** + /// ratio_less + //*********************************************************************** + template + struct ratio_less : etl::bool_constant<(TRatio1::num * TRatio2::den) < (TRatio2::num * TRatio1::den)> + { + }; - public: + //*********************************************************************** + /// ratio_less_equal + //*********************************************************************** + template + struct ratio_less_equal : etl::bool_constant::value> + { + }; - typedef etl::ratio type; + //*********************************************************************** + /// ratio_greater + //*********************************************************************** + template + struct ratio_greater : etl::bool_constant::value> + { + }; + + //*********************************************************************** + /// ratio_greater_equal + //*********************************************************************** + template + struct ratio_greater_equal : etl::bool_constant::value> + { }; //*********************************************************************** @@ -196,7 +172,7 @@ namespace etl typedef ratio<1000000000000000000, 1> exa; #endif - /// An approximation of PI to 6 digits. + /// An approximation of Pi. typedef ratio<355, 113> ratio_pi; /// An approximation of root 2. @@ -206,7 +182,7 @@ namespace etl typedef ratio<169, 239> ratio_1_over_root2; /// An approximation of e. - typedef ratio<326, 120> ratio_e; + typedef ratio<106, 39> ratio_e; } #endif diff --git a/test/test_ratio.cpp b/test/test_ratio.cpp index 7f061d49..fc7d5f06 100644 --- a/test/test_ratio.cpp +++ b/test/test_ratio.cpp @@ -47,17 +47,10 @@ namespace static ETL_CONSTANT intmax_t value = A; }; - // Helper to find the least common multiple - template - struct lcm - { - static ETL_CONSTANT intmax_t value = (A / gcd::value) * B; - }; - SUITE(test_ratio) { //************************************************************************* - TEST(test_constructor) + TEST(test_definitions) { constexpr intmax_t Num = 20; constexpr intmax_t Den = 600; @@ -77,6 +70,120 @@ namespace CHECK_EQUAL(D, ratio_type::den); } + //************************************************************************* + TEST(test_ratio_add) + { + using two_thirds = etl::ratio<2, 3>; + using one_sixth = etl::ratio<1, 6>; + using ratio = etl::ratio_add; + + CHECK_TRUE((std::is_same>::value)); + CHECK_EQUAL(5, ratio::num); + CHECK_EQUAL(6, ratio::den); + } + + //************************************************************************* + TEST(test_ratio_subtract) + { + using two_thirds = etl::ratio<2, 3>; + using one_sixth = etl::ratio<1, 6>; + using ratio = etl::ratio_subtract; + + CHECK_TRUE((std::is_same>::value)); + CHECK_EQUAL(1, ratio::num); + CHECK_EQUAL(2, ratio::den); + } + + //************************************************************************* + TEST(test_ratio_multiply) + { + using two_thirds = etl::ratio<2, 3>; + using one_sixth = etl::ratio<1, 6>; + using ratio = etl::ratio_multiply; + + CHECK_TRUE((std::is_same>::value)); + CHECK_EQUAL(1, ratio::num); + CHECK_EQUAL(9, ratio::den); + } + + //************************************************************************* + TEST(test_ratio_divide) + { + using two_thirds = etl::ratio<2, 3>; + using one_sixth = etl::ratio<1, 6>; + using ratio = etl::ratio_divide; + + CHECK_TRUE((std::is_same>::value)); + CHECK_EQUAL(4, ratio::num); + CHECK_EQUAL(1, ratio::den); + } + + //************************************************************************* + TEST(test_ratio_equal) + { + using ratio1 = etl::ratio<5, 32>; + using ratio2 = etl::ratio<3, 16>; // 6/32 + + CHECK_TRUE((etl::ratio_equal::value)); + CHECK_FALSE((etl::ratio_equal::value)); + CHECK_FALSE((etl::ratio_equal::value)); + } + + //************************************************************************* + TEST(test_ratio_not_equal) + { + using ratio1 = etl::ratio<5, 32>; + using ratio2 = etl::ratio<3, 16>; // 6/32 + + CHECK_FALSE((etl::ratio_not_equal::value)); + CHECK_TRUE((etl::ratio_not_equal::value)); + CHECK_TRUE((etl::ratio_not_equal::value)); + } + + //************************************************************************* + TEST(test_ratio_less) + { + using ratio1 = etl::ratio<5, 32>; + using ratio2 = etl::ratio<3, 16>; // 6/32 + + CHECK_FALSE((etl::ratio_less::value)); + CHECK_TRUE((etl::ratio_less::value)); + CHECK_FALSE((etl::ratio_less::value)); + } + + //************************************************************************* + TEST(test_ratio_less_equal) + { + using ratio1 = etl::ratio<5, 32>; + using ratio2 = etl::ratio<3, 16>; // 6/32 + + CHECK_TRUE((etl::ratio_less_equal::value)); + CHECK_TRUE((etl::ratio_less_equal::value)); + CHECK_FALSE((etl::ratio_less_equal::value)); + } + + //************************************************************************* + TEST(test_ratio_greater) + { + using ratio1 = etl::ratio<5, 32>; + using ratio2 = etl::ratio<3, 16>; // 6/32 + + CHECK_FALSE((etl::ratio_greater::value)); + CHECK_FALSE((etl::ratio_greater::value)); + CHECK_TRUE((etl::ratio_greater::value)); + } + + //************************************************************************* + TEST(test_ratio_greater_equal) + { + using ratio1 = etl::ratio<5, 32>; + using ratio2 = etl::ratio<3, 16>; // 6/32 + + CHECK_TRUE((etl::ratio_greater_equal::value)); + CHECK_FALSE((etl::ratio_greater_equal::value)); + CHECK_TRUE((etl::ratio_greater_equal::value)); + } + //************************************************************************* TEST(test_predefined_ratios) { @@ -126,8 +233,19 @@ namespace double expected_pi = 3.1415926535897931; double actual_pi = double(etl::ratio_pi::num) / double(etl::ratio_pi::den); - CHECK_CLOSE(expected_pi, actual_pi, 0.0000003); + + double expected_root_2 = 1.414213562373095; + double actual_root_2 = double(etl::ratio_root2::num) / double(etl::ratio_root2::den); + CHECK_CLOSE(expected_root_2, actual_root_2, 0.00002); + + double expected_1_over_root_2 = 1.0 / 1.414213562373095; + double actual_1_over_root_2 = double(etl::ratio_1_over_root2::num) / double(etl::ratio_1_over_root2::den); + CHECK_CLOSE(expected_1_over_root_2, actual_1_over_root_2, 0.000007); + + double expected_e = 2.7182818284590451; + double actual_e = double(etl::ratio_e::num) / double(etl::ratio_e::den); + CHECK_CLOSE(expected_e, actual_e, 0.0004); } }; } diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 1d21befc..1ce125eb 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -8899,6 +8899,7 @@ + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index d0b88961..69327b6f 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -3443,6 +3443,9 @@ Tests\Chrono + + Tests\Misc + From bc158cbcbc95e18e7374cdc3250c12bd7c9162a1 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 18 Apr 2025 10:50:48 +0100 Subject: [PATCH 16/33] Updates to chrono classes --- .gitignore | 2 + include/etl/chrono.h | 4 +- include/etl/platform.h | 16 +- include/etl/private/chrono/day.h | 4 +- include/etl/private/chrono/duration.h | 30 +- include/etl/private/chrono/month.h | 4 +- include/etl/private/chrono/month_day.h | 156 ++++++ include/etl/private/chrono/operators.h | 189 +++++++ include/etl/private/chrono/weekday.h | 6 +- include/etl/private/chrono/year.h | 4 +- test/.gitattributes | 1 + test/CMakeLists.txt | 597 +++++++++++----------- test/cppcheck_macro_definitions.txt | 5 + test/test_chrono_day.cpp | 195 +++---- test/test_chrono_month_day.cpp | 384 ++++++++++++++ test/test_chrono_weekday.cpp | 3 + test/test_chrono_weekday_indexed.cpp | 1 + test/test_chrono_weekday_last.cpp | 1 + test/vs2022/etl.vcxproj | 4 + test/vs2022/etl.vcxproj.filters | 12 + test/vs2022/etl_solution_suppressions.cfg | 4 + 21 files changed, 1174 insertions(+), 448 deletions(-) create mode 100644 include/etl/private/chrono/month_day.h create mode 100644 include/etl/private/chrono/operators.h create mode 100644 test/.gitattributes create mode 100644 test/cppcheck_macro_definitions.txt create mode 100644 test/test_chrono_month_day.cpp create mode 100644 test/vs2022/etl_solution_suppressions.cfg diff --git a/.gitignore b/.gitignore index ab33079c..420a66d3 100644 --- a/.gitignore +++ b/.gitignore @@ -389,3 +389,5 @@ test/vs2022/Debug MSVC C++20 - Force C++03 test/vs2022/Release MSVC C++20 - No STL - Optimised -O2 - Sanitiser test/test_file_list.txt test/reflog.txt +test/etl_error_handler/assert_function/build-make +test/syntax_check/bgcc diff --git a/include/etl/chrono.h b/include/etl/chrono.h index 51fd1fd8..8789d656 100644 --- a/include/etl/chrono.h +++ b/include/etl/chrono.h @@ -49,7 +49,9 @@ SOFTWARE. #include "private/chrono/weekday_indexed.h" #include "private/chrono/weekday_last.h" #include "private/chrono/month.h" -#include "private/chrono/year.h" +#include "private/chrono/month_day.h" +#include "private/chrono/year.h" +#include "private/chrono/operators.h" #endif #undef ETL_IN_CHRONO_H diff --git a/include/etl/platform.h b/include/etl/platform.h index 361fade2..1eaa1329 100644 --- a/include/etl/platform.h +++ b/include/etl/platform.h @@ -272,8 +272,8 @@ SOFTWARE. #endif //************************************* -// Indicate if etl::literals::chrono_literals has weekdays (_day) -#if defined(ETL_DISABLE_CHRONO_LITERALS_WEEKDAY) +// Indicate if etl::literals::chrono_literals has days (_days) +#if defined(ETL_DISABLE_CHRONO_LITERALS_DAY) #define ETL_HAS_CHRONO_LITERALS_DAY 0 #else #define ETL_HAS_CHRONO_LITERALS_DAY 1 @@ -288,7 +288,7 @@ SOFTWARE. #endif //************************************* -// Indicate if etl::literals::chrono_literals has month (_month) +// Indicate if etl::literals::chrono_literals has month (_months) #if defined(ETL_DISABLE_CHRONO_LITERALS_MONTH) #define ETL_HAS_CHRONO_LITERALS_MONTH 0 #else @@ -296,13 +296,21 @@ SOFTWARE. #endif //************************************* -// Indicate if etl::literals::chrono_literals has year (_year) +// Indicate if etl::literals::chrono_literals has year (_years) #if defined(ETL_DISABLE_CHRONO_LITERALS_YEAR) #define ETL_HAS_CHRONO_LITERALS_YEAR 0 #else #define ETL_HAS_CHRONO_LITERALS_YEAR 1 #endif +//************************************* +// Indicate if etl::literals::chrono_literals has year (_hours, _minutes, _seconds, _milliseconds, _microseconds, _nanoseconds) +#if defined(ETL_DISABLE_CHRONO_LITERALS_DURATION) +#define ETL_HAS_CHRONO_LITERALS_DURATION 0 +#else +#define ETL_HAS_CHRONO_LITERALS_DURATION 1 +#endif + //************************************* // The macros below are dependent on the profile. // C++11 diff --git a/include/etl/private/chrono/day.h b/include/etl/private/chrono/day.h index 91557a95..511ae0a9 100644 --- a/include/etl/private/chrono/day.h +++ b/include/etl/private/chrono/day.h @@ -311,7 +311,6 @@ namespace etl } #if ETL_HAS_CHRONO_LITERALS_DAY -#if ETL_USING_CPP11 namespace etl { namespace literals @@ -321,7 +320,7 @@ namespace etl //*********************************************************************** /// Literal for days //*********************************************************************** - constexpr etl::chrono::day operator ""_day(unsigned long long d) noexcept + inline constexpr etl::chrono::day operator ""_day(unsigned long long d) noexcept { return etl::chrono::day(static_cast(d)); } @@ -329,4 +328,3 @@ namespace etl } } #endif -#endif diff --git a/include/etl/private/chrono/duration.h b/include/etl/private/chrono/duration.h index 6d4a5334..10c79460 100644 --- a/include/etl/private/chrono/duration.h +++ b/include/etl/private/chrono/duration.h @@ -258,11 +258,17 @@ namespace etl { ETL_CONSTEXPR14 size_t operator()(const etl::chrono::duration& d) const { - TRep value = d.count(); - size_t num = TPeriod::num; - size_t den = TPeriod::den; + uint8_t buffer[sizeof(TRep) + sizeof(intmax_t) + sizeof(intmax_t)]; - return 0; //etl::private_hash::generic_hash(p, p + sizeof(unsigned)); + TRep value = d.count(); + intmax_t num = TPeriod::num; + intmax_t den = TPeriod::den; + + memcpy(buffer, &value, sizeof(TRep)); + memcpy(buffer + sizeof(TRep), &num, sizeof(intmax_t)); + memcpy(buffer + sizeof(TRep) + sizeof(intmax_t), &den, sizeof(intmax_t)); + + return etl::private_hash::generic_hash(buffer, buffer + sizeof(TRep) + sizeof(intmax_t) + sizeof(intmax_t)); } }; #endif @@ -349,8 +355,7 @@ namespace etl } } -#if ETL_HAS_CHRONO_LITERALS_DAY -#if ETL_USING_CPP11 +#if ETL_HAS_CHRONO_LITERALS_DURATION namespace etl { namespace literals @@ -360,7 +365,7 @@ namespace etl //*********************************************************************** /// Literal for hours duration //*********************************************************************** - ETL_IF_CONSTEXPR etl::chrono::hours operator ""_hours(unsigned long long h) noexcept + inline ETL_CONSTEXPR etl::chrono::hours operator ""_hours(unsigned long long h) noexcept { return etl::chrono::hours(static_cast(h)); } @@ -368,7 +373,7 @@ namespace etl //*********************************************************************** /// Literal for minutes duration //*********************************************************************** - ETL_IF_CONSTEXPR etl::chrono::minutes operator ""_minutes(unsigned long long m) noexcept + inline ETL_CONSTEXPR etl::chrono::minutes operator ""_minutes(unsigned long long m) noexcept { return etl::chrono::minutes(static_cast(m)); } @@ -376,7 +381,7 @@ namespace etl //*********************************************************************** /// Literal for seconds duration //*********************************************************************** - ETL_IF_CONSTEXPR etl::chrono::seconds operator ""_seconds(unsigned long long s) noexcept + inline ETL_CONSTEXPR etl::chrono::seconds operator ""_seconds(unsigned long long s) noexcept { return etl::chrono::seconds(static_cast(s)); } @@ -384,7 +389,7 @@ namespace etl //*********************************************************************** /// Literal for milliseconds duration //*********************************************************************** - ETL_IF_CONSTEXPR etl::chrono::milliseconds operator ""_milliseconds(unsigned long long s) noexcept + inline ETL_CONSTEXPR etl::chrono::milliseconds operator ""_milliseconds(unsigned long long s) noexcept { return etl::chrono::milliseconds(static_cast(s)); } @@ -392,7 +397,7 @@ namespace etl //*********************************************************************** /// Literal for microseconds duration //*********************************************************************** - ETL_IF_CONSTEXPR etl::chrono::microseconds operator ""_microseconds(unsigned long long s) noexcept + inline ETL_CONSTEXPR etl::chrono::microseconds operator ""_microseconds(unsigned long long s) noexcept { return etl::chrono::microseconds(static_cast(s)); } @@ -400,7 +405,7 @@ namespace etl //*********************************************************************** /// Literal for nanoseconds duration //*********************************************************************** - ETL_IF_CONSTEXPR etl::chrono::nanoseconds operator ""_nanoseconds(unsigned long long s) noexcept + inline ETL_CONSTEXPR etl::chrono::nanoseconds operator ""_nanoseconds(unsigned long long s) noexcept { return etl::chrono::nanoseconds(static_cast(s)); } @@ -408,4 +413,3 @@ namespace etl } } #endif -#endif diff --git a/include/etl/private/chrono/month.h b/include/etl/private/chrono/month.h index 30653a58..f9693c2c 100644 --- a/include/etl/private/chrono/month.h +++ b/include/etl/private/chrono/month.h @@ -362,7 +362,6 @@ namespace etl } #if ETL_HAS_CHRONO_LITERALS_MONTH -#if ETL_USING_CPP11 namespace etl { namespace literals @@ -372,7 +371,7 @@ namespace etl //*********************************************************************** /// Literal for months //*********************************************************************** - constexpr etl::chrono::month operator ""_month(unsigned long long m) noexcept + inline constexpr etl::chrono::month operator ""_month(unsigned long long m) noexcept { return etl::chrono::month(static_cast(m)); } @@ -380,4 +379,3 @@ namespace etl } } #endif -#endif diff --git a/include/etl/private/chrono/month_day.h b/include/etl/private/chrono/month_day.h new file mode 100644 index 00000000..fbcb03bc --- /dev/null +++ b/include/etl/private/chrono/month_day.h @@ -0,0 +1,156 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +namespace etl +{ + namespace chrono + { + namespace private_chrono + { + static ETL_CONSTANT unsigned char days_in_month[13] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + } + + class month_day + { + public: + + //************************************************************************* + /// Default constructor. + //************************************************************************* + month_day() = default; + + //************************************************************************* + /// Construct from month and day. + //************************************************************************* + ETL_CONSTEXPR month_day(const etl::chrono::month& m_, const etl::chrono::day& d_) ETL_NOEXCEPT + : m(m_) + , d(d_) + { + } + + //************************************************************************* + /// Returns the month. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::month month() const ETL_NOEXCEPT + { + return m; + } + + //************************************************************************* + /// Returns the day. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::day day() const ETL_NOEXCEPT + { + return d; + } + + //************************************************************************* + /// Returns true if the month/day is valid. + //************************************************************************* + ETL_CONSTEXPR14 bool ok() const ETL_NOEXCEPT + { + if (!m.ok() || !d.ok()) + { + return false; + } + + unsigned max_day = 0; + + unsigned m_v = static_cast(m); + max_day = private_chrono::days_in_month[m_v]; + + return (max_day > 0) && + (static_cast(d) >= 1) && + (static_cast(d) <= max_day); + } + + //************************************************************************* + /// Returns true if the two instances are equal. + //************************************************************************* + friend ETL_CONSTEXPR bool operator ==(const etl::chrono::month_day& lhs, + const etl::chrono::month_day& rhs) ETL_NOEXCEPT + { + return (lhs.d == rhs.d) && (lhs.m == rhs.m); + } + + //*********************************************************************** + /// Spaceship operator + //*********************************************************************** +#if ETL_USING_CPP20 + friend [[nodiscard]] constexpr auto operator <=>(const etl::chrono::month_day& lhs, + const etl::chrono::month_day& rhs) noexcept + { + auto cmp = lhs.m <=> rhs.m; + + if (cmp != 0) + { + return cmp; + } + else + { + return lhs.d <=> rhs.d; + } + } +#endif + + private: + + etl::chrono::month m; + etl::chrono::day d; + }; + } + + //************************************************************************* + /// Hash function for etl::chrono::month_day + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::month_day& md) const + { + uint8_t buffer[sizeof(unsigned int) + sizeof(unsigned int)]; + + unsigned int m = md.month(); + unsigned int d = md.day(); + + memcpy(buffer, &m, sizeof(m)); + memcpy(buffer + sizeof(m), &d, sizeof(d)); + + return etl::private_hash::generic_hash(buffer, buffer + sizeof(unsigned int) + sizeof(unsigned int)); + } + }; +#endif +} + diff --git a/include/etl/private/chrono/operators.h b/include/etl/private/chrono/operators.h new file mode 100644 index 00000000..169217e7 --- /dev/null +++ b/include/etl/private/chrono/operators.h @@ -0,0 +1,189 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +namespace etl +{ + namespace chrono + { + //// year_month + //constexpr auto operator/(const etl::chrono::year& y, + // const etl::chrono::month& m ) noexcept + // -> etl::chrono::year_month; + + //constexpr auto operator/( const etl::chrono::year& y, int m ) noexcept + // -> etl::chrono::year_month; + + //// month_day + //constexpr auto operator/( const etl::chrono::month& m, + // const etl::chrono::day& d ) noexcept + // -> etl::chrono::month_day; + + //constexpr auto operator/( const etl::chrono::month& m, int d ) noexcept + // -> etl::chrono::month_day; + + //constexpr auto operator/( int m, const etl::chrono::day& d ) noexcept + // -> etl::chrono::month_day; + + //constexpr auto operator/( const etl::chrono::day& d, + // const etl::chrono::month& m ) noexcept + // -> etl::chrono::month_day; + + //constexpr auto operator/( const etl::chrono::day& d, int m ) noexcept + // -> etl::chrono::month_day; + + //// month_day_last + //constexpr auto operator/( const etl::chrono::month& m, + // etl::chrono::last_spec ) noexcept + // -> etl::chrono::month_day_last; + + //constexpr auto operator/( int m, etl::chrono::last_spec ) noexcept + // -> etl::chrono::month_day_last; + + //constexpr auto operator/( etl::chrono::last_spec, + // const etl::chrono::month& m ) noexcept + // -> etl::chrono::month_day_last; + + //constexpr auto operator/( etl::chrono::last_spec, int m ) noexcept + // -> etl::chrono::month_day_last; + + //// month_weekday + //constexpr auto operator/( const etl::chrono::month& m, + // const etl::chrono::weekday_indexed& wdi ) noexcept + // -> etl::chrono::month_weekday; + + //constexpr auto operator/( int m, const etl::chrono::weekday_indexed& wdi ) noexcept + // -> etl::chrono::month_weekday; + + //constexpr auto operator/(const etl::chrono::weekday_indexed& wdi, + // const etl::chrono::month& m ) noexcept + // -> etl::chrono::month_weekday; + + //constexpr auto operator/( const etl::chrono::weekday_indexed& wdi, int m ) noexcept + // -> etl::chrono::month_weekday; + + //// month_weekday_last + //constexpr auto operator/( const etl::chrono::month& m, + // const etl::chrono::weekday_last& wdl ) noexcept + // -> etl::chrono::month_weekday_last; + + //constexpr auto operator/( int m, const etl::chrono::weekday_last& wdl ) noexcept + // -> etl::chrono::month_weekday_last; + + //constexpr auto operator/( const etl::chrono::weekday_last& wdl, + // const etl::chrono::month& m ) noexcept + // -> etl::chrono::month_weekday_last; + + //constexpr auto operator/( const etl::chrono::weekday_last& wdl, int m ) noexcept + // -> etl::chrono::month_weekday_last; + + //// year_month_day + //constexpr auto operator/( const etl::chrono::year_month& ym, + // const etl::chrono::day& d ) noexcept + // -> etl::chrono::year_month_day; + + //constexpr auto operator/( const etl::chrono::year_month& ym, int d ) noexcept + // -> etl::chrono::year_month_day; + + //constexpr auto operator/( const etl::chrono::year& y, + // const etl::chrono::month_day& md ) noexcept + // -> etl::chrono::year_month_day; + + //constexpr auto operator/( int y, const etl::chrono::month_day& md ) noexcept + // -> etl::chrono::year_month_day; + + //constexpr auto operator/( const etl::chrono::month_day& md, + // const etl::chrono::year& y ) noexcept + // -> etl::chrono::year_month_day; + + //constexpr auto operator/( const etl::chrono::month_day& md, int y ) noexcept + // -> etl::chrono::year_month_day; + + //// year_month_day_last + //constexpr auto operator/( const etl::chrono::year_month& ym, + // etl::chrono::last_spec ) noexcept + // -> etl::chrono::year_month_day_last; + + //constexpr auto operator/( const etl::chrono::year& y, + // const etl::chrono::month_day_last& mdl ) noexcept + // -> etl::chrono::year_month_day_last; + + //constexpr auto operator/( int y, const etl::chrono::month_day_last& mdl ) noexcept + // -> etl::chrono::year_month_day_last; + + //constexpr auto operator/( const etl::chrono::month_day_last& mdl, + // const etl::chrono::year& y ) noexcept + // -> etl::chrono::year_month_day_last; + + //constexpr auto operator/( const etl::chrono::month_day_last& mdl, int y ) noexcept + // -> etl::chrono::year_month_day_last; + + //// year_month_weekday + //constexpr auto operator/( const etl::chrono::year_month& ym, + // const etl::chrono::weekday_indexed& wdi ) noexcept + // -> etl::chrono::year_month_weekday; + + //constexpr auto operator/( const etl::chrono::year& y, + // const etl::chrono::month_weekday& mwd ) noexcept + // -> etl::chrono::year_month_weekday; + + //constexpr auto operator/( int y, const etl::chrono::month_weekday& mwd ) noexcept + // -> etl::chrono::year_month_weekday; + + //constexpr auto operator/( const etl::chrono::month_weekday& mwd, + // const etl::chrono::year& y ) noexcept + // -> etl::chrono::year_month_weekday; + + //constexpr auto operator/( const etl::chrono::month_weekday& mwd, int y ) noexcept + // -> etl::chrono::year_month_weekday; + + //// year_month_weekday_last + //constexpr auto operator/( const etl::chrono::year_month& ym, + // const etl::chrono::weekday_last& wdl ) noexcept + // -> etl::chrono::year_month_weekday_last; + + //constexpr auto operator/( const etl::chrono::year& y, + // const etl::chrono::month_weekday_last& mwdl ) noexcept + // -> etl::chrono::year_month_weekday_last; + + //constexpr auto operator/( int y, const etl::chrono::month_weekday_last& mwdl ) noexcept + // -> etl::chrono::year_month_weekday_last; + + //constexpr auto operator/( const etl::chrono::month_weekday_last& mwdl, + // const etl::chrono::year& y ) noexcept + // -> etl::chrono::year_month_weekday_last; + + //constexpr auto operator/( const etl::chrono::month_weekday_last& mwdl, int y ) noexcept + // -> etl::chrono::year_month_weekday_last; + } +} \ No newline at end of file diff --git a/include/etl/private/chrono/weekday.h b/include/etl/private/chrono/weekday.h index fc4df27f..d294d9c8 100644 --- a/include/etl/private/chrono/weekday.h +++ b/include/etl/private/chrono/weekday.h @@ -370,7 +370,6 @@ namespace etl } #if ETL_HAS_CHRONO_LITERALS_WEEKDAY -#if ETL_USING_CPP11 namespace etl { namespace literals @@ -380,12 +379,11 @@ namespace etl //*********************************************************************** /// Literal for weekdays //*********************************************************************** - constexpr etl::chrono::weekday operator ""_weekday(unsigned long long m) noexcept + inline constexpr etl::chrono::weekday operator ""_weekday(unsigned long long wd) noexcept { - return etl::chrono::weekday(static_cast(m)); + return etl::chrono::weekday(static_cast(wd)); } } } } #endif -#endif diff --git a/include/etl/private/chrono/year.h b/include/etl/private/chrono/year.h index ff873e37..695d369f 100644 --- a/include/etl/private/chrono/year.h +++ b/include/etl/private/chrono/year.h @@ -311,7 +311,6 @@ namespace etl } #if ETL_HAS_CHRONO_LITERALS_YEAR -#if ETL_USING_CPP11 namespace etl { namespace literals @@ -321,7 +320,7 @@ namespace etl //*********************************************************************** /// Literal for years //*********************************************************************** - constexpr etl::chrono::year operator ""_year(unsigned long long y) noexcept + inline constexpr etl::chrono::year operator ""_year(unsigned long long y) noexcept { return etl::chrono::year(static_cast(y)); } @@ -329,4 +328,3 @@ namespace etl } } #endif -#endif diff --git a/test/.gitattributes b/test/.gitattributes new file mode 100644 index 00000000..5a97bcac --- /dev/null +++ b/test/.gitattributes @@ -0,0 +1 @@ +*.tar filter=lfs diff=lfs merge=lfs -text diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 648d4c4f..87fe5d39 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -12,307 +12,308 @@ project(etl_unit_tests LANGUAGES CXX) add_executable(etl_tests main.cpp - murmurhash3.cpp - test_algorithm.cpp - test_alignment.cpp - test_array.cpp - test_array_view.cpp - test_array_wrapper.cpp - test_atomic.cpp - test_base64_RFC2152_decoder.cpp - test_base64_RFC2152_encoder.cpp - test_base64_RFC3501_decoder.cpp - test_base64_RFC3501_encoder.cpp - test_base64_RFC4648_decoder_with_no_padding.cpp - test_base64_RFC4648_decoder_with_padding.cpp - test_base64_RFC4648_encoder_with_no_padding.cpp - test_base64_RFC4648_encoder_with_padding.cpp - test_base64_RFC4648_URL_decoder_with_no_padding.cpp - test_base64_RFC4648_URL_decoder_with_padding.cpp - test_base64_RFC4648_URL_encoder_with_no_padding.cpp - test_base64_RFC4648_URL_encoder_with_padding.cpp - test_binary.cpp - test_bip_buffer_spsc_atomic.cpp - test_bit.cpp - test_bitset_legacy.cpp - test_bitset_new_comparisons.cpp - test_bitset_new_default_element_type.cpp - test_bitset_new_explicit_single_element_type.cpp - test_bitset_new_ext_default_element_type.cpp - test_bitset_new_ext_explicit_single_element_type.cpp - test_bit_stream.cpp - test_bit_stream_reader_big_endian.cpp - test_bit_stream_reader_little_endian.cpp - test_bit_stream_writer_big_endian.cpp - test_bit_stream_writer_little_endian.cpp - test_bloom_filter.cpp - test_bresenham_line.cpp - test_bsd_checksum.cpp - test_buffer_descriptors.cpp - test_byte.cpp - test_byte_stream.cpp - test_callback_service.cpp - test_callback_timer.cpp - test_callback_timer_atomic.cpp - test_callback_timer_interrupt.cpp - test_callback_timer_locked.cpp - test_char_traits.cpp - test_checksum.cpp - +# murmurhash3.cpp +# test_algorithm.cpp +# test_alignment.cpp +# test_array.cpp +# test_array_view.cpp +# test_array_wrapper.cpp +# test_atomic.cpp +# test_base64_RFC2152_decoder.cpp +# test_base64_RFC2152_encoder.cpp +# test_base64_RFC3501_decoder.cpp +# test_base64_RFC3501_encoder.cpp +# test_base64_RFC4648_decoder_with_no_padding.cpp +# test_base64_RFC4648_decoder_with_padding.cpp +# test_base64_RFC4648_encoder_with_no_padding.cpp +# test_base64_RFC4648_encoder_with_padding.cpp +# test_base64_RFC4648_URL_decoder_with_no_padding.cpp +# test_base64_RFC4648_URL_decoder_with_padding.cpp +# test_base64_RFC4648_URL_encoder_with_no_padding.cpp +# test_base64_RFC4648_URL_encoder_with_padding.cpp +# test_binary.cpp +# test_bip_buffer_spsc_atomic.cpp +# test_bit.cpp +# test_bitset_legacy.cpp +# test_bitset_new_comparisons.cpp +# test_bitset_new_default_element_type.cpp +# test_bitset_new_explicit_single_element_type.cpp +# test_bitset_new_ext_default_element_type.cpp +# test_bitset_new_ext_explicit_single_element_type.cpp +# test_bit_stream.cpp +# test_bit_stream_reader_big_endian.cpp +# test_bit_stream_reader_little_endian.cpp +# test_bit_stream_writer_big_endian.cpp +# test_bit_stream_writer_little_endian.cpp +# test_bloom_filter.cpp +# test_bresenham_line.cpp +# test_bsd_checksum.cpp +# test_buffer_descriptors.cpp +# test_byte.cpp +# test_byte_stream.cpp +# test_callback_service.cpp +# test_callback_timer.cpp +# test_callback_timer_atomic.cpp +# test_callback_timer_interrupt.cpp +# test_callback_timer_locked.cpp +# test_char_traits.cpp +# test_checksum.cpp test_chrono_day.cpp - test_chrono_weekday.cpp + test_chrono_duration.cpp test_chrono_month.cpp + test_chrono_weekday.cpp + test_chrono_weekday_indexed.cpp + test_chrono_weekday_last.cpp test_chrono_year.cpp - - test_circular_buffer.cpp - test_circular_buffer_external_buffer.cpp - test_circular_iterator.cpp - test_compare.cpp - test_constant.cpp - test_container.cpp - test_correlation.cpp - test_covariance.cpp - test_crc1.cpp - test_crc16.cpp - test_crc16_a.cpp - test_crc16_arc.cpp - test_crc16_aug_ccitt.cpp - test_crc16_buypass.cpp - test_crc16_ccitt.cpp - test_crc16_cdma2000.cpp - test_crc16_dds110.cpp - test_crc16_dectr.cpp - test_crc16_dectx.cpp - test_crc16_dnp.cpp - test_crc16_en13757.cpp - test_crc16_genibus.cpp - test_crc16_kermit.cpp - test_crc16_m17.cpp - test_crc16_maxim.cpp - test_crc16_mcrf4xx.cpp - test_crc16_modbus.cpp - test_crc16_profibus.cpp - test_crc16_riello.cpp - test_crc16_t10dif.cpp - test_crc16_teledisk.cpp - test_crc16_tms37157.cpp - test_crc16_usb.cpp - test_crc16_x25.cpp - test_crc16_xmodem.cpp - test_crc32.cpp - test_crc32_bzip2.cpp - test_crc32_c.cpp - test_crc32_d.cpp - test_crc32_jamcrc.cpp - test_crc32_mpeg2.cpp - test_crc32_posix.cpp - test_crc32_q.cpp - test_crc32_xfer.cpp - test_crc64_ecma.cpp - test_crc8_ccitt.cpp - test_crc8_cdma2000.cpp - test_crc8_darc.cpp - test_crc8_dvbs2.cpp - test_crc8_ebu.cpp - test_crc8_icode.cpp - test_crc8_itu.cpp - test_crc8_j1850.cpp - test_crc8_j1850_zero.cpp - test_crc8_maxim.cpp - test_crc8_rohc.cpp - test_crc8_wcdma.cpp - test_cyclic_value.cpp - test_debounce.cpp - test_delegate.cpp - test_delegate_cpp03.cpp - test_delegate_service.cpp - test_delegate_service_compile_time.cpp - test_delegate_service_cpp03.cpp - test_deque.cpp - test_endian.cpp - test_enum_type.cpp - test_error_handler.cpp - test_etl_traits.cpp - test_exception.cpp - test_expected.cpp - test_fixed_iterator.cpp - test_fixed_sized_memory_block_allocator.cpp - test_flags.cpp - test_flat_map.cpp - test_flat_multimap.cpp - test_flat_multiset.cpp - test_flat_set.cpp - test_fnv_1.cpp - test_format_spec.cpp - test_forward_list.cpp - test_forward_list_shared_pool.cpp - test_fsm.cpp - test_function.cpp - test_functional.cpp - test_gamma.cpp - test_hash.cpp - test_hfsm.cpp - test_hfsm_recurse_to_inner_state_on_start.cpp - test_histogram.cpp - test_indirect_vector.cpp - test_indirect_vector_external_buffer.cpp - test_instance_count.cpp - test_integral_limits.cpp - test_intrusive_forward_list.cpp - test_intrusive_links.cpp - test_intrusive_list.cpp - test_intrusive_queue.cpp - test_intrusive_stack.cpp - test_invert.cpp - test_io_port.cpp - test_iterator.cpp - test_jenkins.cpp - test_largest.cpp - test_limiter.cpp - test_limits.cpp - test_list.cpp - test_list_shared_pool.cpp - test_macros.cpp - test_make_string.cpp - test_map.cpp - test_math.cpp - test_math_functions.cpp - test_mean.cpp - test_memory.cpp - test_mem_cast.cpp - test_mem_cast_ptr.cpp - test_message.cpp - test_message_broker.cpp - test_message_bus.cpp - test_message_packet.cpp - test_message_router.cpp - test_message_router_registry.cpp - test_message_timer.cpp - test_message_timer_atomic.cpp - test_message_timer_interrupt.cpp - test_message_timer_locked.cpp - test_multimap.cpp - test_multiset.cpp - test_multi_array.cpp - test_multi_range.cpp - test_multi_span.cpp - test_multi_vector.cpp - test_murmur3.cpp - test_nth_type.cpp - test_numeric.cpp - test_observer.cpp - test_optional.cpp - test_overload.cpp - test_packet.cpp - test_parameter_pack.cpp - test_parameter_type.cpp - test_parity_checksum.cpp - test_pearson.cpp - test_poly_span_dynamic_extent.cpp - test_poly_span_fixed_extent.cpp - test_pool.cpp - test_pool_external_buffer.cpp - test_priority_queue.cpp - test_pseudo_moving_average.cpp - test_quantize.cpp - test_queue.cpp - test_queue_lockable.cpp - test_queue_lockable_small.cpp - test_queue_memory_model_small.cpp - test_queue_mpmc_mutex.cpp - test_queue_mpmc_mutex_small.cpp - test_queue_spsc_atomic.cpp - test_queue_spsc_atomic_small.cpp - test_queue_spsc_isr.cpp - test_queue_spsc_isr_small.cpp - test_queue_spsc_locked.cpp - test_queue_spsc_locked_small.cpp - test_random.cpp - test_reference_flat_map.cpp - test_reference_flat_multimap.cpp - test_reference_flat_multiset.cpp - test_reference_flat_set.cpp - test_rescale.cpp - test_result.cpp - test_rms.cpp - test_scaled_rounding.cpp - test_set.cpp - test_shared_message.cpp - test_singleton.cpp - test_smallest.cpp - test_span_dynamic_extent.cpp - test_span_fixed_extent.cpp - test_stack.cpp - test_standard_deviation.cpp - test_state_chart.cpp - test_state_chart_compile_time.cpp - test_state_chart_compile_time_with_data_parameter.cpp - test_state_chart_with_data_parameter.cpp - test_state_chart_with_rvalue_data_parameter.cpp - test_string_char.cpp - test_string_char_external_buffer.cpp - test_string_stream.cpp - test_string_stream_u16.cpp - test_string_stream_u32.cpp - test_string_stream_u8.cpp - test_string_stream_wchar_t.cpp - test_string_u16.cpp - test_string_u16_external_buffer.cpp - test_string_u32.cpp - test_string_u32_external_buffer.cpp - test_string_u8.cpp - test_string_u8_external_buffer.cpp - test_string_utilities.cpp - test_string_utilities_std.cpp - test_string_utilities_std_u16.cpp - test_string_utilities_std_u32.cpp - test_string_utilities_std_u8.cpp - test_string_utilities_std_wchar_t.cpp - test_string_utilities_u16.cpp - test_string_utilities_u32.cpp - test_string_utilities_u8.cpp - test_string_utilities_wchar_t.cpp - test_string_view.cpp - test_string_wchar_t.cpp - test_string_wchar_t_external_buffer.cpp - test_successor.cpp - test_task_scheduler.cpp - test_threshold.cpp - test_to_arithmetic.cpp - test_to_arithmetic_u16.cpp - test_to_arithmetic_u32.cpp - test_to_arithmetic_u8.cpp - test_to_arithmetic_wchar_t.cpp - test_to_string.cpp - test_to_u16string.cpp - test_to_u32string.cpp - test_to_u8string.cpp - test_to_wstring.cpp - test_type_def.cpp - test_type_lookup.cpp - test_type_select.cpp - test_type_traits.cpp - test_unaligned_type.cpp - test_unaligned_type_constexpr.cpp - test_unordered_map.cpp - test_unordered_multimap.cpp - test_unordered_multiset.cpp - test_unordered_set.cpp - test_user_type.cpp - test_utility.cpp - test_variance.cpp - test_variant_legacy.cpp - test_variant_pool.cpp - test_variant_pool_external_buffer.cpp - test_variant_variadic.cpp - test_vector.cpp - test_vector_external_buffer.cpp - test_vector_non_trivial.cpp - test_vector_pointer.cpp - test_vector_pointer_external_buffer.cpp - test_visitor.cpp - test_xor_checksum.cpp - test_xor_rotate_checksum.cpp +# test_circular_buffer.cpp +# test_circular_buffer_external_buffer.cpp +# test_circular_iterator.cpp +# test_compare.cpp +# test_constant.cpp +# test_container.cpp +# test_correlation.cpp +# test_covariance.cpp +# test_crc1.cpp +# test_crc16.cpp +# test_crc16_a.cpp +# test_crc16_arc.cpp +# test_crc16_aug_ccitt.cpp +# test_crc16_buypass.cpp +# test_crc16_ccitt.cpp +# test_crc16_cdma2000.cpp +# test_crc16_dds110.cpp +# test_crc16_dectr.cpp +# test_crc16_dectx.cpp +# test_crc16_dnp.cpp +# test_crc16_en13757.cpp +# test_crc16_genibus.cpp +# test_crc16_kermit.cpp +# test_crc16_m17.cpp +# test_crc16_maxim.cpp +# test_crc16_mcrf4xx.cpp +# test_crc16_modbus.cpp +# test_crc16_profibus.cpp +# test_crc16_riello.cpp +# test_crc16_t10dif.cpp +# test_crc16_teledisk.cpp +# test_crc16_tms37157.cpp +# test_crc16_usb.cpp +# test_crc16_x25.cpp +# test_crc16_xmodem.cpp +# test_crc32.cpp +# test_crc32_bzip2.cpp +# test_crc32_c.cpp +# test_crc32_d.cpp +# test_crc32_jamcrc.cpp +# test_crc32_mpeg2.cpp +# test_crc32_posix.cpp +# test_crc32_q.cpp +# test_crc32_xfer.cpp +# test_crc64_ecma.cpp +# test_crc8_ccitt.cpp +# test_crc8_cdma2000.cpp +# test_crc8_darc.cpp +# test_crc8_dvbs2.cpp +# test_crc8_ebu.cpp +# test_crc8_icode.cpp +# test_crc8_itu.cpp +# test_crc8_j1850.cpp +# test_crc8_j1850_zero.cpp +# test_crc8_maxim.cpp +# test_crc8_rohc.cpp +# test_crc8_wcdma.cpp +# test_cyclic_value.cpp +# test_debounce.cpp +# test_delegate.cpp +# test_delegate_cpp03.cpp +# test_delegate_service.cpp +# test_delegate_service_compile_time.cpp +# test_delegate_service_cpp03.cpp +# test_deque.cpp +# test_endian.cpp +# test_enum_type.cpp +# test_error_handler.cpp +# test_etl_traits.cpp +# test_exception.cpp +# test_expected.cpp +# test_fixed_iterator.cpp +# test_fixed_sized_memory_block_allocator.cpp +# test_flags.cpp +# test_flat_map.cpp +# test_flat_multimap.cpp +# test_flat_multiset.cpp +# test_flat_set.cpp +# test_fnv_1.cpp +# test_format_spec.cpp +# test_forward_list.cpp +# test_forward_list_shared_pool.cpp +# test_fsm.cpp +# test_function.cpp +# test_functional.cpp +# test_gamma.cpp +# test_hash.cpp +# test_hfsm.cpp +# test_hfsm_recurse_to_inner_state_on_start.cpp +# test_histogram.cpp +# test_indirect_vector.cpp +# test_indirect_vector_external_buffer.cpp +# test_instance_count.cpp +# test_integral_limits.cpp +# test_intrusive_forward_list.cpp +# test_intrusive_links.cpp +# test_intrusive_list.cpp +# test_intrusive_queue.cpp +# test_intrusive_stack.cpp +# test_invert.cpp +# test_io_port.cpp +# test_iterator.cpp +# test_jenkins.cpp +# test_largest.cpp +# test_limiter.cpp +# test_limits.cpp +# test_list.cpp +# test_list_shared_pool.cpp +# test_macros.cpp +# test_make_string.cpp +# test_map.cpp +# test_math.cpp +# test_math_functions.cpp +# test_mean.cpp +# test_memory.cpp +# test_mem_cast.cpp +# test_mem_cast_ptr.cpp +# test_message.cpp +# test_message_broker.cpp +# test_message_bus.cpp +# test_message_packet.cpp +# test_message_router.cpp +# test_message_router_registry.cpp +# test_message_timer.cpp +# test_message_timer_atomic.cpp +# test_message_timer_interrupt.cpp +# test_message_timer_locked.cpp +# test_multimap.cpp +# test_multiset.cpp +# test_multi_array.cpp +# test_multi_range.cpp +# test_multi_span.cpp +# test_multi_vector.cpp +# test_murmur3.cpp +# test_nth_type.cpp +# test_numeric.cpp +# test_observer.cpp +# test_optional.cpp +# test_overload.cpp +# test_packet.cpp +# test_parameter_pack.cpp +# test_parameter_type.cpp +# test_parity_checksum.cpp +# test_pearson.cpp +# test_poly_span_dynamic_extent.cpp +# test_poly_span_fixed_extent.cpp +# test_pool.cpp +# test_pool_external_buffer.cpp +# test_priority_queue.cpp +# test_pseudo_moving_average.cpp +# test_quantize.cpp +# test_queue.cpp +# test_queue_lockable.cpp +# test_queue_lockable_small.cpp +# test_queue_memory_model_small.cpp +# test_queue_mpmc_mutex.cpp +# test_queue_mpmc_mutex_small.cpp +# test_queue_spsc_atomic.cpp +# test_queue_spsc_atomic_small.cpp +# test_queue_spsc_isr.cpp +# test_queue_spsc_isr_small.cpp +# test_queue_spsc_locked.cpp +# test_queue_spsc_locked_small.cpp +# test_random.cpp +# test_reference_flat_map.cpp +# test_reference_flat_multimap.cpp +# test_reference_flat_multiset.cpp +# test_reference_flat_set.cpp +# test_rescale.cpp +# test_result.cpp +# test_rms.cpp +# test_scaled_rounding.cpp +# test_set.cpp +# test_shared_message.cpp +# test_singleton.cpp +# test_smallest.cpp +# test_span_dynamic_extent.cpp +# test_span_fixed_extent.cpp +# test_stack.cpp +# test_standard_deviation.cpp +# test_state_chart.cpp +# test_state_chart_compile_time.cpp +# test_state_chart_compile_time_with_data_parameter.cpp +# test_state_chart_with_data_parameter.cpp +# test_state_chart_with_rvalue_data_parameter.cpp +# test_string_char.cpp +# test_string_char_external_buffer.cpp +# test_string_stream.cpp +# test_string_stream_u16.cpp +# test_string_stream_u32.cpp +# test_string_stream_u8.cpp +# test_string_stream_wchar_t.cpp +# test_string_u16.cpp +# test_string_u16_external_buffer.cpp +# test_string_u32.cpp +# test_string_u32_external_buffer.cpp +# test_string_u8.cpp +# test_string_u8_external_buffer.cpp +# test_string_utilities.cpp +# test_string_utilities_std.cpp +# test_string_utilities_std_u16.cpp +# test_string_utilities_std_u32.cpp +# test_string_utilities_std_u8.cpp +# test_string_utilities_std_wchar_t.cpp +# test_string_utilities_u16.cpp +# test_string_utilities_u32.cpp +# test_string_utilities_u8.cpp +# test_string_utilities_wchar_t.cpp +# test_string_view.cpp +# test_string_wchar_t.cpp +# test_string_wchar_t_external_buffer.cpp +# test_successor.cpp +# test_task_scheduler.cpp +# test_threshold.cpp +# test_to_arithmetic.cpp +# test_to_arithmetic_u16.cpp +# test_to_arithmetic_u32.cpp +# test_to_arithmetic_u8.cpp +# test_to_arithmetic_wchar_t.cpp +# test_to_string.cpp +# test_to_u16string.cpp +# test_to_u32string.cpp +# test_to_u8string.cpp +# test_to_wstring.cpp +# test_type_def.cpp +# test_type_lookup.cpp +# test_type_select.cpp +# test_type_traits.cpp +# test_unaligned_type.cpp +# test_unaligned_type_constexpr.cpp +# test_unordered_map.cpp +# test_unordered_multimap.cpp +# test_unordered_multiset.cpp +# test_unordered_set.cpp +# test_user_type.cpp +# test_utility.cpp +# test_variance.cpp +# test_variant_legacy.cpp +# test_variant_pool.cpp +# test_variant_pool_external_buffer.cpp +# test_variant_variadic.cpp +# test_vector.cpp +# test_vector_external_buffer.cpp +# test_vector_non_trivial.cpp +# test_vector_pointer.cpp +# test_vector_pointer_external_buffer.cpp +# test_visitor.cpp +# test_xor_checksum.cpp +# test_xor_rotate_checksum.cpp ) target_compile_definitions(etl_tests PRIVATE -DETL_DEBUG) diff --git a/test/cppcheck_macro_definitions.txt b/test/cppcheck_macro_definitions.txt new file mode 100644 index 00000000..3f2fb051 --- /dev/null +++ b/test/cppcheck_macro_definitions.txt @@ -0,0 +1,5 @@ +ETL_CONSTEXPR constexpr +ETL_CONSTEXPR14 +ETL_CONSTEXPR17 +ETL_CONSTEXPR20 +ETL_IF_CONSTEXPR20 \ No newline at end of file diff --git a/test/test_chrono_day.cpp b/test/test_chrono_day.cpp index 815cb4f4..7a9432a8 100644 --- a/test/test_chrono_day.cpp +++ b/test/test_chrono_day.cpp @@ -30,128 +30,112 @@ SOFTWARE. #include "etl/platform.h" -#if ETL_USING_CPP20 - #include "unit_test_framework.h" #include "etl/chrono.h" -#include -#include +#include #include namespace { + //************************************************************************* + bool is_day_ok(etl::chrono::day day) + { + unsigned d = unsigned(day); + + if ((d < 1) || (d > 31)) + { + return (day.ok() == false); + } + else + { + return (day.ok() == true); + } + } + SUITE(test_chrono_day) { //************************************************************************* TEST(test_default_constructor) { - std::chrono::day std_day; etl::chrono::day day; - CHECK_EQUAL(std_day.ok(), day.ok()); + CHECK_FALSE(day.ok()); } //************************************************************************* TEST(test_constructor_in_range) { - for (unsigned i = 0U; i < 256; ++i) + for (unsigned expected = 1U; expected < 31; ++expected) { - std::chrono::day std_day(i); - etl::chrono::day day(i); + etl::chrono::day day(expected); - CHECK_EQUAL(std_day.ok(), day.ok()); - CHECK_EQUAL(unsigned(std_day), unsigned(day)); + CHECK_TRUE(is_day_ok(day)); + CHECK_EQUAL(expected, unsigned(day)); } } //************************************************************************* TEST(test_pre_increment) { - std::chrono::day std_day(0); etl::chrono::day day(0); - for (int i = 0; i < 255; ++i) + for (int expected = 0; expected < 256; ++expected, ++day) { - ++std_day; - ++day; - - CHECK_EQUAL(std_day.ok(), day.ok()); - CHECK_EQUAL(unsigned(std_day), unsigned(day)); + CHECK_TRUE(is_day_ok(day)); + CHECK_EQUAL(expected, unsigned(day)); } } //************************************************************************* TEST(test_post_increment) { - std::chrono::day std_day(0); etl::chrono::day day(0); - for (int i = 0; i < 255; ++i) + for (int expected = 0; expected < 256; expected++, day++) { - std::chrono::day std_last_day = std_day++; - etl::chrono::day last_day = day++; - - CHECK_EQUAL(std_last_day.ok(), last_day.ok()); - CHECK_EQUAL(unsigned(std_last_day), unsigned(last_day)); - - CHECK_EQUAL(std_day.ok(), day.ok()); - CHECK_EQUAL(unsigned(std_day), unsigned(day)); + CHECK_TRUE(is_day_ok(day)); + CHECK_EQUAL(expected, unsigned(day)); } } //************************************************************************* TEST(test_pre_decrement) { - std::chrono::day std_day(256); - etl::chrono::day day(256); + etl::chrono::day day(255); - for (int i = 0; i < 255; ++i) + for (int expected = 255; expected > 0; --expected, --day) { - --std_day; - --day; - - CHECK_EQUAL(std_day.ok(), day.ok()); - CHECK_EQUAL(unsigned(std_day), unsigned(day)); + CHECK_TRUE(is_day_ok(day)); + CHECK_EQUAL(expected, unsigned(day)); } } //************************************************************************* TEST(test_post_decrement) { - std::chrono::day std_day(256); - etl::chrono::day day(256); + etl::chrono::day day(255); - for (int i = 0; i < 255; ++i) + for (int expected = 255; expected > 0; expected--, day--) { - std::chrono::day std_last_day = std_day--; - etl::chrono::day last_day = day--; - - CHECK_EQUAL(std_last_day.ok(), last_day.ok()); - CHECK_EQUAL(unsigned(std_last_day), unsigned(last_day)); - - CHECK_EQUAL(std_day.ok(), day.ok()); - CHECK_EQUAL(unsigned(std_day), unsigned(day)); + CHECK_TRUE(is_day_ok(day)); + CHECK_EQUAL(expected, unsigned(day)); } } //************************************************************************* TEST(test_plus_equal_days) { - std::chrono::day std_day(0); etl::chrono::day day(0); - - std::chrono::days std_days(2); etl::chrono::days days(2); - for (int i = 0; i < 128; ++i) + for (int expected = 2; expected < 256; expected += 2) { - std_day += std_days; - day += days; + day += days; - CHECK_EQUAL(std_day.ok(), day.ok()); - CHECK_EQUAL(unsigned(std_day), unsigned(day)); + CHECK_TRUE(is_day_ok(day)); + CHECK_EQUAL(expected, unsigned(day)); } } @@ -162,17 +146,15 @@ namespace { for (int ds = 0; ds < 256; ++ds) { - std::chrono::day std_day(d); etl::chrono::day day(d); - - std::chrono::days std_days(ds); etl::chrono::days days(ds); - std_day = std_day + std_days; - day = day + days; + day = day + days; - CHECK_EQUAL(std_day.ok(), day.ok()); - CHECK_EQUAL(unsigned(std_day), unsigned(day)); + unsigned expected = (d + ds) % 256; + + CHECK_TRUE(is_day_ok(day)); + CHECK_EQUAL(expected, unsigned(day)); } } } @@ -182,19 +164,17 @@ namespace { for (int d = 0; d < 256; ++d) { - for (int ds = 0; ds < 256; ++ds) + for (int ds = 0; ds < d; ++ds) { - std::chrono::day std_day(d); etl::chrono::day day(d); - - std::chrono::days std_days(ds); etl::chrono::days days(ds); - std_day = std_days + std_day; - day = days + day; + day = days + day; - CHECK_EQUAL(std_day.ok(), day.ok()); - CHECK_EQUAL(unsigned(std_day), unsigned(day)); + unsigned expected = (d + ds) % 256; + + CHECK_TRUE(is_day_ok(day)); + CHECK_EQUAL(expected, unsigned(day)); } } } @@ -202,66 +182,47 @@ namespace //************************************************************************* TEST(test_minus_equal_days) { - for (int d = 0; d <= 256; ++d) + etl::chrono::day day(255); + etl::chrono::days days(2); + + for (int expected = 253; expected > 0; expected -= 2) { - for (int ds = 0; ds <= 256; ++ds) - { - std::chrono::day std_day(d); - etl::chrono::day day(d); + day -= days; - std::chrono::days std_days(ds); - etl::chrono::days days(ds); - - std_day -= std_days; - day -= days; - - CHECK_EQUAL(std_day.ok(), day.ok()); - CHECK_EQUAL(unsigned(std_day), unsigned(day)); - } + CHECK_TRUE(is_day_ok(day)); + CHECK_EQUAL(expected, unsigned(day)); } } //************************************************************************* TEST(test_day_minus_days) { - for (int d = 0; d <= 256; ++d) + etl::chrono::day day(255); + etl::chrono::days days(2); + + for (int expected = 253; expected > 0; expected -= 2) { - for (int ds = 0; ds <= 256; ++ds) - { - std::chrono::day std_day(d); - etl::chrono::day day(d); + day = day - days; - std::chrono::days std_days(ds); - etl::chrono::days days(ds); - - std_day = std_day - std_days; - day = day - days; - - CHECK_EQUAL(std_day.ok(), day.ok()); - CHECK_EQUAL(unsigned(std_day), unsigned(day)); - } + CHECK_TRUE(is_day_ok(day)); + CHECK_EQUAL(expected, unsigned(day)); } } //************************************************************************* TEST(test_day_minus_day) { - for (int d = 0; d < 256; ++d) + for (int d1 = 0; d1 < 256; ++d1) { - std::chrono::day std_day1(d); - std::chrono::day std_day2(255 - d); + for (int d2 = 0; d2 < 256; ++d2) + { + etl::chrono::day day1(d1); + etl::chrono::day day2(d2); - std::chrono::day day1(d); - std::chrono::day day2(255 - d); - - auto std_days12 = std_day1 - std_day2; - auto std_days21 = std_day2 - std_day1; - - auto days12 = day1 - day2; - auto days21 = day2 - day1; - - CHECK_EQUAL(std_days12.count(), days12.count()); - CHECK_EQUAL(std_days21.count(), days21.count()); + etl::chrono::days result_days = day1 - day2; + int expected_days = d1 - d2; + CHECK_EQUAL(expected_days, result_days.count()); + } } } @@ -275,14 +236,12 @@ namespace //************************************************************************* TEST(test_literal_day) { - using namespace std::literals::chrono_literals; using namespace etl::literals::chrono_literals; - std::chrono::day std_day = 25d; - etl::chrono::day day = 25_day; + etl::chrono::day day = 25_day; - CHECK_EQUAL(std_day.ok(), day.ok()); - CHECK_EQUAL(unsigned(std_day), unsigned(day)); + CHECK_TRUE(day.ok()); + CHECK_EQUAL(25, unsigned(day)); } //************************************************************************* @@ -329,5 +288,3 @@ namespace } }; } - -#endif \ No newline at end of file diff --git a/test/test_chrono_month_day.cpp b/test/test_chrono_month_day.cpp new file mode 100644 index 00000000..e1e0a5d8 --- /dev/null +++ b/test/test_chrono_month_day.cpp @@ -0,0 +1,384 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2024 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include +#include +#include + +#if ETL_USING_CPP20 + +namespace +{ + SUITE(test_chrono_month_day) + { + //************************************************************************* + TEST(test_default_constructor) + { + etl::chrono::month_day md; + + CHECK_FALSE(md.ok()); + } + + //************************************************************************* + TEST(test_constructor_in_range) + { + for (unsigned i = 0U; i < 256; ++i) + { + std::chrono::month std_month(i); + etl::chrono::month month(i); + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + + //************************************************************************* + TEST(test_pre_increment) + { + std::chrono::month std_month(0); + etl::chrono::month month(0); + + for (int i = 0; i < 255; ++i) + { + ++std_month; + ++month; + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + + //************************************************************************* + TEST(test_post_increment) + { + std::chrono::month std_month(0); + etl::chrono::month month(0); + + for (int i = 0; i < 256; ++i) + { + std::chrono::month std_last_month = std_month++; + etl::chrono::month last_month = month++; + + CHECK_EQUAL(std_last_month.ok(), last_month.ok()); + CHECK_EQUAL(unsigned(std_last_month), unsigned(last_month)); + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + + //************************************************************************* + TEST(test_pre_decrement) + { + std::chrono::month std_month(255); + etl::chrono::month month(255); + + for (int i = 0; i < 256; ++i) + { + --std_month; + --month; + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + + //************************************************************************* + TEST(test_post_decrement) + { + std::chrono::month std_month(255); + etl::chrono::month month(255); + + for (int i = 0; i < 256; ++i) + { + std::chrono::month std_last_month = std_month--; + etl::chrono::month last_month = month--; + + CHECK_EQUAL(std_last_month.ok(), last_month.ok()); + CHECK_EQUAL(unsigned(std_last_month), unsigned(last_month)); + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + + //************************************************************************* + TEST(test_plus_equal_months) + { + for (int m = 0; m <= 12; ++m) + { + for (int ms = 0; ms <= 24; ++ms) + { + std::chrono::month std_month(m); + etl::chrono::month month(m); + + std::chrono::months std_months(ms); + etl::chrono::months months(ms); + + std_month += std_months; + month += months; + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + } + + //************************************************************************* + TEST(test_month_plus_months) + { + for (int m = 0; m <= 12; ++m) + { + for (int ms = 0; ms <= 24; ++ms) + { + std::chrono::month std_month(m); + etl::chrono::month month(m); + + std::chrono::months std_months(ms); + etl::chrono::months months(ms); + + std_month = std_month + std_months; + month = month + months; + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + } + + //************************************************************************* + TEST(test_months_plus_month) + { + for (int m = 0; m <= 12; ++m) + { + for (int ms = 0; ms <= 24; ++ms) + { + std::chrono::month std_month(m); + etl::chrono::month month(m); + + std::chrono::months std_months(ms); + etl::chrono::months months(ms); + + std_month = std_months + std_month; + month = months + month; + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + } + + //************************************************************************* + TEST(test_minus_equal_months) + { + for (int m = 0; m <= 12; ++m) + { + for (int ms = 0; ms <= 24; ++ms) + { + std::chrono::month std_month(m); + etl::chrono::month month(m); + + std::chrono::months std_months(ms); + etl::chrono::months months(ms); + + std_month -= std_months; + month -= months; + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + } + + //************************************************************************* + TEST(test_month_minus_months) + { + for (int m = 0; m <= 12; ++m) + { + for (int ms = 0; ms <= 24; ++ms) + { + std::chrono::month std_month(m); + etl::chrono::month month(m); + + std::chrono::months std_months(ms); + etl::chrono::months months(ms); + + std_month = std_month - std_months; + month = month - months; + + CHECK_EQUAL(std_month.ok(), month.ok()); + CHECK_EQUAL(unsigned(std_month), unsigned(month)); + } + } + } + + //************************************************************************* + TEST(test_month_minus_month) + { + for (int m = 0; m < 256; ++m) + { + std::chrono::month std_month1(m); + std::chrono::month std_month2(255 - m); + + std::chrono::month month1(m); + std::chrono::month month2(255 - m); + + auto std_months12 = std_month1 - std_month2; + auto std_months21 = std_month2 - std_month1; + + auto months12 = month1 - month2; + auto months21 = month2 - month1; + + CHECK_EQUAL(std_months12.count(), months12.count()); + CHECK_EQUAL(std_months21.count(), months21.count()); + } + } + + //************************************************************************* + TEST(test_min_max_month) + { + CHECK_EQUAL(1U, etl::chrono::month::min()); + CHECK_EQUAL(12U, etl::chrono::month::max()); + } + + //************************************************************************* + TEST(test_literal_month) + { + using namespace etl::literals::chrono_literals; + + etl::chrono::month month1 = 1_month; + etl::chrono::month month2 = 2_month; + etl::chrono::month month3 = 3_month; + etl::chrono::month month4 = 4_month; + etl::chrono::month month5 = 5_month; + etl::chrono::month month6 = 6_month; + etl::chrono::month month7 = 7_month; + etl::chrono::month month8 = 8_month; + etl::chrono::month month9 = 9_month; + etl::chrono::month month10 = 10_month; + etl::chrono::month month11 = 11_month; + etl::chrono::month month12 = 12_month; + + CHECK_TRUE(month1.ok()); + CHECK_TRUE(month2.ok()); + CHECK_TRUE(month3.ok()); + CHECK_TRUE(month4.ok()); + CHECK_TRUE(month5.ok()); + CHECK_TRUE(month6.ok()); + CHECK_TRUE(month7.ok()); + CHECK_TRUE(month8.ok()); + CHECK_TRUE(month9.ok()); + CHECK_TRUE(month10.ok()); + CHECK_TRUE(month11.ok()); + CHECK_TRUE(month12.ok()); + + CHECK_EQUAL(1U, unsigned(month1)); + CHECK_EQUAL(2U, unsigned(month2)); + CHECK_EQUAL(3U, unsigned(month3)); + CHECK_EQUAL(4U, unsigned(month4)); + CHECK_EQUAL(5U, unsigned(month5)); + CHECK_EQUAL(6U, unsigned(month6)); + CHECK_EQUAL(7U, unsigned(month7)); + CHECK_EQUAL(8U, unsigned(month8)); + CHECK_EQUAL(9U, unsigned(month9)); + CHECK_EQUAL(10U, unsigned(month10)); + CHECK_EQUAL(11U, unsigned(month11)); + CHECK_EQUAL(12U, unsigned(month12)); + } + + //************************************************************************* + TEST(test_month_comparison_operators) + { + etl::chrono::month month1(1); + etl::chrono::month month2(2); + + CHECK_TRUE(month1 == month1); + CHECK_FALSE(month1 != month1); + CHECK_TRUE(month1 < month2); + CHECK_FALSE(month1 < month1); + CHECK_FALSE(month2 < month1); + CHECK_TRUE(month1 <= month2); + CHECK_TRUE(month1 <= month1); + CHECK_FALSE(month2 <= month1); + CHECK_FALSE(month1 > month2); + CHECK_FALSE(month1 > month1); + CHECK_TRUE(month2 > month1); + CHECK_FALSE(month1 >= month2); + CHECK_TRUE(month1 >= month1); + CHECK_TRUE(month2 >= month1); + +#if ETL_USING_CPP20 + CHECK_TRUE((month1 <=> month1) == 0); + CHECK_TRUE((month1 <=> month2) < 0); + CHECK_TRUE((month2 <=> month1) > 0); +#endif + } + + //************************************************************************* + TEST(test_month_hashes_are_unique) + { + std::vector hashes; + + for (int i = 0; i < 256; ++i) + { + hashes.push_back(etl::hash()(etl::chrono::month(i))); + } + + std::sort(hashes.begin(), hashes.end()); + (void)std::unique(hashes.begin(), hashes.end()); + CHECK_EQUAL(256U, hashes.size()); + } + + //************************************************************************* + TEST(test_month_types) + { + CHECK_EQUAL(static_cast(std::chrono::January), static_cast(etl::chrono::January)); + CHECK_EQUAL(static_cast(std::chrono::February), static_cast(etl::chrono::February)); + CHECK_EQUAL(static_cast(std::chrono::March), static_cast(etl::chrono::March)); + CHECK_EQUAL(static_cast(std::chrono::April), static_cast(etl::chrono::April)); + CHECK_EQUAL(static_cast(std::chrono::May), static_cast(etl::chrono::May)); + CHECK_EQUAL(static_cast(std::chrono::June), static_cast(etl::chrono::June)); + CHECK_EQUAL(static_cast(std::chrono::July), static_cast(etl::chrono::July)); + CHECK_EQUAL(static_cast(std::chrono::August), static_cast(etl::chrono::August)); + CHECK_EQUAL(static_cast(std::chrono::September), static_cast(etl::chrono::September)); + CHECK_EQUAL(static_cast(std::chrono::October), static_cast(etl::chrono::October)); + CHECK_EQUAL(static_cast(std::chrono::November), static_cast(etl::chrono::November)); + CHECK_EQUAL(static_cast(std::chrono::December), static_cast(etl::chrono::December)); + } + }; +} + +#endif \ No newline at end of file diff --git a/test/test_chrono_weekday.cpp b/test/test_chrono_weekday.cpp index c4cbe05d..132160ec 100644 --- a/test/test_chrono_weekday.cpp +++ b/test/test_chrono_weekday.cpp @@ -36,6 +36,7 @@ SOFTWARE. #include +#include #include #include @@ -262,6 +263,7 @@ namespace } } +#if ETL_USING_CPP20 //************************************************************************* TEST(test_weekday_minus_weekday) { @@ -283,6 +285,7 @@ namespace CHECK_EQUAL(std_days21.count(), days21.count()); } } +#endif //************************************************************************* TEST(test_min_max_weekday) diff --git a/test/test_chrono_weekday_indexed.cpp b/test/test_chrono_weekday_indexed.cpp index faa55596..e690fc96 100644 --- a/test/test_chrono_weekday_indexed.cpp +++ b/test/test_chrono_weekday_indexed.cpp @@ -36,6 +36,7 @@ SOFTWARE. #include +#include #include #include diff --git a/test/test_chrono_weekday_last.cpp b/test/test_chrono_weekday_last.cpp index 09c8f8d6..e2787a2e 100644 --- a/test/test_chrono_weekday_last.cpp +++ b/test/test_chrono_weekday_last.cpp @@ -36,6 +36,7 @@ SOFTWARE. #include +#include #include #include diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 1ce125eb..8c275868 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -3096,6 +3096,8 @@ + + @@ -7959,6 +7961,7 @@ + @@ -9084,6 +9087,7 @@ + true true diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 69327b6f..1fb6e5fc 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -1449,6 +1449,12 @@ ETL\Private + + ETL\Private\chrono + + + ETL\Private\chrono + @@ -3446,6 +3452,9 @@ Tests\Misc + + Tests\Chrono + @@ -3648,6 +3657,9 @@ Tests\Syntax Checks\Source + + Tests\Test Support + diff --git a/test/vs2022/etl_solution_suppressions.cfg b/test/vs2022/etl_solution_suppressions.cfg new file mode 100644 index 00000000..f76caa4c --- /dev/null +++ b/test/vs2022/etl_solution_suppressions.cfg @@ -0,0 +1,4 @@ +[cppcheck] +-i*.cpp +[cppcheck_files] +[cppcheck_includes] From a27aa2a556fc94eb7d5e122feccea01b6c45a9ab Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 20 Apr 2025 13:33:30 +0100 Subject: [PATCH 17/33] Full etl:chrono::duration implementation and unit tests --- include/etl/private/chrono/duration.h | 158 ++++++ test/test_chrono_duration.cpp | 684 ++++++++++++++++++++++++-- 2 files changed, 794 insertions(+), 48 deletions(-) diff --git a/include/etl/private/chrono/duration.h b/include/etl/private/chrono/duration.h index 10c79460..3160ab18 100644 --- a/include/etl/private/chrono/duration.h +++ b/include/etl/private/chrono/duration.h @@ -185,6 +185,40 @@ namespace etl return etl::chrono::duration(etl::chrono::duration_values::max()); } + //*********************************************************************** + ETL_CONSTEXPR duration& operator ++() + { + ++value; + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR duration operator ++(int) + { + duration temp(*this); + ++value; + + return temp; + } + + //*********************************************************************** + ETL_CONSTEXPR duration& operator --() + { + --value; + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR duration operator --(int) + { + duration temp(*this); + --value; + + return temp; + } + private: TRep value; @@ -353,6 +387,130 @@ namespace etl { return !(lhs < rhs); } + + //*********************************************************************** + /// Operator + + //*********************************************************************** + template + ETL_CONSTEXPR14 typename etl::common_type, etl::chrono::duration >::type + operator +(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + { + // Determine the common type of the two durations. + using common_duration = typename etl::common_type, etl::chrono::duration>::type; + + // Convert both durations to the common type. + common_duration lhs_converted = etl::chrono::duration_cast(lhs); + common_duration rhs_converted = etl::chrono::duration_cast(rhs); + + // Return the sum of the two converted durations. + return common_duration(lhs_converted.count() + rhs_converted.count()); + } + + //*********************************************************************** + /// Operator - + //*********************************************************************** + template + ETL_CONSTEXPR14 typename etl::common_type, etl::chrono::duration >::type + operator -(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + { + // Determine the common type of the two durations. + using common_duration = typename etl::common_type, etl::chrono::duration>::type; + + // Convert both durations to the common type. + common_duration lhs_converted = etl::chrono::duration_cast(lhs); + common_duration rhs_converted = etl::chrono::duration_cast(rhs); + + // Return the sum of the two converted durations. + return common_duration(lhs_converted.count() - rhs_converted.count()); + } + + //*********************************************************************** + /// Operator * + //*********************************************************************** + template + ETL_CONSTEXPR14 etl::chrono::duration::type, TPeriod1> + operator *(const etl::chrono::duration& lhs, const TRep2& rhs) + { + using common_rep = typename etl::common_type::type; + using result_duration = etl::chrono::duration; + + // Multiply the count of the duration by the scalar value + return result_duration(static_cast(lhs.count()) * static_cast(rhs)); + } + + //*********************************************************************** + /// Operator * + //*********************************************************************** + template + ETL_CONSTEXPR14 etl::chrono::duration::type, TPeriod2> + operator *(const TRep1& lhs, const etl::chrono::duration& rhs) + { + using common_rep = typename etl::common_type::type; + using result_duration = etl::chrono::duration; + + // Multiply the count of the duration by the scalar value + return result_duration(static_cast(rhs.count()) * static_cast(lhs)); + } + + //*********************************************************************** + /// Operator / + //*********************************************************************** + template + ETL_CONSTEXPR14 etl::chrono::duration::type, TPeriod1> + operator /(const etl::chrono::duration& lhs, const TRep2& rhs) + { + using common_rep = typename etl::common_type::type; + using result_duration = etl::chrono::duration; + + // Multiply the count of the duration by the scalar value + return result_duration(static_cast(lhs.count()) / static_cast(rhs)); + } + + //*********************************************************************** + /// Operator / + //*********************************************************************** + template + ETL_CONSTEXPR14 typename etl::common_type::type + operator /(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + { + // Determine the common type of the two durations. + using common_duration = typename etl::common_type, etl::chrono::duration>::type; + + common_duration lhs_converted = etl::chrono::duration_cast(lhs); + common_duration rhs_converted = etl::chrono::duration_cast(rhs); + + return typename etl::common_type::type(lhs_converted.count() / rhs_converted.count()); + } + + //*********************************************************************** + /// Operator % + //*********************************************************************** + template + ETL_CONSTEXPR14 etl::chrono::duration::type, TPeriod1> + operator %(const etl::chrono::duration& lhs, const TRep2& rhs) + { + using common_rep = typename etl::common_type::type; + using result_duration = etl::chrono::duration; + + // Mod the count of the duration by the scalar value + return result_duration(static_cast(lhs.count()) % static_cast(rhs)); + } + + //*********************************************************************** + /// Operator % + //*********************************************************************** + template + ETL_CONSTEXPR14 typename etl::common_type::type + operator %(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + { + // Determine the common type of the two durations. + using common_duration = typename etl::common_type, etl::chrono::duration>::type; + + common_duration lhs_converted = etl::chrono::duration_cast(lhs); + common_duration rhs_converted = etl::chrono::duration_cast(rhs); + + return typename etl::common_type::type(lhs_converted.count() % rhs_converted.count()); + } } #if ETL_HAS_CHRONO_LITERALS_DURATION diff --git a/test/test_chrono_duration.cpp b/test/test_chrono_duration.cpp index f20ed3fc..f97a606a 100644 --- a/test/test_chrono_duration.cpp +++ b/test/test_chrono_duration.cpp @@ -38,7 +38,20 @@ SOFTWARE. #include #include #include -#include + +// Set to 0 to reference against std::chrono +#define ETL_USING_ETL_CHRONO 1 + +#if ETL_USING_ETL_CHRONO + #define Chrono etl::chrono +#else + #if ETL_USING_CPP20 + #include + #define Chrono std::chrono + #else + #error std::chrono not supported + #endif +#endif namespace { @@ -47,7 +60,7 @@ namespace //************************************************************************* TEST(test_default_constructor) { - using duration_type = etl::chrono::duration; + using duration_type = Chrono::duration; duration_type duration; @@ -59,7 +72,7 @@ namespace //************************************************************************* TEST(test_duration_values_zero_min_max) { - using duration_values_type = etl::chrono::duration_values; + using duration_values_type = Chrono::duration_values; CHECK_EQUAL(size_t(0), duration_values_type::zero()); CHECK_EQUAL(std::numeric_limits::min(), duration_values_type::min()); @@ -69,7 +82,7 @@ namespace //************************************************************************* TEST(test_duration_zero_min_max) { - using duration_type = etl::chrono::duration; + using duration_type = Chrono::duration; CHECK_EQUAL(duration_type(0).count(), duration_type::zero().count()); CHECK_EQUAL(duration_type(std::numeric_limits::min()).count(), duration_type::min().count()); @@ -79,45 +92,45 @@ namespace //************************************************************************* TEST(test_predefined_duration_periods) { - CHECK_EQUAL((etl::ratio<1U, 1000000000U>::type::num), etl::chrono::nanoseconds::period::num); - CHECK_EQUAL((etl::ratio<1U, 1000000000U>::type::den), etl::chrono::nanoseconds::period::den); + CHECK_EQUAL((etl::ratio<1U, 1000000000U>::type::num), Chrono::nanoseconds::period::num); + CHECK_EQUAL((etl::ratio<1U, 1000000000U>::type::den), Chrono::nanoseconds::period::den); - CHECK_EQUAL((etl::ratio<1U, 1000000U>::type::num), etl::chrono::microseconds::period::num); - CHECK_EQUAL((etl::ratio<1U, 1000000U>::type::den), etl::chrono::microseconds::period::den); + CHECK_EQUAL((etl::ratio<1U, 1000000U>::type::num), Chrono::microseconds::period::num); + CHECK_EQUAL((etl::ratio<1U, 1000000U>::type::den), Chrono::microseconds::period::den); - CHECK_EQUAL((etl::ratio<1U, 1000U>::type::num), etl::chrono::milliseconds::period::num); - CHECK_EQUAL((etl::ratio<1U, 1000U>::type::den), etl::chrono::milliseconds::period::den); + CHECK_EQUAL((etl::ratio<1U, 1000U>::type::num), Chrono::milliseconds::period::num); + CHECK_EQUAL((etl::ratio<1U, 1000U>::type::den), Chrono::milliseconds::period::den); - CHECK_EQUAL(etl::ratio<1U>::type::num, etl::chrono::seconds::period::num); - CHECK_EQUAL(etl::ratio<1U>::type::den, etl::chrono::seconds::period::den); + CHECK_EQUAL(etl::ratio<1U>::type::num, Chrono::seconds::period::num); + CHECK_EQUAL(etl::ratio<1U>::type::den, Chrono::seconds::period::den); - CHECK_EQUAL(etl::ratio<60U>::type::num, etl::chrono::minutes::period::num); - CHECK_EQUAL(etl::ratio<60U>::type::den, etl::chrono::minutes::period::den); + CHECK_EQUAL(etl::ratio<60U>::type::num, Chrono::minutes::period::num); + CHECK_EQUAL(etl::ratio<60U>::type::den, Chrono::minutes::period::den); - CHECK_EQUAL(etl::ratio<3600U>::type::num, etl::chrono::hours::period::num); - CHECK_EQUAL(etl::ratio<3600U>::type::den, etl::chrono::hours::period::den); + CHECK_EQUAL(etl::ratio<3600U>::type::num, Chrono::hours::period::num); + CHECK_EQUAL(etl::ratio<3600U>::type::den, Chrono::hours::period::den); - CHECK_EQUAL(etl::ratio<86400U>::type::num, etl::chrono::days::period::num); - CHECK_EQUAL(etl::ratio<86400U>::type::den, etl::chrono::days::period::den); + CHECK_EQUAL(etl::ratio<86400U>::type::num, Chrono::days::period::num); + CHECK_EQUAL(etl::ratio<86400U>::type::den, Chrono::days::period::den); - CHECK_EQUAL(etl::ratio<604800U>::type::num, etl::chrono::weeks::period::num); - CHECK_EQUAL(etl::ratio<604800U>::type::den, etl::chrono::weeks::period::den); + CHECK_EQUAL(etl::ratio<604800U>::type::num, Chrono::weeks::period::num); + CHECK_EQUAL(etl::ratio<604800U>::type::den, Chrono::weeks::period::den); - CHECK_EQUAL(etl::ratio<604800U>::type::num, etl::chrono::weeks::period::num); - CHECK_EQUAL(etl::ratio<604800U>::type::den, etl::chrono::weeks::period::den); + CHECK_EQUAL(etl::ratio<604800U>::type::num, Chrono::weeks::period::num); + CHECK_EQUAL(etl::ratio<604800U>::type::den, Chrono::weeks::period::den); - CHECK_EQUAL(etl::ratio<2629746U>::type::num, etl::chrono::months::period::num); - CHECK_EQUAL(etl::ratio<2629746U>::type::den, etl::chrono::months::period::den); + CHECK_EQUAL(etl::ratio<2629746U>::type::num, Chrono::months::period::num); + CHECK_EQUAL(etl::ratio<2629746U>::type::den, Chrono::months::period::den); - CHECK_EQUAL(etl::ratio<31556952U>::type::num, etl::chrono::years::period::num); - CHECK_EQUAL(etl::ratio<31556952U>::type::den, etl::chrono::years::period::den); + CHECK_EQUAL(etl::ratio<31556952U>::type::num, Chrono::years::period::num); + CHECK_EQUAL(etl::ratio<31556952U>::type::den, Chrono::years::period::den); } //************************************************************************* TEST(test_duration_common_type) { - using duration_type1 = etl::chrono::duration; - using duration_type2 = etl::chrono::duration; + using duration_type1 = Chrono::duration; + using duration_type2 = Chrono::duration; using duration_type = etl::common_type::type; @@ -128,11 +141,11 @@ namespace //************************************************************************* TEST(test_duration_cast_with_same_rep_and_period_for_duration_type1_and_duration_type2) { - using duration_type1 = etl::chrono::duration; - using duration_type2 = etl::chrono::duration>; + using duration_type1 = Chrono::duration; + using duration_type2 = Chrono::duration>; duration_type1 dur1(245); - duration_type2 dur2 = etl::chrono::duration_cast(dur1); + duration_type2 dur2 = Chrono::duration_cast(dur1); CHECK_EQUAL(duration_type1::period::num, duration_type2::period::num); CHECK_EQUAL(duration_type1::period::den, duration_type2::period::den); @@ -142,11 +155,11 @@ namespace //************************************************************************* TEST(test_duration_cast_where_ratio_divide_of_periods_num_is_1) { - using duration_type1 = etl::chrono::duration; - using duration_type2 = etl::chrono::duration; + using duration_type1 = Chrono::duration; + using duration_type2 = Chrono::duration; duration_type1 dur1(245000); - duration_type2 dur2 = etl::chrono::duration_cast(dur1); + duration_type2 dur2 = Chrono::duration_cast(dur1); typedef typename etl::ratio_divide::type ratio_divide_t; @@ -159,11 +172,11 @@ namespace //************************************************************************* TEST(test_duration_cast_where_ratio_divide_of_periods_den_is_1) { - using duration_type1 = etl::chrono::duration; - using duration_type2 = etl::chrono::duration; + using duration_type1 = Chrono::duration; + using duration_type2 = Chrono::duration; duration_type1 dur1(245); - duration_type2 dur2 = etl::chrono::duration_cast(dur1); + duration_type2 dur2 = Chrono::duration_cast(dur1); typedef typename etl::ratio_divide::type ratio_divide_t; @@ -176,11 +189,11 @@ namespace //************************************************************************* TEST(test_duration_cast_when_rep_and_period_are_not_equal_and_ratio_divide_of_periods_num_and_den_are_not_1) { - using duration_type1 = etl::chrono::duration>; - using duration_type2 = etl::chrono::duration>; + using duration_type1 = Chrono::duration>; + using duration_type2 = Chrono::duration>; duration_type1 dur1(245); - duration_type2 dur2 = etl::chrono::duration_cast(dur1); + duration_type2 dur2 = Chrono::duration_cast(dur1); typedef typename etl::ratio_divide::type ratio_divide_t; @@ -196,12 +209,12 @@ namespace int Two_Hours = 2; int Four_Hours = 4; - etl::chrono::hours hours1(Two_Hours); - etl::chrono::hours hours2(Four_Hours); - etl::chrono::seconds seconds(0); + Chrono::hours hours1(Two_Hours); + Chrono::hours hours2(Four_Hours); + Chrono::seconds seconds(0); seconds = hours1; - int seconds_per_hour = etl::chrono::hours::period::num / etl::chrono::seconds::period::num; + int seconds_per_hour = Chrono::hours::period::num / Chrono::seconds::period::num; CHECK_EQUAL(seconds.count(), hours1.count() * seconds_per_hour); CHECK_EQUAL(Two_Hours, hours1.count()); @@ -213,8 +226,8 @@ namespace //************************************************************************* TEST(test_duration_comparison_operators) { - using duration_type1 = etl::chrono::duration; - using duration_type2 = etl::chrono::duration; + using duration_type1 = Chrono::duration; + using duration_type2 = Chrono::duration; duration_type1 dur1a(245); duration_type1 dur1b(245); @@ -267,7 +280,7 @@ namespace //************************************************************************* TEST(test_duration_unary_operators) { - using duration_type = etl::chrono::duration; + using duration_type = Chrono::duration; duration_type dur(245); @@ -281,7 +294,7 @@ namespace //************************************************************************* TEST(test_duration_hashes_are_unique) { - using duration_type = etl::chrono::duration; + using duration_type = Chrono::duration; std::vector hashes; @@ -294,5 +307,580 @@ namespace (void)std::unique(hashes.begin(), hashes.end()); CHECK_EQUAL(256U, hashes.size()); } + + //************************************************************************* + TEST(test_duration_pre_increment) + { + Chrono::hours hours(0); + Chrono::minutes minutes(0); + Chrono::seconds seconds(0); + + for (int i = 1; i < 100; ++i) + { + ++hours; + ++minutes; + ++seconds; + + CHECK_EQUAL(i, hours.count()); + CHECK_EQUAL(i, minutes.count()); + CHECK_EQUAL(i, seconds.count()); + } + } + + //************************************************************************* + TEST(test_duration_post_increment) + { + Chrono::hours hours(0); + Chrono::minutes minutes(0); + Chrono::seconds seconds(0); + + for (int i = 1; i < 100; ++i) + { + Chrono::hours last_hours = hours++; + Chrono::minutes last_minutes = minutes++; + Chrono::seconds last_seconds = seconds++; + + CHECK_EQUAL(i - 1, last_hours.count()); + CHECK_EQUAL(i - 1, last_minutes.count()); + CHECK_EQUAL(i - 1, last_seconds.count()); + + CHECK_EQUAL(i, hours.count()); + CHECK_EQUAL(i, minutes.count()); + CHECK_EQUAL(i, seconds.count()); + } + } + + //************************************************************************* + TEST(test_duration_pre_decrement) + { + Chrono::hours hours(101); + Chrono::minutes minutes(101); + Chrono::seconds seconds(101); + + for (int i = 100; i > 0; --i) + { + --hours; + --minutes; + --seconds; + + CHECK_EQUAL(i, hours.count()); + CHECK_EQUAL(i, minutes.count()); + CHECK_EQUAL(i, seconds.count()); + } + } + + //************************************************************************* + TEST(test_duration_post_decrement) + { + Chrono::hours hours(101); + Chrono::minutes minutes(101); + Chrono::seconds seconds(101); + + for (int i = 100; i > 0; --i) + { + Chrono::hours last_hours = hours--; + Chrono::minutes last_minutes = minutes--; + Chrono::seconds last_seconds = seconds--; + + CHECK_EQUAL(i + 1, last_hours.count()); + CHECK_EQUAL(i + 1, last_minutes.count()); + CHECK_EQUAL(i + 1, last_seconds.count()); + + CHECK_EQUAL(i, hours.count()); + CHECK_EQUAL(i, minutes.count()); + CHECK_EQUAL(i, seconds.count()); + } + } + + //************************************************************************* + TEST(test_addition_same_type) + { + Chrono::seconds s1(10); // 10 seconds + Chrono::seconds s2(20); // 20 seconds + + auto result = s1 + s2; + + CHECK_EQUAL(30, result.count()); // 10 + 20 = 30 seconds + } + + //************************************************************************* + TEST(test_addition_different_types) + { + Chrono::seconds s1(10); // 10 seconds + Chrono::milliseconds ms1(500); // 500 milliseconds + + auto result = s1 + ms1; + + // Result should be in the common type (milliseconds) + CHECK_EQUAL(10500, result.count()); // 10 seconds + 500 milliseconds = 10500 milliseconds + } + + //************************************************************************* + TEST(test_addition_with_zero) + { + Chrono::seconds s1(10); // 10 seconds + Chrono::seconds s2(0); // 0 seconds + + auto result = s1 + s2; + + CHECK_EQUAL(10, result.count()); // 10 + 0 = 10 seconds + } + + //************************************************************************* + TEST(test_addition_negative_duration) + { + Chrono::seconds s1(10); // 10 seconds + Chrono::seconds s2(-5); // -5 seconds + + auto result = s1 + s2; + + CHECK_EQUAL(5, result.count()); // 10 + (-5) = 5 seconds + } + + //************************************************************************* + TEST(test_addition_large_values) + { + Chrono::seconds s1(1000000); // 1,000,000 seconds + Chrono::milliseconds ms1(500000); // 500,000 milliseconds + + auto result = s1 + ms1; + + // Result should be in the common type (milliseconds) + CHECK_EQUAL(1000500000, result.count()); // 1,000,000 seconds + 500,000 milliseconds = 1,000,500,000 milliseconds + } + + //************************************************************************* + TEST(test_subtraction_same_type) + { + Chrono::seconds s1(20); // 20 seconds + Chrono::seconds s2(10); // 10 seconds + + auto result = s1 - s2; + + CHECK_EQUAL(10, result.count()); // 20 - 10 = 10 seconds + } + + //************************************************************************* + TEST(test_subtraction_different_types) + { + Chrono::seconds s1(10); // 10 seconds + Chrono::milliseconds ms1(500); // 500 milliseconds + + auto result = s1 - ms1; + + // Result should be in the common type (milliseconds) + CHECK_EQUAL(9500, result.count()); // 10 seconds - 500 milliseconds = 9500 milliseconds + } + + //************************************************************************* + TEST(test_subtraction_with_zero) + { + Chrono::seconds s1(10); // 10 seconds + Chrono::seconds s2(0); // 0 seconds + + auto result = s1 - s2; + + CHECK_EQUAL(10, result.count()); // 10 - 0 = 10 seconds + } + + //************************************************************************* + TEST(test_subtraction_negative_duration) + { + Chrono::seconds s1(10); // 10 seconds + Chrono::seconds s2(-5); // -5 seconds + + auto result = s1 - s2; + + CHECK_EQUAL(15, result.count()); // 10 - (-5) = 15 seconds + } + + //************************************************************************* + TEST(test_subtraction_large_values) + { + Chrono::seconds s1(1000000); // 1,000,000 seconds + Chrono::milliseconds ms1(500000); // 500,000 milliseconds + + auto result = s1 - ms1; + + // Result should be in the common type (milliseconds) + CHECK_EQUAL(999500000, result.count()); // 1,000,000 seconds - 500,000 milliseconds = 999,500,000 milliseconds + } + + //************************************************************************* + TEST(test_subtraction_resulting_in_negative) + { + Chrono::seconds s1(5); // 5 seconds + Chrono::seconds s2(10); // 10 seconds + + auto result = s1 - s2; + + CHECK_EQUAL(-5, result.count()); // 5 - 10 = -5 seconds + } + + //************************************************************************* + TEST(test_multiplication_with_scalar_positive_duration_scalar) + { + etl::chrono::seconds s1(10); // 10 seconds + int scalar = 5; // Scalar value + + auto result = s1 * scalar; + + CHECK_EQUAL(50, result.count()); // 10 * 5 = 50 seconds + } + + //************************************************************************* + TEST(test_multiplication_with_scalar_negative_duration_scalar) + { + etl::chrono::seconds s1(10); // 10 seconds + int scalar = -3; // Negative scalar value + + auto result = s1 * scalar; + + CHECK_EQUAL(-30, result.count()); // 10 * (-3) = -30 seconds + } + + //************************************************************************* + TEST(test_multiplication_with_scalar_zero_duration_scalar) + { + etl::chrono::seconds s1(10); // 10 seconds + int scalar = 0; // Scalar value + + auto result = s1 * scalar; + + CHECK_EQUAL(0, result.count()); // 10 * 0 = 0 seconds + } + + //************************************************************************* + TEST(test_multiplication_with_large_scalar_duration_scalar) + { + etl::chrono::seconds s1(1000); // 1,000 seconds + int scalar = 1000000; // Large scalar value + + auto result = s1 * scalar; + + CHECK_EQUAL(1000000000, result.count()); // 1,000 * 1,000,000 = 1,000,000,000 seconds + } + + //************************************************************************* + TEST(test_multiplication_with_floating_point_scalar_duration_scalar) + { + etl::chrono::seconds s1(10); // 10 seconds + double scalar = 2.5; // Floating-point scalar value + + auto result = s1 * scalar; + + CHECK_EQUAL(25, result.count()); // 10 * 2.5 = 25 seconds + } + + //************************************************************************* + TEST(test_multiplication_with_different_representation_duration_scalar) + { + etl::chrono::milliseconds ms1(500); // 500 milliseconds + int scalar = 3; // Scalar value + + auto result = ms1 * scalar; + + CHECK_EQUAL(1500, result.count()); // 500 * 3 = 1,500 milliseconds + } + + //************************************************************************* + TEST(test_multiplication_with_scalar_positive_scalar_duration) + { + etl::chrono::seconds s1(10); // 10 seconds + int scalar = 5; // Scalar value + + auto result = scalar * s1; + + CHECK_EQUAL(50, result.count()); // 10 * 5 = 50 seconds + } + + //************************************************************************* + TEST(test_multiplication_with_scalar_negative_scalar_duration) + { + etl::chrono::seconds s1(10); // 10 seconds + int scalar = -3; // Negative scalar value + + auto result = scalar * s1; + + CHECK_EQUAL(-30, result.count()); // 10 * (-3) = -30 seconds + } + + //************************************************************************* + TEST(test_multiplication_with_scalar_zero_scalar_duration) + { + etl::chrono::seconds s1(10); // 10 seconds + int scalar = 0; // Scalar value + + auto result = scalar * s1; + + CHECK_EQUAL(0, result.count()); // 10 * 0 = 0 seconds + } + + //************************************************************************* + TEST(test_multiplication_with_large_scalar_scalar_duration) + { + etl::chrono::seconds s1(1000); // 1,000 seconds + int scalar = 1000000; // Large scalar value + + auto result = scalar * s1; + + CHECK_EQUAL(1000000000, result.count()); // 1,000 * 1,000,000 = 1,000,000,000 seconds + } + + //************************************************************************* + TEST(test_multiplication_with_floating_point_scalar_scalar_duration) + { + etl::chrono::seconds s1(10); // 10 seconds + double scalar = 2.5; // Floating-point scalar value + + auto result = scalar * s1; + + CHECK_EQUAL(25, result.count()); // 10 * 2.5 = 25 seconds + } + + //************************************************************************* + TEST(test_multiplication_with_different_representation_scalar_duration) + { + etl::chrono::milliseconds ms1(500); // 500 milliseconds + int scalar = 3; // Scalar value + + auto result = scalar * ms1; + + CHECK_EQUAL(1500, result.count()); // 500 * 3 = 1,500 milliseconds + } + + //************************************************************************* + TEST(test_division_with_scalar_positive_duration_scalar) + { + etl::chrono::seconds s1(10); // 10 seconds + int scalar = 5; // Scalar value + + auto result = s1 / scalar; + + CHECK_EQUAL(2, result.count()); // 10 / 5 = 2 seconds + } + + //************************************************************************* + TEST(test_division_with_scalar_negative_duration_scalar) + { + etl::chrono::seconds s1(10); // 10 seconds + int scalar = -2; // Negative scalar value + + auto result = s1 / scalar; + + CHECK_EQUAL(-5, result.count()); // 10 / (-2) = -5 seconds + } + + //************************************************************************* + TEST(test_division_with_large_scalar_duration_scalar) + { + etl::chrono::seconds s1(10000000); // 10,000,000 seconds + int scalar = 1000000; // Large scalar value + + auto result = s1 / scalar; + + CHECK_EQUAL(10, result.count()); // 10,000,000 / 1,000,000 = 10 seconds + } + + //************************************************************************* + TEST(test_division_with_floating_point_scalar_duration_scalar) + { + etl::chrono::seconds s1(10); // 10 seconds + double scalar = 2.5; // Floating-point scalar value + + auto result = s1 / scalar; + + CHECK_EQUAL(4, result.count()); // 10 / 2.5 = 4 seconds + } + + //************************************************************************* + TEST(test_division_with_different_representation_duration_scalar) + { + etl::chrono::milliseconds ms1(500); // 500 milliseconds + int scalar = 2; // Scalar value + + auto result = ms1 / scalar; + + CHECK_EQUAL(250, result.count()); // 500 / 2 = 250 milliseconds + } + + //************************************************************************* + TEST(test_division_same_type) + { + etl::chrono::seconds s1(20); // 20 seconds + etl::chrono::seconds s2(10); // 10 seconds + + auto result = s1 / s2; + + CHECK_EQUAL(2, result); // 20 / 10 = 2 + } + + //************************************************************************* + TEST(test_division_different_types) + { + etl::chrono::seconds s1(10); // 10 seconds + etl::chrono::milliseconds ms1(500); // 500 milliseconds + + auto result = s1 / ms1; + + // Result should be in the common type (milliseconds) + CHECK_EQUAL(20, result); // 10 seconds / 500 milliseconds = 20 + } + + //************************************************************************* + TEST(test_division_with_large_values) + { + etl::chrono::seconds s1(1000000); // 1,000,000 seconds + etl::chrono::milliseconds ms1(500000); // 500,000 milliseconds + + auto result = s1 / ms1; + + CHECK_EQUAL(2000, result); // 1,000,000 seconds / 500,000 milliseconds = 2000 + } + + //************************************************************************* + TEST(test_division_resulting_in_fraction) + { + etl::chrono::seconds s1(7); // 7 seconds + etl::chrono::seconds s2(3); // 3 seconds + + auto result = s1 / s2; + + CHECK_EQUAL(2, result); // 7 / 3 = 2 (integer division) + } + + //************************************************************************* + TEST(test_division_by_larger_duration) + { + etl::chrono::seconds s1(5); // 5 seconds + etl::chrono::seconds s2(10); // 10 seconds + + auto result = s1 / s2; + + CHECK_EQUAL(0, result); // 5 / 10 = 0 (integer division) + } + + //************************************************************************* + TEST(test_division_by_one) + { + etl::chrono::seconds s1(10); // 10 seconds + etl::chrono::seconds s2(1); // 1 second + + auto result = s1 / s2; + + CHECK_EQUAL(10, result); // 10 / 1 = 10 + } + + //************************************************************************* + TEST(test_modulus_with_positive_scalar) + { + etl::chrono::seconds s1(10); // 10 seconds + int scalar = 3; // Scalar value + + auto result = s1 % scalar; + + CHECK_EQUAL(1, result.count()); // 10 % 3 = 1 second + } + + //************************************************************************* + TEST(test_modulus_with_negative_scalar) + { + etl::chrono::seconds s1(10); // 10 seconds + int scalar = -3; // Negative scalar value + + auto result = s1 % scalar; + + CHECK_EQUAL(1, result.count()); // 10 % -3 = 1 second (modulus result is positive) + } + + //************************************************************************* + TEST(test_modulus_with_large_scalar) + { + etl::chrono::seconds s1(10); // 10 seconds + int scalar = 100; // Scalar value larger than duration + + auto result = s1 % scalar; + + CHECK_EQUAL(10, result.count()); // 10 % 100 = 10 seconds + } + + //************************************************************************* + TEST(test_modulus_with_different_representation) + { + etl::chrono::milliseconds ms1(1050); // 1050 milliseconds + int scalar = 500; // Scalar value + + auto result = ms1 % scalar; + + CHECK_EQUAL(50, result.count()); // 1050 % 500 = 50 milliseconds + } + + //************************************************************************* + TEST(test_modulus_same_type) + { + etl::chrono::seconds s1(10); // 10 seconds + etl::chrono::seconds s2(3); // 3 seconds + + auto result = s1 % s2; + + CHECK_EQUAL(1, result); // 10 % 3 = 1 second + } + + //************************************************************************* + TEST(test_modulus_different_types) + { + etl::chrono::seconds s1(10); // 10 seconds + etl::chrono::milliseconds ms1(3000); // 3000 milliseconds + + auto result = s1 % ms1; + + // Result should be in the common type (milliseconds) + CHECK_EQUAL(1000, result); // 10 seconds % 3000 milliseconds = 1000 milliseconds + } + + //************************************************************************* + TEST(test_modulus_with_large_values) + { + etl::chrono::seconds s1(1000000); // 1,000,000 seconds + etl::chrono::milliseconds ms1(500000); // 500,000 milliseconds + + auto result = s1 % ms1; + + CHECK_EQUAL(0, result); // 1,000,000 seconds % 500,000 milliseconds = 0 + } + + //************************************************************************* + TEST(test_modulus_resulting_in_fraction) + { + etl::chrono::seconds s1(7); // 7 seconds + etl::chrono::seconds s2(3); // 3 seconds + + auto result = s1 % s2; + + CHECK_EQUAL(1, result); // 7 % 3 = 1 second + } + + //************************************************************************* + TEST(test_modulus_by_larger_duration) + { + etl::chrono::seconds s1(5); // 5 seconds + etl::chrono::seconds s2(10); // 10 seconds + + auto result = s1 % s2; + + CHECK_EQUAL(5, result); // 5 % 10 = 5 seconds + } + + //************************************************************************* + TEST(test_modulus_with_different_periods) + { + etl::chrono::seconds s1(10); // 10 seconds + etl::chrono::milliseconds ms1(2500); // 2500 milliseconds + + auto result = s1 % ms1; + + // Result should be in the common type (milliseconds) + CHECK_EQUAL(0, result); // 10 seconds % 2500 milliseconds = 0 milliseconds + } }; } From ee748eb6cb3f602f9fb8f8253fc7131f925618bc Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Tue, 22 Apr 2025 20:16:52 +0100 Subject: [PATCH 18/33] Updates to chrono classes --- include/etl/chrono.h | 3 +- include/etl/private/chrono/day.h | 14 + include/etl/private/chrono/duration.h | 85 ++++ include/etl/private/chrono/month.h | 93 ++++ include/etl/private/chrono/month_day.h | 84 +++- include/etl/private/chrono/month_weekday.h | 211 ++++++++ include/etl/private/chrono/weekday.h | 261 +++++++--- include/etl/private/chrono/weekday_indexed.h | 153 ------ include/etl/private/chrono/weekday_last.h | 115 ----- include/etl/private/chrono/year.h | 15 +- test/test_chrono_day.cpp | 15 +- test/test_chrono_duration.cpp | 246 ++++++++-- test/test_chrono_month.cpp | 13 + test/test_chrono_month_day.cpp | 492 +++++++------------ test/test_chrono_month_day_last.cpp | 130 +++++ test/test_chrono_month_weekday.cpp | 126 +++++ test/test_chrono_month_weekday_last.cpp | 125 +++++ test/test_chrono_weekday.cpp | 154 +++--- test/test_chrono_weekday_indexed.cpp | 87 ++-- test/test_chrono_weekday_last.cpp | 68 +-- test/test_chrono_year.cpp | 166 +++---- test/vs2022/etl.vcxproj | 6 +- test/vs2022/etl.vcxproj.filters | 18 +- 23 files changed, 1756 insertions(+), 924 deletions(-) create mode 100644 include/etl/private/chrono/month_weekday.h delete mode 100644 include/etl/private/chrono/weekday_indexed.h delete mode 100644 include/etl/private/chrono/weekday_last.h create mode 100644 test/test_chrono_month_day_last.cpp create mode 100644 test/test_chrono_month_weekday.cpp create mode 100644 test/test_chrono_month_weekday_last.cpp diff --git a/include/etl/chrono.h b/include/etl/chrono.h index 8789d656..0c35a887 100644 --- a/include/etl/chrono.h +++ b/include/etl/chrono.h @@ -46,10 +46,9 @@ SOFTWARE. #include "private/chrono/duration.h" #include "private/chrono/day.h" #include "private/chrono/weekday.h" -#include "private/chrono/weekday_indexed.h" -#include "private/chrono/weekday_last.h" #include "private/chrono/month.h" #include "private/chrono/month_day.h" +#include "private/chrono/month_weekday.h" #include "private/chrono/year.h" #include "private/chrono/operators.h" #endif diff --git a/include/etl/private/chrono/day.h b/include/etl/private/chrono/day.h index a3459658..192a5ccc 100644 --- a/include/etl/private/chrono/day.h +++ b/include/etl/private/chrono/day.h @@ -163,6 +163,20 @@ namespace etl return static_cast(value); } + //*********************************************************************** + /// Compare day with another. + /// if day < other, returns -1; + /// else if day > other, returns 1; + /// else returns 0; + //*********************************************************************** + ETL_CONSTEXPR14 int compare(const day& other) const ETL_NOEXCEPT + { + if (value < other.value) return -1; + if (value > other.value) return 1; + + return 0; + } + //*********************************************************************** /// The minimum day value for which ok() will return true //*********************************************************************** diff --git a/include/etl/private/chrono/duration.h b/include/etl/private/chrono/duration.h index 3160ab18..df6ee983 100644 --- a/include/etl/private/chrono/duration.h +++ b/include/etl/private/chrono/duration.h @@ -219,6 +219,75 @@ namespace etl return temp; } + //*********************************************************************** + ETL_CONSTEXPR duration& operator +=(const duration& d) + { + value += d.count(); + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR duration& operator -=(const duration& d) + { + value -= d.count(); + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR duration& operator *=(const TRep& r) + { + value *= r; + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR duration& operator /=(const TRep& r) + { + value /= r; + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR duration& operator %=(const TRep& r) + { + value %= r; + + return *this; + } + + //*********************************************************************** + ETL_CONSTEXPR duration& operator %=(const duration& d) + { + value %= d.count(); + + return *this; + } + + //*********************************************************************** + /// Compare duration with another. + /// if duration < other, returns -1; + /// else if duration > other, returns 1; + /// else returns 0; + //*********************************************************************** + template + ETL_CONSTEXPR14 int compare(const duration& other) const ETL_NOEXCEPT + { + // Determine the common type of the two durations. + using common_duration = typename etl::common_type, etl::chrono::duration>::type; + + common_duration lhs_converted = etl::chrono::duration_cast(*this); + common_duration rhs_converted = etl::chrono::duration_cast(other); + + if (lhs_converted.count() < rhs_converted.count()) return -1; + if (lhs_converted.count() > rhs_converted.count()) return 1; + + return 0; + } + private: TRep value; @@ -388,6 +457,22 @@ namespace etl return !(lhs < rhs); } + //*********************************************************************** + /// Spaceship operator + //*********************************************************************** +#if ETL_USING_CPP20 + template + [[nodiscard]] constexpr auto operator <=>(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) noexcept + { + typedef typename etl::common_type, etl::chrono::duration >::type common_t; + + common_t l = etl::chrono::duration_cast(lhs); + common_t r = etl::chrono::duration_cast(rhs); + + return (l.count() <=> r.count()); + } +#endif + //*********************************************************************** /// Operator + //*********************************************************************** diff --git a/include/etl/private/chrono/month.h b/include/etl/private/chrono/month.h index 6c3d05cc..1359c555 100644 --- a/include/etl/private/chrono/month.h +++ b/include/etl/private/chrono/month.h @@ -155,6 +155,20 @@ namespace etl return (value >= 1U) && (value <= 12U); } + //*********************************************************************** + /// Compare month with another. + /// if month < other, returns -1; + /// else if month > other, returns 1; + /// else returns 0; + //*********************************************************************** + ETL_CONSTEXPR14 int compare(const month& other) const ETL_NOEXCEPT + { + if (value < other.value) return -1; + if (value > other.value) return 1; + + return 0; + } + //*********************************************************************** /// The minimum month value for which ok() will return true //*********************************************************************** @@ -342,6 +356,68 @@ namespace etl static ETL_CONSTANT etl::chrono::month November{ 11 }; static ETL_CONSTANT etl::chrono::month December{ 12 }; #endif + + //************************************************************************* + /// month_day_last + //************************************************************************* + class month_day_last + { + public: + + //************************************************************************* + /// Construct from month. + //************************************************************************* + ETL_CONSTEXPR explicit month_day_last(const etl::chrono::month& m_) ETL_NOEXCEPT + : m(m_) + { + } + + //************************************************************************* + /// Get the month. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::month month() const ETL_NOEXCEPT + { + return m; + } + + //************************************************************************* + /// Is the contained month OK? + //************************************************************************* + bool ok() const ETL_NOEXCEPT + { + return m.ok(); + } + + private: + + etl::chrono::month m; + }; + + //*********************************************************************** + /// Equality operator + //*********************************************************************** + ETL_CONSTEXPR bool operator ==(const etl::chrono::month_day_last& mdl1, const etl::chrono::month_day_last& mdl2) ETL_NOEXCEPT + { + return (static_cast(mdl1.month()) == static_cast(mdl2.month())); + } + + //*********************************************************************** + /// Inequality operator + //*********************************************************************** + ETL_CONSTEXPR bool operator !=(const etl::chrono::month_day_last& mdl1, const etl::chrono::month_day_last& mdl2) ETL_NOEXCEPT + { + return !(mdl1 == mdl2); + } + + //*********************************************************************** + /// Spaceship operator + //*********************************************************************** +#if ETL_USING_CPP20 + [[nodiscard]] constexpr auto operator <=>(const etl::chrono::month_day_last& mdl1, const etl::chrono::month_day_last& mdl2) noexcept + { + return (static_cast(mdl1.month()) <=> static_cast(mdl2.month())); + } +#endif } //************************************************************************* @@ -360,6 +436,23 @@ namespace etl } }; #endif + + //************************************************************************* + /// Hash function for etl::chrono::month_day_last + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::month_day_last& mdl) const + { + unsigned value = (unsigned)mdl.month(); + const uint8_t* p = reinterpret_cast(&value); + + return etl::private_hash::generic_hash(p, p + sizeof(unsigned)); + } + }; +#endif } #if ETL_HAS_CHRONO_LITERALS_MONTH diff --git a/include/etl/private/chrono/month_day.h b/include/etl/private/chrono/month_day.h index fbcb03bc..e58f62f0 100644 --- a/include/etl/private/chrono/month_day.h +++ b/include/etl/private/chrono/month_day.h @@ -96,7 +96,7 @@ namespace etl } //************************************************************************* - /// Returns true if the two instances are equal. + /// Equality operator. //************************************************************************* friend ETL_CONSTEXPR bool operator ==(const etl::chrono::month_day& lhs, const etl::chrono::month_day& rhs) ETL_NOEXCEPT @@ -104,6 +104,66 @@ namespace etl return (lhs.d == rhs.d) && (lhs.m == rhs.m); } + //************************************************************************* + /// Equality operator. + //************************************************************************* + friend ETL_CONSTEXPR bool operator !=(const etl::chrono::month_day& lhs, + const etl::chrono::month_day& rhs) ETL_NOEXCEPT + { + return !(lhs == rhs); + } + + //************************************************************************* + /// Less-than operator. + //************************************************************************* + friend ETL_NODISCARD ETL_CONSTEXPR + bool operator <(const etl::chrono::month_day& lhs, + const etl::chrono::month_day& rhs) ETL_NOEXCEPT + { + if (lhs.month() < rhs.month()) + { + return true; + } + else if (lhs.month() == rhs.month()) + { + return lhs.day() < rhs.day(); + } + else + { + return false; + } + } + + //************************************************************************* + /// Less-than-equal operator. + //************************************************************************* + friend ETL_NODISCARD ETL_CONSTEXPR + bool operator <=(const etl::chrono::month_day& lhs, + const etl::chrono::month_day& rhs) ETL_NOEXCEPT + { + return !(rhs < lhs); + } + + //************************************************************************* + /// Greater-than operator. + //************************************************************************* + friend ETL_NODISCARD ETL_CONSTEXPR + bool operator >(const etl::chrono::month_day& lhs, + const etl::chrono::month_day& rhs) ETL_NOEXCEPT + { + return rhs < lhs; + } + + //************************************************************************* + /// Greater-than-equal operator. + //************************************************************************* + friend ETL_NODISCARD ETL_CONSTEXPR + bool operator >=(const etl::chrono::month_day& lhs, + const etl::chrono::month_day& rhs) ETL_NOEXCEPT + { + return !(lhs < rhs); + } + //*********************************************************************** /// Spaceship operator //*********************************************************************** @@ -111,7 +171,7 @@ namespace etl friend [[nodiscard]] constexpr auto operator <=>(const etl::chrono::month_day& lhs, const etl::chrono::month_day& rhs) noexcept { - auto cmp = lhs.m <=> rhs.m; + auto cmp = lhs.month() <=> rhs.month(); if (cmp != 0) { @@ -119,11 +179,29 @@ namespace etl } else { - return lhs.d <=> rhs.d; + return lhs.day() <=> rhs.day(); } } #endif + //*********************************************************************** + /// Compare month_day with another. + /// if month < other.month, returns -1; + /// else if month > other.month, returns 1; + /// else if day < other.day, returns -1; + /// else if day > other.day, returns 1; + /// else returns 0; + //*********************************************************************** + ETL_CONSTEXPR14 int compare(const month_day& other) const ETL_NOEXCEPT + { + if (m < other.m) return -1; + if (m > other.m) return 1; + if (d < other.d) return -1; + if (d > other.d) return 1; + + return 0; + } + private: etl::chrono::month m; diff --git a/include/etl/private/chrono/month_weekday.h b/include/etl/private/chrono/month_weekday.h new file mode 100644 index 00000000..e1f99d95 --- /dev/null +++ b/include/etl/private/chrono/month_weekday.h @@ -0,0 +1,211 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +namespace etl +{ + namespace chrono + { + class month_weekday + { + public: + + //************************************************************************* + /// Construct from month and weekday_indexed. + //************************************************************************* + ETL_CONSTEXPR month_weekday(const etl::chrono::month& m_, const etl::chrono::weekday_indexed& wdi_) ETL_NOEXCEPT + : m(m_) + , wdi(wdi_) + { + } + + //************************************************************************* + /// Returns the month. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::month month() const ETL_NOEXCEPT + { + return m; + } + + //************************************************************************* + /// Returns the weekday_indexed. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::weekday_indexed weekday_indexed() const ETL_NOEXCEPT + { + return wdi; + } + + //************************************************************************* + /// Returns true if the month/day is valid. + //************************************************************************* + ETL_CONSTEXPR14 bool ok() const ETL_NOEXCEPT + { + return m.ok() && wdi.ok(); + } + + //************************************************************************* + /// Equality operator. + //************************************************************************* + friend ETL_CONSTEXPR bool operator ==(const etl::chrono::month_weekday& lhs, + const etl::chrono::month_weekday& rhs) ETL_NOEXCEPT + { + return (lhs.m == rhs.m) && (lhs.wdi == rhs.wdi); + } + + //************************************************************************* + /// Equality operator. + //************************************************************************* + friend ETL_CONSTEXPR bool operator !=(const etl::chrono::month_weekday& lhs, + const etl::chrono::month_weekday& rhs) ETL_NOEXCEPT + { + return !(lhs == rhs); + } + + private: + + etl::chrono::month m; + etl::chrono::weekday_indexed wdi; + }; + + //************************************************************************* + /// Construct from month and weekday_last. + //************************************************************************* + class month_weekday_last + { + public: + + //************************************************************************* + /// Construct from month and weekday_indexed. + //************************************************************************* + ETL_CONSTEXPR month_weekday_last(const etl::chrono::month& m_, const etl::chrono::weekday_last& wdl_) ETL_NOEXCEPT + : m(m_) + , wdl(wdl_) + { + } + + //************************************************************************* + /// Returns the month. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::month month() const ETL_NOEXCEPT + { + return m; + } + + //************************************************************************* + /// Returns the weekday_indexed. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::weekday_last weekday_last() const ETL_NOEXCEPT + { + return wdl; + } + + //************************************************************************* + /// Returns true if the month/day is valid. + //************************************************************************* + ETL_CONSTEXPR14 bool ok() const ETL_NOEXCEPT + { + return m.ok() && wdl.ok(); + } + + //************************************************************************* + /// Equality operator. + //************************************************************************* + friend ETL_CONSTEXPR bool operator ==(const etl::chrono::month_weekday_last& lhs, + const etl::chrono::month_weekday_last& rhs) ETL_NOEXCEPT + { + return (lhs.m == rhs.m) && (lhs.wdl == rhs.wdl); + } + + //************************************************************************* + /// Equality operator. + //************************************************************************* + friend ETL_CONSTEXPR bool operator !=(const etl::chrono::month_weekday_last& lhs, + const etl::chrono::month_weekday_last& rhs) ETL_NOEXCEPT + { + return !(lhs == rhs); + } + + private: + + etl::chrono::month m; + etl::chrono::weekday_last wdl; + }; + } + + //************************************************************************* + /// Hash function for etl::chrono::month_weekday + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::month_weekday& mw) const + { + uint8_t buffer[sizeof(unsigned int) + sizeof(unsigned int)]; + + unsigned int a = mw.month(); + unsigned int b = mw.weekday_indexed().weekday().c_encoding(); + unsigned int c = mw.weekday_indexed().index(); + + memcpy(buffer, &a, sizeof(a)); + memcpy(buffer + sizeof(a), &b, sizeof(b)); + memcpy(buffer + sizeof(b), &b, sizeof(c)); + + return etl::private_hash::generic_hash(buffer, buffer + sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned int)); + } + }; +#endif + + //************************************************************************* + /// Hash function for etl::chrono::month_weekday_last + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::month_weekday_last& mw) const + { + uint8_t buffer[sizeof(unsigned int) + sizeof(unsigned int)]; + + unsigned int a = mw.month(); + unsigned int b = mw.weekday_last().weekday().c_encoding(); + + memcpy(buffer, &a, sizeof(a)); + memcpy(buffer + sizeof(a), &b, sizeof(b)); + + return etl::private_hash::generic_hash(buffer, buffer + sizeof(unsigned int) + sizeof(unsigned int)); + } + }; +#endif +} + diff --git a/include/etl/private/chrono/weekday.h b/include/etl/private/chrono/weekday.h index d294d9c8..e434ef56 100644 --- a/include/etl/private/chrono/weekday.h +++ b/include/etl/private/chrono/weekday.h @@ -160,18 +160,20 @@ namespace etl //*********************************************************************** /// The minimum weekday value for which ok() will return true + /// C encoding. //*********************************************************************** - static ETL_CONSTEXPR etl::chrono::weekday min() ETL_NOEXCEPT + static ETL_CONSTEXPR unsigned min() ETL_NOEXCEPT { - return etl::chrono::weekday(0); + return 0; } //*********************************************************************** /// The maximum weekday value for which ok() will return true + /// C encoding. //*********************************************************************** - static ETL_CONSTEXPR etl::chrono::weekday max() ETL_NOEXCEPT + static ETL_CONSTEXPR unsigned max() ETL_NOEXCEPT { - return etl::chrono::weekday(6); + return 6; } //*********************************************************************** @@ -198,7 +200,7 @@ namespace etl //*********************************************************************** /// Index operator from etl::chrono::last_spec //*********************************************************************** - ETL_CONSTEXPR etl::chrono::weekday_last operator[](etl::chrono::last_spec) const ETL_NOEXCEPT; + ETL_CONSTEXPR etl::chrono::weekday_last operator[](etl::chrono::last_spec last) const ETL_NOEXCEPT; //*********************************************************************** /// Returns true if the day is a weekend. @@ -210,14 +212,7 @@ namespace etl private: - //*********************************************************************** - /// Normalise to a in-range weekday - //*********************************************************************** - ETL_CONSTEXPR void normalise() ETL_NOEXCEPT - { - value %= 7U; - } - + // The weekday value in C encoding. unsigned char value; }; @@ -237,48 +232,6 @@ namespace etl return !(wd1 == wd2); } - //*********************************************************************** - /// Less-than operator - //*********************************************************************** - ETL_CONSTEXPR bool operator <(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT - { - return (wd1.c_encoding() < wd2.c_encoding()); - } - - //*********************************************************************** - /// Less-than-or-equal operator - //*********************************************************************** - ETL_CONSTEXPR bool operator <=(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT - { - return (wd1.c_encoding() <= wd2.c_encoding()); - } - - //*********************************************************************** - /// Greater-than operator - //*********************************************************************** - ETL_CONSTEXPR bool operator >(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT - { - return (wd1.c_encoding() > wd2.c_encoding()); - } - - //*********************************************************************** - /// Greater-than-or-equal operator - //*********************************************************************** - ETL_CONSTEXPR bool operator >=(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) ETL_NOEXCEPT - { - return (wd1.c_encoding() >= wd2.c_encoding()); - } - - //*********************************************************************** - /// Spaceship operator - //*********************************************************************** -#if ETL_USING_CPP20 - [[nodiscard]] constexpr auto operator <=>(const etl::chrono::weekday& wd1, const etl::chrono::weekday& wd2) noexcept - { - return (wd1.c_encoding() <=> wd2.c_encoding()); - } -#endif - //*********************************************************************** /// Add etl::chrono::days to etl::chrono::weekday ///\return etl::chrono::weekday @@ -349,6 +302,176 @@ namespace etl static ETL_CONSTANT etl::chrono::weekday Friday{ 5U }; static ETL_CONSTANT etl::chrono::weekday Saturday{ 6U }; #endif + + //*********************************************************************** + /// weekday_indexed + //*********************************************************************** + class weekday_indexed + { + public: + + //*********************************************************************** + /// Default constructor + //*********************************************************************** + ETL_CONSTEXPR weekday_indexed() ETL_NOEXCEPT + : wd() + , i() + { + } + + //*********************************************************************** + /// Construct from weekday and index + //*********************************************************************** + ETL_CONSTEXPR weekday_indexed(const etl::chrono::weekday& wd_, unsigned index_) ETL_NOEXCEPT + : wd(wd_) + , i(static_cast(index_)) + { + } + + //*********************************************************************** + /// Copy constructor + //*********************************************************************** + ETL_CONSTEXPR weekday_indexed(const etl::chrono::weekday_indexed& other) ETL_NOEXCEPT + : wd(other.wd) + , i(other.i) + { + } + + //*********************************************************************** + /// Assignment operator + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::weekday_indexed& operator =(const etl::chrono::weekday_indexed& rhs) ETL_NOEXCEPT + { + wd = rhs.wd; + i = rhs.i; + + return *this; + } + + //*********************************************************************** + /// Get weekday + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR etl::chrono::weekday weekday() const ETL_NOEXCEPT + { + return wd; + } + + //*********************************************************************** + /// Get index + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR unsigned index() const ETL_NOEXCEPT + { + return i; + } + + //*********************************************************************** + /// Returns true if the weekday and index are valid + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + { + return wd.ok() && (i >= 1U) && (i <= 5U); + } + + private: + + etl::chrono::weekday wd; + uint_least8_t i; + }; + + //*********************************************************************** + /// Equality operator + //*********************************************************************** + ETL_CONSTEXPR bool operator ==(const etl::chrono::weekday_indexed& wd1, const etl::chrono::weekday_indexed& wd2) ETL_NOEXCEPT + { + return (wd1.weekday() == wd2.weekday()) && + (wd1.index() == wd2.index()); + } + + //*********************************************************************** + /// Inequality operator + //*********************************************************************** + ETL_CONSTEXPR bool operator !=(const etl::chrono::weekday_indexed& wd1, const etl::chrono::weekday_indexed& wd2) ETL_NOEXCEPT + { + return !(wd1 == wd2); + } + + //*********************************************************************** + /// weekday_last + //*********************************************************************** + class weekday_last + { + public: + + //*********************************************************************** + /// Construct from unsigned + //*********************************************************************** + ETL_CONSTEXPR explicit weekday_last(const etl::chrono::weekday& wd_) ETL_NOEXCEPT + : wd(wd_) + { + } + + //*********************************************************************** + /// Copy constructor + //*********************************************************************** + ETL_CONSTEXPR weekday_last(const etl::chrono::weekday_last& other) ETL_NOEXCEPT + : wd(other.wd) + { + } + + //*********************************************************************** + /// Assignment operator + //*********************************************************************** + ETL_CONSTEXPR14 etl::chrono::weekday_last& operator =(const etl::chrono::weekday_last& rhs) ETL_NOEXCEPT + { + wd = rhs.wd; + + return *this; + } + + //*********************************************************************** + /// Get weekday + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR etl::chrono::weekday weekday() const ETL_NOEXCEPT + { + return wd; + } + + //*********************************************************************** + /// Returns true if the weekday is valid + //*********************************************************************** + ETL_NODISCARD ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT + { + return wd.ok(); + } + + private: + + etl::chrono::weekday wd; + }; + + //*********************************************************************** + /// Equality operator + //*********************************************************************** + ETL_CONSTEXPR bool operator ==(const etl::chrono::weekday_last& wd1, const etl::chrono::weekday_last& wd2) ETL_NOEXCEPT + { + return (wd1.weekday() == wd2.weekday()); + } + + //*********************************************************************** + /// weekday index operator from index + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday_indexed etl::chrono::weekday::operator[](unsigned index) const ETL_NOEXCEPT + { + return etl::chrono::weekday_indexed(*this, index); + } + + //*********************************************************************** + /// Index operator from etl::chrono::last_spec + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::weekday_last etl::chrono::weekday::operator[](etl::chrono::last_spec last) const ETL_NOEXCEPT + { + return etl::chrono::weekday_last(*this); + } } //************************************************************************* @@ -367,6 +490,34 @@ namespace etl } }; #endif + + //************************************************************************* + /// Hash function for etl::chrono::weekday_indexed + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::weekday_indexed& wdi) const + { + return etl::hash()(wdi.weekday()) ^ etl::hash()(wdi.index()); + } + }; +#endif + + //************************************************************************* + /// Hash function for etl::chrono::weekday_last + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::weekday_last& wdl) const + { + return etl::hash()(wdl.weekday()); + } + }; +#endif } #if ETL_HAS_CHRONO_LITERALS_WEEKDAY diff --git a/include/etl/private/chrono/weekday_indexed.h b/include/etl/private/chrono/weekday_indexed.h deleted file mode 100644 index 46bc2354..00000000 --- a/include/etl/private/chrono/weekday_indexed.h +++ /dev/null @@ -1,153 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -https://www.etlcpp.com - -Copyright(c) 2023 John Wellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#ifndef ETL_IN_CHRONO_H - #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H -#endif - -namespace etl -{ - namespace chrono - { - //*********************************************************************** - /// weekday_indexed - //*********************************************************************** - class weekday_indexed - { - public: - - //*********************************************************************** - /// Default constructor - //*********************************************************************** - ETL_CONSTEXPR weekday_indexed() ETL_NOEXCEPT - : wd() - , i() - { - } - - //*********************************************************************** - /// Construct from weekday and index - //*********************************************************************** - ETL_CONSTEXPR weekday_indexed(const etl::chrono::weekday& wd_, unsigned index_) ETL_NOEXCEPT - : wd(wd_) - , i(index_) - { - } - - //*********************************************************************** - /// Copy constructor - //*********************************************************************** - ETL_CONSTEXPR weekday_indexed(const etl::chrono::weekday_indexed& other) ETL_NOEXCEPT - : wd(other.wd) - , i(other.i) - { - } - - //*********************************************************************** - /// Assignment operator - //*********************************************************************** - ETL_CONSTEXPR14 etl::chrono::weekday_indexed& operator =(const etl::chrono::weekday_indexed& rhs) ETL_NOEXCEPT - { - wd = rhs.wd; - i = rhs.i; - - return *this; - } - - //*********************************************************************** - /// Get weekday - //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR etl::chrono::weekday weekday() const ETL_NOEXCEPT - { - return wd; - } - - //*********************************************************************** - /// Get index - //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR unsigned index() const ETL_NOEXCEPT - { - return i; - } - - //*********************************************************************** - /// Returns true if the weekday and index are valid - //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT - { - return wd.ok() && (i >= 1U) && (i <= 5U); - } - - private: - - etl::chrono::weekday wd; - unsigned i; - }; - - //*********************************************************************** - /// Equality operator - //*********************************************************************** - ETL_CONSTEXPR bool operator ==(const etl::chrono::weekday_indexed& wd1, const etl::chrono::weekday_indexed& wd2) ETL_NOEXCEPT - { - return (wd1.weekday() == wd2.weekday()) && - (wd1.index() == wd2.index()); - } - - //*********************************************************************** - /// Inequality operator - //*********************************************************************** - ETL_CONSTEXPR bool operator !=(const etl::chrono::weekday_indexed& wd1, const etl::chrono::weekday_indexed& wd2) ETL_NOEXCEPT - { - return !(wd1 == wd2); - } - - //*********************************************************************** - /// weekday index operator from index - //*********************************************************************** - ETL_CONSTEXPR etl::chrono::weekday_indexed etl::chrono::weekday::operator[](unsigned index) const ETL_NOEXCEPT - { - return etl::chrono::weekday_indexed(*this, index); - } - } - - //************************************************************************* - /// Hash function for etl::chrono::weekday_indexed - //************************************************************************* -#if ETL_USING_8BIT_TYPES - template <> - struct hash - { - size_t operator()(const etl::chrono::weekday_indexed& wdi) const - { - return etl::hash()(wdi.weekday()) ^ etl::hash()(wdi.index()); - } - }; -#endif -} diff --git a/include/etl/private/chrono/weekday_last.h b/include/etl/private/chrono/weekday_last.h deleted file mode 100644 index 62dc337a..00000000 --- a/include/etl/private/chrono/weekday_last.h +++ /dev/null @@ -1,115 +0,0 @@ -///\file - -/****************************************************************************** -The MIT License(MIT) - -Embedded Template Library. -https://github.com/ETLCPP/etl -https://www.etlcpp.com - -Copyright(c) 2023 John Wellbelove - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files(the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions : - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -******************************************************************************/ - -#ifndef ETL_IN_CHRONO_H - #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H -#endif - -namespace etl -{ - namespace chrono - { - //*********************************************************************** - /// weekday_last - //*********************************************************************** - class weekday_last - { - public: - - //*********************************************************************** - /// Construct from unsigned - //*********************************************************************** - ETL_CONSTEXPR explicit weekday_last(const etl::chrono::weekday& wd_) ETL_NOEXCEPT - : wd(wd_) - { - } - - //*********************************************************************** - /// Copy constructor - //*********************************************************************** - ETL_CONSTEXPR weekday_last(const etl::chrono::weekday_last& other) ETL_NOEXCEPT - : wd(other.wd) - { - } - - //*********************************************************************** - /// Assignment operator - //*********************************************************************** - ETL_CONSTEXPR14 etl::chrono::weekday_last& operator =(const etl::chrono::weekday_last& rhs) ETL_NOEXCEPT - { - wd = rhs.wd; - - return *this; - } - - //*********************************************************************** - /// Get weekday - //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR etl::chrono::weekday weekday() const ETL_NOEXCEPT - { - return wd; - } - - //*********************************************************************** - /// Returns true if the weekday is valid - //*********************************************************************** - ETL_NODISCARD ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT - { - return wd.ok(); - } - - private: - - etl::chrono::weekday wd; - }; - - //*********************************************************************** - /// Equality operator - //*********************************************************************** - ETL_CONSTEXPR bool operator ==(const etl::chrono::weekday_last& wd1, const etl::chrono::weekday_last& wd2) ETL_NOEXCEPT - { - return (wd1.weekday() == wd2.weekday()); - } - } - - //************************************************************************* - /// Hash function for etl::chrono::weekday_last - //************************************************************************* -#if ETL_USING_8BIT_TYPES - template <> - struct hash - { - size_t operator()(const etl::chrono::weekday_last& wdl) const - { - return etl::hash()(wdl.weekday()); - } - }; -#endif -} diff --git a/include/etl/private/chrono/year.h b/include/etl/private/chrono/year.h index 695d369f..84306f78 100644 --- a/include/etl/private/chrono/year.h +++ b/include/etl/private/chrono/year.h @@ -281,6 +281,19 @@ namespace etl return result; } + //*********************************************************************** + /// Subtract etl::chrono::year from etl::chrono::years + ///\return etl::chrono::years + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::year operator -(const etl::chrono::years& ys, const etl::chrono::year& y) ETL_NOEXCEPT + { + etl::chrono::year result(y); + + result -= ys; + + return result; + } + //*********************************************************************** /// Subtract etl::chrono::year from etl::chrono::year ///\return etl::chrono::years @@ -288,7 +301,7 @@ namespace etl ETL_CONSTEXPR etl::chrono::years operator -(const etl::chrono::year& y1, const etl::chrono::year& y2) ETL_NOEXCEPT { return etl::chrono::years(static_cast(static_cast(y1)) - - static_cast(static_cast(y2))); + static_cast(static_cast(y2))); } } diff --git a/test/test_chrono_day.cpp b/test/test_chrono_day.cpp index a801f607..74245e72 100644 --- a/test/test_chrono_day.cpp +++ b/test/test_chrono_day.cpp @@ -38,7 +38,7 @@ SOFTWARE. #include // Set to 0 to reference against std::chrono -#define ETL_USING_ETL_CHRONO 0 +#define ETL_USING_ETL_CHRONO 1 #if ETL_USING_ETL_CHRONO #define Chrono etl::chrono @@ -290,6 +290,19 @@ namespace #endif } +#if ETL_USING_ETL_CHRONO + //************************************************************************* + TEST(test_day_compare) + { + Chrono::day day10(10); + Chrono::day day20(20); + + CHECK_EQUAL(0, day10.compare(day10)); + CHECK_EQUAL(-1, day10.compare(day20)); + CHECK_EQUAL(1, day20.compare(day10)); + } +#endif + #if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_day_hashes_are_unique) diff --git a/test/test_chrono_duration.cpp b/test/test_chrono_duration.cpp index f97a606a..90bca535 100644 --- a/test/test_chrono_duration.cpp +++ b/test/test_chrono_duration.cpp @@ -520,7 +520,7 @@ namespace //************************************************************************* TEST(test_multiplication_with_scalar_positive_duration_scalar) { - etl::chrono::seconds s1(10); // 10 seconds + Chrono::seconds s1(10); // 10 seconds int scalar = 5; // Scalar value auto result = s1 * scalar; @@ -531,7 +531,7 @@ namespace //************************************************************************* TEST(test_multiplication_with_scalar_negative_duration_scalar) { - etl::chrono::seconds s1(10); // 10 seconds + Chrono::seconds s1(10); // 10 seconds int scalar = -3; // Negative scalar value auto result = s1 * scalar; @@ -542,7 +542,7 @@ namespace //************************************************************************* TEST(test_multiplication_with_scalar_zero_duration_scalar) { - etl::chrono::seconds s1(10); // 10 seconds + Chrono::seconds s1(10); // 10 seconds int scalar = 0; // Scalar value auto result = s1 * scalar; @@ -553,7 +553,7 @@ namespace //************************************************************************* TEST(test_multiplication_with_large_scalar_duration_scalar) { - etl::chrono::seconds s1(1000); // 1,000 seconds + Chrono::seconds s1(1000); // 1,000 seconds int scalar = 1000000; // Large scalar value auto result = s1 * scalar; @@ -564,7 +564,7 @@ namespace //************************************************************************* TEST(test_multiplication_with_floating_point_scalar_duration_scalar) { - etl::chrono::seconds s1(10); // 10 seconds + Chrono::seconds s1(10); // 10 seconds double scalar = 2.5; // Floating-point scalar value auto result = s1 * scalar; @@ -575,7 +575,7 @@ namespace //************************************************************************* TEST(test_multiplication_with_different_representation_duration_scalar) { - etl::chrono::milliseconds ms1(500); // 500 milliseconds + Chrono::milliseconds ms1(500); // 500 milliseconds int scalar = 3; // Scalar value auto result = ms1 * scalar; @@ -586,7 +586,7 @@ namespace //************************************************************************* TEST(test_multiplication_with_scalar_positive_scalar_duration) { - etl::chrono::seconds s1(10); // 10 seconds + Chrono::seconds s1(10); // 10 seconds int scalar = 5; // Scalar value auto result = scalar * s1; @@ -597,7 +597,7 @@ namespace //************************************************************************* TEST(test_multiplication_with_scalar_negative_scalar_duration) { - etl::chrono::seconds s1(10); // 10 seconds + Chrono::seconds s1(10); // 10 seconds int scalar = -3; // Negative scalar value auto result = scalar * s1; @@ -608,7 +608,7 @@ namespace //************************************************************************* TEST(test_multiplication_with_scalar_zero_scalar_duration) { - etl::chrono::seconds s1(10); // 10 seconds + Chrono::seconds s1(10); // 10 seconds int scalar = 0; // Scalar value auto result = scalar * s1; @@ -619,7 +619,7 @@ namespace //************************************************************************* TEST(test_multiplication_with_large_scalar_scalar_duration) { - etl::chrono::seconds s1(1000); // 1,000 seconds + Chrono::seconds s1(1000); // 1,000 seconds int scalar = 1000000; // Large scalar value auto result = scalar * s1; @@ -630,7 +630,7 @@ namespace //************************************************************************* TEST(test_multiplication_with_floating_point_scalar_scalar_duration) { - etl::chrono::seconds s1(10); // 10 seconds + Chrono::seconds s1(10); // 10 seconds double scalar = 2.5; // Floating-point scalar value auto result = scalar * s1; @@ -641,7 +641,7 @@ namespace //************************************************************************* TEST(test_multiplication_with_different_representation_scalar_duration) { - etl::chrono::milliseconds ms1(500); // 500 milliseconds + Chrono::milliseconds ms1(500); // 500 milliseconds int scalar = 3; // Scalar value auto result = scalar * ms1; @@ -652,7 +652,7 @@ namespace //************************************************************************* TEST(test_division_with_scalar_positive_duration_scalar) { - etl::chrono::seconds s1(10); // 10 seconds + Chrono::seconds s1(10); // 10 seconds int scalar = 5; // Scalar value auto result = s1 / scalar; @@ -663,7 +663,7 @@ namespace //************************************************************************* TEST(test_division_with_scalar_negative_duration_scalar) { - etl::chrono::seconds s1(10); // 10 seconds + Chrono::seconds s1(10); // 10 seconds int scalar = -2; // Negative scalar value auto result = s1 / scalar; @@ -674,7 +674,7 @@ namespace //************************************************************************* TEST(test_division_with_large_scalar_duration_scalar) { - etl::chrono::seconds s1(10000000); // 10,000,000 seconds + Chrono::seconds s1(10000000); // 10,000,000 seconds int scalar = 1000000; // Large scalar value auto result = s1 / scalar; @@ -685,7 +685,7 @@ namespace //************************************************************************* TEST(test_division_with_floating_point_scalar_duration_scalar) { - etl::chrono::seconds s1(10); // 10 seconds + Chrono::seconds s1(10); // 10 seconds double scalar = 2.5; // Floating-point scalar value auto result = s1 / scalar; @@ -696,7 +696,7 @@ namespace //************************************************************************* TEST(test_division_with_different_representation_duration_scalar) { - etl::chrono::milliseconds ms1(500); // 500 milliseconds + Chrono::milliseconds ms1(500); // 500 milliseconds int scalar = 2; // Scalar value auto result = ms1 / scalar; @@ -707,8 +707,8 @@ namespace //************************************************************************* TEST(test_division_same_type) { - etl::chrono::seconds s1(20); // 20 seconds - etl::chrono::seconds s2(10); // 10 seconds + Chrono::seconds s1(20); // 20 seconds + Chrono::seconds s2(10); // 10 seconds auto result = s1 / s2; @@ -718,8 +718,8 @@ namespace //************************************************************************* TEST(test_division_different_types) { - etl::chrono::seconds s1(10); // 10 seconds - etl::chrono::milliseconds ms1(500); // 500 milliseconds + Chrono::seconds s1(10); // 10 seconds + Chrono::milliseconds ms1(500); // 500 milliseconds auto result = s1 / ms1; @@ -730,8 +730,8 @@ namespace //************************************************************************* TEST(test_division_with_large_values) { - etl::chrono::seconds s1(1000000); // 1,000,000 seconds - etl::chrono::milliseconds ms1(500000); // 500,000 milliseconds + Chrono::seconds s1(1000000); // 1,000,000 seconds + Chrono::milliseconds ms1(500000); // 500,000 milliseconds auto result = s1 / ms1; @@ -741,8 +741,8 @@ namespace //************************************************************************* TEST(test_division_resulting_in_fraction) { - etl::chrono::seconds s1(7); // 7 seconds - etl::chrono::seconds s2(3); // 3 seconds + Chrono::seconds s1(7); // 7 seconds + Chrono::seconds s2(3); // 3 seconds auto result = s1 / s2; @@ -752,8 +752,8 @@ namespace //************************************************************************* TEST(test_division_by_larger_duration) { - etl::chrono::seconds s1(5); // 5 seconds - etl::chrono::seconds s2(10); // 10 seconds + Chrono::seconds s1(5); // 5 seconds + Chrono::seconds s2(10); // 10 seconds auto result = s1 / s2; @@ -763,8 +763,8 @@ namespace //************************************************************************* TEST(test_division_by_one) { - etl::chrono::seconds s1(10); // 10 seconds - etl::chrono::seconds s2(1); // 1 second + Chrono::seconds s1(10); // 10 seconds + Chrono::seconds s2(1); // 1 second auto result = s1 / s2; @@ -774,7 +774,7 @@ namespace //************************************************************************* TEST(test_modulus_with_positive_scalar) { - etl::chrono::seconds s1(10); // 10 seconds + Chrono::seconds s1(10); // 10 seconds int scalar = 3; // Scalar value auto result = s1 % scalar; @@ -785,7 +785,7 @@ namespace //************************************************************************* TEST(test_modulus_with_negative_scalar) { - etl::chrono::seconds s1(10); // 10 seconds + Chrono::seconds s1(10); // 10 seconds int scalar = -3; // Negative scalar value auto result = s1 % scalar; @@ -796,7 +796,7 @@ namespace //************************************************************************* TEST(test_modulus_with_large_scalar) { - etl::chrono::seconds s1(10); // 10 seconds + Chrono::seconds s1(10); // 10 seconds int scalar = 100; // Scalar value larger than duration auto result = s1 % scalar; @@ -807,7 +807,7 @@ namespace //************************************************************************* TEST(test_modulus_with_different_representation) { - etl::chrono::milliseconds ms1(1050); // 1050 milliseconds + Chrono::milliseconds ms1(1050); // 1050 milliseconds int scalar = 500; // Scalar value auto result = ms1 % scalar; @@ -818,8 +818,8 @@ namespace //************************************************************************* TEST(test_modulus_same_type) { - etl::chrono::seconds s1(10); // 10 seconds - etl::chrono::seconds s2(3); // 3 seconds + Chrono::seconds s1(10); // 10 seconds + Chrono::seconds s2(3); // 3 seconds auto result = s1 % s2; @@ -829,8 +829,8 @@ namespace //************************************************************************* TEST(test_modulus_different_types) { - etl::chrono::seconds s1(10); // 10 seconds - etl::chrono::milliseconds ms1(3000); // 3000 milliseconds + Chrono::seconds s1(10); // 10 seconds + Chrono::milliseconds ms1(3000); // 3000 milliseconds auto result = s1 % ms1; @@ -841,8 +841,8 @@ namespace //************************************************************************* TEST(test_modulus_with_large_values) { - etl::chrono::seconds s1(1000000); // 1,000,000 seconds - etl::chrono::milliseconds ms1(500000); // 500,000 milliseconds + Chrono::seconds s1(1000000); // 1,000,000 seconds + Chrono::milliseconds ms1(500000); // 500,000 milliseconds auto result = s1 % ms1; @@ -852,8 +852,8 @@ namespace //************************************************************************* TEST(test_modulus_resulting_in_fraction) { - etl::chrono::seconds s1(7); // 7 seconds - etl::chrono::seconds s2(3); // 3 seconds + Chrono::seconds s1(7); // 7 seconds + Chrono::seconds s2(3); // 3 seconds auto result = s1 % s2; @@ -863,8 +863,8 @@ namespace //************************************************************************* TEST(test_modulus_by_larger_duration) { - etl::chrono::seconds s1(5); // 5 seconds - etl::chrono::seconds s2(10); // 10 seconds + Chrono::seconds s1(5); // 5 seconds + Chrono::seconds s2(10); // 10 seconds auto result = s1 % s2; @@ -874,13 +874,169 @@ namespace //************************************************************************* TEST(test_modulus_with_different_periods) { - etl::chrono::seconds s1(10); // 10 seconds - etl::chrono::milliseconds ms1(2500); // 2500 milliseconds + Chrono::seconds s1(10); // 10 seconds + Chrono::milliseconds ms1(2500); // 2500 milliseconds auto result = s1 % ms1; // Result should be in the common type (milliseconds) CHECK_EQUAL(0, result); // 10 seconds % 2500 milliseconds = 0 milliseconds } + + //************************************************************************* + TEST(test_operator_plus_equals_positive_value) + { + Chrono::seconds s1(10); // 10 seconds + Chrono::seconds s2(5); // 5 seconds + + s1 += s2; + + CHECK_EQUAL(15, s1.count()); // 10 + 5 = 15 seconds + } + + //************************************************************************* + TEST(test_operator_plus_equals_negative_value) + { + Chrono::seconds s1(10); // 10 seconds + Chrono::seconds s2(-5); // -5 seconds + + s1 += s2; + + CHECK_EQUAL(5, s1.count()); // 10 + (-5) = 5 seconds + } + + //************************************************************************* + TEST(test_operator_minus_equals_positive_value) + { + Chrono::seconds s1(10); // 10 seconds + Chrono::seconds s2(5); // 5 seconds + + s1 -= s2; + + CHECK_EQUAL(5, s1.count()); // 10 - 5 = 5 seconds + } + + //************************************************************************* + TEST(test_operator_minus_equals_negative_value) + { + Chrono::seconds s1(10); // 10 seconds + Chrono::seconds s2(-5); // -5 seconds + + s1 -= s2; + + CHECK_EQUAL(15, s1.count()); // 10 - (-5) = 15 seconds + } + + //************************************************************************* + TEST(test_operator_times_equals_positive_value) + { + Chrono::seconds s1(10); // 10 seconds + int scalar = 5; + + s1 *= scalar; + + CHECK_EQUAL(50, s1.count()); // 10 * 5 = 50 seconds + } + + //************************************************************************* + TEST(test_operator_times_equals_negative_value) + { + Chrono::seconds s1(10); // 10 seconds + int scalar = -5; + + s1 *= scalar; + + CHECK_EQUAL(-50, s1.count()); // 10 * (-5) = -50 seconds + } + + //************************************************************************* + TEST(test_operator_divide_equals_positive_value) + { + Chrono::seconds s1(10); // 10 seconds + int scalar = 5; + + s1 /= scalar; + + CHECK_EQUAL(2, s1.count()); // 10 / 5 = 2 seconds + } + + //************************************************************************* + TEST(test_operator_divide_equals_negative_value) + { + Chrono::seconds s1(10); // 10 seconds + int scalar = -5; + + s1 /= scalar; + + CHECK_EQUAL(-2, s1.count()); // 10 / (-5) = -2 seconds + } + + //************************************************************************* + TEST(test_operator_mod_equals_positive_value) + { + Chrono::seconds s1(10); // 10 seconds + int scalar = 4; + + s1 %= scalar; + + CHECK_EQUAL(2, s1.count()); // 10 % 4 = 2 seconds + } + + //************************************************************************* + TEST(test_operator_mod_equals_negative_value) + { + Chrono::seconds s1(10); // 10 seconds + int scalar = -4; + + s1 %= scalar; + + CHECK_EQUAL(2, s1.count()); // 10 % (-4) = 2 seconds + } + + //************************************************************************* + TEST(test_operator_mod_equals_positive_duration) + { + Chrono::seconds s1(10); // 10 seconds + Chrono::seconds s2(3); // 3 seconds + + s1 %= s2; + + CHECK_EQUAL(1, s1.count()); // 10 seconds % 3 seconds = 1 second + } + + //************************************************************************* + TEST(test_operator_mod_equals_negative_duration) + { + Chrono::seconds s1(10); // 10 seconds + Chrono::seconds s2(-3); // 3 seconds + + s1 %= s2; + + CHECK_EQUAL(1, s1.count()); // 10 seconds % (-3) seconds = 1 second + } + +#if ETL_USING_CPP20 + //************************************************************************* + TEST(test_duration_spaceship_operator) + { + 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); + } +#endif + + //************************************************************************* + TEST(test_duration_compare) + { + Chrono::seconds s1(2); // 2 seconds + Chrono::milliseconds ms1(1500); // 1500 milliseconds + + CHECK_EQUAL(0, s1.compare(s1)); + CHECK_EQUAL(-1, ms1.compare(s1)); + CHECK_EQUAL(1, s1.compare(ms1)); + } }; } diff --git a/test/test_chrono_month.cpp b/test/test_chrono_month.cpp index 3c0ffac8..058f260a 100644 --- a/test/test_chrono_month.cpp +++ b/test/test_chrono_month.cpp @@ -281,6 +281,19 @@ namespace } #endif +#if ETL_USING_ETL_CHRONO + //************************************************************************* + TEST(test_month_compare) + { + Chrono::month month1(Chrono::January); + Chrono::month month2(Chrono::February); + + CHECK_EQUAL(0, month1.compare(month1)); + CHECK_EQUAL(-1, month1.compare(month2)); + CHECK_EQUAL(1, month2.compare(month1)); + } +#endif + #if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_literal_month) diff --git a/test/test_chrono_month_day.cpp b/test/test_chrono_month_day.cpp index 9a7c66b2..af5d00fc 100644 --- a/test/test_chrono_month_day.cpp +++ b/test/test_chrono_month_day.cpp @@ -37,6 +37,20 @@ SOFTWARE. #include #include +// Set to 0 to reference against std::chrono +#define ETL_USING_ETL_CHRONO 1 + +#if ETL_USING_ETL_CHRONO + #define Chrono etl::chrono +#else + #if ETL_USING_CPP20 + #include + #define Chrono std::chrono + #else + #error std::chrono not supported + #endif +#endif + namespace { SUITE(test_chrono_month_day) @@ -44,336 +58,158 @@ namespace //************************************************************************* TEST(test_default_constructor) { - etl::chrono::month_day md; + Chrono::month_day md; - CHECK_FALSE(md.ok()); + CHECK_FALSE(md.ok()); // Default-constructed month_day is not valid + } + + //************************************************************************* + TEST(test_constructor_with_month_and_day) + { + Chrono::month_day md{Chrono::January, Chrono::day{15}}; + + CHECK_TRUE(md.ok()); // Valid month_day + CHECK_EQUAL(Chrono::January, md.month()); + CHECK_EQUAL(Chrono::day{15}, md.day()); + } + + //************************************************************************* + TEST(test_invalid_month_day) + { + Chrono::month_day md{Chrono::month{13}, Chrono::day{15}}; // Invalid month (13) + + CHECK_FALSE(md.ok()); // Invalid month_day + } + + //************************************************************************* + TEST(test_invalid_day_in_month_day) + { + Chrono::month_day md{Chrono::January, Chrono::day{32}}; // Invalid day (32) + + CHECK_FALSE(md.ok()); // Invalid month_day + } + +#if ETL_USING_CPP20 + //************************************************************************* + TEST(test_month_day_spaceship_operator) + { + Chrono::month_day md1{Chrono::January, Chrono::day{15}}; + 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 + } +#endif + +#if ETL_USING_ETL_CHRONO + //************************************************************************* + TEST(test_month_day_compare) + { + Chrono::month_day md1{Chrono::January, Chrono::day{15}}; + Chrono::month_day md2{Chrono::February, Chrono::day{10}}; + Chrono::month_day md3{Chrono::January, Chrono::day{15}}; + + CHECK_TRUE(md1.compare(md3) == 0); // Same month and day + CHECK_TRUE(md1.compare(md2) == -1); // Different month and day + CHECK_TRUE(md2.compare(md1) == 1); // Same month and day + } +#endif + + //************************************************************************* + TEST(test_month_day_equality_operator) + { + Chrono::month_day md1{Chrono::January, Chrono::day{15}}; + Chrono::month_day md2{Chrono::February, Chrono::day{10}}; + Chrono::month_day md3{Chrono::January, Chrono::day{20}}; + + CHECK_TRUE(md1 == md1); // January == January + CHECK_FALSE(md1 == md2); // January != February + CHECK_FALSE(md1 == md2); // 20th != 15th in the same month + } + + //************************************************************************* + TEST(test_month_day_not_equality_operator) + { + Chrono::month_day md1{Chrono::January, Chrono::day{15}}; + Chrono::month_day md2{Chrono::February, Chrono::day{10}}; + Chrono::month_day md3{Chrono::January, Chrono::day{20}}; + + CHECK_FALSE(md1 != md1); // January == January + CHECK_TRUE(md1 != md2); // January != February + CHECK_TRUE(md1 != md2); // 20th != 15th in the same month + } + + //************************************************************************* + TEST(test_month_day_less_than_operator) + { + Chrono::month_day md1{Chrono::January, Chrono::day{15}}; + Chrono::month_day md2{Chrono::February, Chrono::day{10}}; + Chrono::month_day md3{Chrono::January, Chrono::day{20}}; + + CHECK_TRUE(md1 < md2); // January < February + CHECK_TRUE(md1 < md3); // 15th < 20th in the same month + CHECK_FALSE(md2 < md1); // February !< January + CHECK_FALSE(md3 < md1); // 20th !< 15th in the same month + } + + //************************************************************************* + TEST(test_month_day_less_than_equal_operator) + { + Chrono::month_day md1{Chrono::January, Chrono::day{15}}; + Chrono::month_day md2{Chrono::February, Chrono::day{10}}; + Chrono::month_day md3{Chrono::January, Chrono::day{20}}; + + CHECK_TRUE(md1 <= md1); // January <= January + CHECK_TRUE(md1 <= md2); // January <= February + CHECK_TRUE(md1 <= md3); // 15th <= 20th in the same month + CHECK_FALSE(md2 <= md1); // February !<= January + CHECK_FALSE(md3 <= md1); // 20th !<= 15th in the same month + } + + //************************************************************************* + TEST(test_month_day_greater_than_operator) + { + Chrono::month_day md1{Chrono::January, Chrono::day{15}}; + Chrono::month_day md2{Chrono::February, Chrono::day{10}}; + Chrono::month_day md3{Chrono::January, Chrono::day{20}}; + + CHECK_TRUE(md2 > md1); // February > January + CHECK_TRUE(md3 > md1); // 20th > 15th in the same month + CHECK_FALSE(md1 > md2); // January !> February + CHECK_FALSE(md1 > md3); // 15th !> 20th in the same month + } + + //************************************************************************* + TEST(test_month_day_greater_than_equal_operator) + { + Chrono::month_day md1{Chrono::January, Chrono::day{15}}; + Chrono::month_day md2{Chrono::February, Chrono::day{10}}; + Chrono::month_day md3{Chrono::January, Chrono::day{20}}; + + CHECK_TRUE(md1 >= md1); // January >= January + CHECK_TRUE(md2 >= md1); // February >= January + CHECK_TRUE(md3 >= md1); // 20th >= 15th in the same month + CHECK_FALSE(md1 >= md2); // January !>= February + CHECK_FALSE(md1 >= md3); // 15th !>= 20th in the same month + } + + //************************************************************************* + TEST(test_month_day_min_max) + { + Chrono::month_day md_min{Chrono::January, Chrono::day{1}}; + Chrono::month_day md_max{Chrono::December, Chrono::day{31}}; + + CHECK_TRUE(md_min.ok()); + CHECK_TRUE(md_max.ok()); + + CHECK_EQUAL(Chrono::January, md_min.month()); + CHECK_EQUAL(Chrono::day{1}, md_min.day()); + + CHECK_EQUAL(Chrono::December, md_max.month()); + CHECK_EQUAL(Chrono::day{31}, md_max.day()); } -// //************************************************************************* -// TEST(test_constructor_in_range) -// { -// for (unsigned i = 0U; i < 256; ++i) -// { -// std::chrono::month std_month(i); -// etl::chrono::month month(i); -// -// CHECK_EQUAL(std_month.ok(), month.ok()); -// CHECK_EQUAL(unsigned(std_month), unsigned(month)); -// } -// } -// -// //************************************************************************* -// TEST(test_pre_increment) -// { -// std::chrono::month std_month(0); -// etl::chrono::month month(0); -// -// for (int i = 0; i < 255; ++i) -// { -// ++std_month; -// ++month; -// -// CHECK_EQUAL(std_month.ok(), month.ok()); -// CHECK_EQUAL(unsigned(std_month), unsigned(month)); -// } -// } -// -// //************************************************************************* -// TEST(test_post_increment) -// { -// std::chrono::month std_month(0); -// etl::chrono::month month(0); -// -// for (int i = 0; i < 256; ++i) -// { -// std::chrono::month std_last_month = std_month++; -// etl::chrono::month last_month = month++; -// -// CHECK_EQUAL(std_last_month.ok(), last_month.ok()); -// CHECK_EQUAL(unsigned(std_last_month), unsigned(last_month)); -// -// CHECK_EQUAL(std_month.ok(), month.ok()); -// CHECK_EQUAL(unsigned(std_month), unsigned(month)); -// } -// } -// -// //************************************************************************* -// TEST(test_pre_decrement) -// { -// std::chrono::month std_month(255); -// etl::chrono::month month(255); -// -// for (int i = 0; i < 256; ++i) -// { -// --std_month; -// --month; -// -// CHECK_EQUAL(std_month.ok(), month.ok()); -// CHECK_EQUAL(unsigned(std_month), unsigned(month)); -// } -// } -// -// //************************************************************************* -// TEST(test_post_decrement) -// { -// std::chrono::month std_month(255); -// etl::chrono::month month(255); -// -// for (int i = 0; i < 256; ++i) -// { -// std::chrono::month std_last_month = std_month--; -// etl::chrono::month last_month = month--; -// -// CHECK_EQUAL(std_last_month.ok(), last_month.ok()); -// CHECK_EQUAL(unsigned(std_last_month), unsigned(last_month)); -// -// CHECK_EQUAL(std_month.ok(), month.ok()); -// CHECK_EQUAL(unsigned(std_month), unsigned(month)); -// } -// } -// -// //************************************************************************* -// TEST(test_plus_equal_months) -// { -// for (int m = 0; m <= 12; ++m) -// { -// for (int ms = 0; ms <= 24; ++ms) -// { -// std::chrono::month std_month(m); -// etl::chrono::month month(m); -// -// std::chrono::months std_months(ms); -// etl::chrono::months months(ms); -// -// std_month += std_months; -// month += months; -// -// CHECK_EQUAL(std_month.ok(), month.ok()); -// CHECK_EQUAL(unsigned(std_month), unsigned(month)); -// } -// } -// } -// -// //************************************************************************* -// TEST(test_month_plus_months) -// { -// for (int m = 0; m <= 12; ++m) -// { -// for (int ms = 0; ms <= 24; ++ms) -// { -// std::chrono::month std_month(m); -// etl::chrono::month month(m); -// -// std::chrono::months std_months(ms); -// etl::chrono::months months(ms); -// -// std_month = std_month + std_months; -// month = month + months; -// -// CHECK_EQUAL(std_month.ok(), month.ok()); -// CHECK_EQUAL(unsigned(std_month), unsigned(month)); -// } -// } -// } -// -// //************************************************************************* -// TEST(test_months_plus_month) -// { -// for (int m = 0; m <= 12; ++m) -// { -// for (int ms = 0; ms <= 24; ++ms) -// { -// std::chrono::month std_month(m); -// etl::chrono::month month(m); -// -// std::chrono::months std_months(ms); -// etl::chrono::months months(ms); -// -// std_month = std_months + std_month; -// month = months + month; -// -// CHECK_EQUAL(std_month.ok(), month.ok()); -// CHECK_EQUAL(unsigned(std_month), unsigned(month)); -// } -// } -// } -// -// //************************************************************************* -// TEST(test_minus_equal_months) -// { -// for (int m = 0; m <= 12; ++m) -// { -// for (int ms = 0; ms <= 24; ++ms) -// { -// std::chrono::month std_month(m); -// etl::chrono::month month(m); -// -// std::chrono::months std_months(ms); -// etl::chrono::months months(ms); -// -// std_month -= std_months; -// month -= months; -// -// CHECK_EQUAL(std_month.ok(), month.ok()); -// CHECK_EQUAL(unsigned(std_month), unsigned(month)); -// } -// } -// } -// -// //************************************************************************* -// TEST(test_month_minus_months) -// { -// for (int m = 0; m <= 12; ++m) -// { -// for (int ms = 0; ms <= 24; ++ms) -// { -// std::chrono::month std_month(m); -// etl::chrono::month month(m); -// -// std::chrono::months std_months(ms); -// etl::chrono::months months(ms); -// -// std_month = std_month - std_months; -// month = month - months; -// -// CHECK_EQUAL(std_month.ok(), month.ok()); -// CHECK_EQUAL(unsigned(std_month), unsigned(month)); -// } -// } -// } -// -// //************************************************************************* -// TEST(test_month_minus_month) -// { -// for (int m = 0; m < 256; ++m) -// { -// std::chrono::month std_month1(m); -// std::chrono::month std_month2(255 - m); -// -// std::chrono::month month1(m); -// std::chrono::month month2(255 - m); -// -// auto std_months12 = std_month1 - std_month2; -// auto std_months21 = std_month2 - std_month1; -// -// auto months12 = month1 - month2; -// auto months21 = month2 - month1; -// -// CHECK_EQUAL(std_months12.count(), months12.count()); -// CHECK_EQUAL(std_months21.count(), months21.count()); -// } -// } -// -// //************************************************************************* -// TEST(test_min_max_month) -// { -// CHECK_EQUAL(1U, etl::chrono::month::min()); -// CHECK_EQUAL(12U, etl::chrono::month::max()); -// } -// -// //************************************************************************* -// TEST(test_literal_month) -// { -// using namespace etl::literals::chrono_literals; -// -// etl::chrono::month month1 = 1_month; -// etl::chrono::month month2 = 2_month; -// etl::chrono::month month3 = 3_month; -// etl::chrono::month month4 = 4_month; -// etl::chrono::month month5 = 5_month; -// etl::chrono::month month6 = 6_month; -// etl::chrono::month month7 = 7_month; -// etl::chrono::month month8 = 8_month; -// etl::chrono::month month9 = 9_month; -// etl::chrono::month month10 = 10_month; -// etl::chrono::month month11 = 11_month; -// etl::chrono::month month12 = 12_month; -// -// CHECK_TRUE(month1.ok()); -// CHECK_TRUE(month2.ok()); -// CHECK_TRUE(month3.ok()); -// CHECK_TRUE(month4.ok()); -// CHECK_TRUE(month5.ok()); -// CHECK_TRUE(month6.ok()); -// CHECK_TRUE(month7.ok()); -// CHECK_TRUE(month8.ok()); -// CHECK_TRUE(month9.ok()); -// CHECK_TRUE(month10.ok()); -// CHECK_TRUE(month11.ok()); -// CHECK_TRUE(month12.ok()); -// -// CHECK_EQUAL(1U, unsigned(month1)); -// CHECK_EQUAL(2U, unsigned(month2)); -// CHECK_EQUAL(3U, unsigned(month3)); -// CHECK_EQUAL(4U, unsigned(month4)); -// CHECK_EQUAL(5U, unsigned(month5)); -// CHECK_EQUAL(6U, unsigned(month6)); -// CHECK_EQUAL(7U, unsigned(month7)); -// CHECK_EQUAL(8U, unsigned(month8)); -// CHECK_EQUAL(9U, unsigned(month9)); -// CHECK_EQUAL(10U, unsigned(month10)); -// CHECK_EQUAL(11U, unsigned(month11)); -// CHECK_EQUAL(12U, unsigned(month12)); -// } -// -// //************************************************************************* -// TEST(test_month_comparison_operators) -// { -// etl::chrono::month month1(1); -// etl::chrono::month month2(2); -// -// CHECK_TRUE(month1 == month1); -// CHECK_FALSE(month1 != month1); -// CHECK_TRUE(month1 < month2); -// CHECK_FALSE(month1 < month1); -// CHECK_FALSE(month2 < month1); -// CHECK_TRUE(month1 <= month2); -// CHECK_TRUE(month1 <= month1); -// CHECK_FALSE(month2 <= month1); -// CHECK_FALSE(month1 > month2); -// CHECK_FALSE(month1 > month1); -// CHECK_TRUE(month2 > month1); -// CHECK_FALSE(month1 >= month2); -// CHECK_TRUE(month1 >= month1); -// CHECK_TRUE(month2 >= month1); -// -//#if ETL_USING_CPP20 -// CHECK_TRUE((month1 <=> month1) == 0); -// CHECK_TRUE((month1 <=> month2) < 0); -// CHECK_TRUE((month2 <=> month1) > 0); -//#endif -// } -// -// //************************************************************************* -// TEST(test_month_hashes_are_unique) -// { -// std::vector hashes; -// -// for (int i = 0; i < 256; ++i) -// { -// hashes.push_back(etl::hash()(etl::chrono::month(i))); -// } -// -// std::sort(hashes.begin(), hashes.end()); -// (void)std::unique(hashes.begin(), hashes.end()); -// CHECK_EQUAL(256U, hashes.size()); -// } -// -// //************************************************************************* -// TEST(test_month_types) -// { -// CHECK_EQUAL(static_cast(std::chrono::January), static_cast(etl::chrono::January)); -// CHECK_EQUAL(static_cast(std::chrono::February), static_cast(etl::chrono::February)); -// CHECK_EQUAL(static_cast(std::chrono::March), static_cast(etl::chrono::March)); -// CHECK_EQUAL(static_cast(std::chrono::April), static_cast(etl::chrono::April)); -// CHECK_EQUAL(static_cast(std::chrono::May), static_cast(etl::chrono::May)); -// CHECK_EQUAL(static_cast(std::chrono::June), static_cast(etl::chrono::June)); -// CHECK_EQUAL(static_cast(std::chrono::July), static_cast(etl::chrono::July)); -// CHECK_EQUAL(static_cast(std::chrono::August), static_cast(etl::chrono::August)); -// CHECK_EQUAL(static_cast(std::chrono::September), static_cast(etl::chrono::September)); -// CHECK_EQUAL(static_cast(std::chrono::October), static_cast(etl::chrono::October)); -// CHECK_EQUAL(static_cast(std::chrono::November), static_cast(etl::chrono::November)); -// CHECK_EQUAL(static_cast(std::chrono::December), static_cast(etl::chrono::December)); -// } }; } diff --git a/test/test_chrono_month_day_last.cpp b/test/test_chrono_month_day_last.cpp new file mode 100644 index 00000000..ec9b6ae4 --- /dev/null +++ b/test/test_chrono_month_day_last.cpp @@ -0,0 +1,130 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include +#include +#include + +// Set to 0 to reference against std::chrono +#define ETL_USING_ETL_CHRONO 1 + +#if ETL_USING_ETL_CHRONO + #define Chrono etl::chrono +#else + #if ETL_USING_CPP20 + #include + #define Chrono std::chrono + #else + #error std::chrono not supported + #endif +#endif + +namespace +{ + SUITE(test_chrono_month_day_last) + { + //************************************************************************* + TEST(test_constructor_in_range) + { + Chrono::month_day_last month_day_last_january(Chrono::January); + Chrono::month_day_last month_day_last_february(Chrono::February); + Chrono::month_day_last month_day_last_march(Chrono::March); + Chrono::month_day_last month_day_last_april(Chrono::April); + Chrono::month_day_last month_day_last_may(Chrono::May); + Chrono::month_day_last month_day_last_june(Chrono::June); + Chrono::month_day_last month_day_last_july(Chrono::July); + Chrono::month_day_last month_day_last_august(Chrono::August); + Chrono::month_day_last month_day_last_september(Chrono::September); + Chrono::month_day_last month_day_last_october(Chrono::October); + Chrono::month_day_last month_day_last_november(Chrono::November); + Chrono::month_day_last month_day_last_december(Chrono::December); + + CHECK_TRUE(month_day_last_january.ok()); + CHECK_TRUE(month_day_last_february.ok()); + CHECK_TRUE(month_day_last_march.ok()); + CHECK_TRUE(month_day_last_april.ok()); + CHECK_TRUE(month_day_last_may.ok()); + CHECK_TRUE(month_day_last_june.ok()); + CHECK_TRUE(month_day_last_july.ok()); + CHECK_TRUE(month_day_last_august.ok()); + CHECK_TRUE(month_day_last_september.ok()); + CHECK_TRUE(month_day_last_october.ok()); + CHECK_TRUE(month_day_last_november.ok()); + CHECK_TRUE(month_day_last_december.ok()); + } + + //************************************************************************* + TEST(test_month_day_last_comparison_operators) + { + Chrono::month_day_last month_day_last1(Chrono::January); + Chrono::month_day_last month_day_last2(Chrono::January); + Chrono::month_day_last month_day_last3(Chrono::February); + + CHECK_TRUE(month_day_last1 == month_day_last2); + CHECK_FALSE(month_day_last1 == month_day_last3); + + CHECK_FALSE(month_day_last1 != month_day_last2); + CHECK_TRUE(month_day_last1 != month_day_last3); + } + +#if ETL_USING_ETL_CHRONO + //************************************************************************* + TEST(test_month_day_last_hashes_are_unique) + { + std::vector hashes; + + for (int i = 0; i < 6; ++i) + { + hashes.push_back(etl::hash()(Chrono::month_day_last(Chrono::January))); + hashes.push_back(etl::hash()(Chrono::month_day_last(Chrono::February))); + hashes.push_back(etl::hash()(Chrono::month_day_last(Chrono::March))); + hashes.push_back(etl::hash()(Chrono::month_day_last(Chrono::April))); + hashes.push_back(etl::hash()(Chrono::month_day_last(Chrono::May))); + hashes.push_back(etl::hash()(Chrono::month_day_last(Chrono::June))); + hashes.push_back(etl::hash()(Chrono::month_day_last(Chrono::July))); + hashes.push_back(etl::hash()(Chrono::month_day_last(Chrono::August))); + hashes.push_back(etl::hash()(Chrono::month_day_last(Chrono::September))); + hashes.push_back(etl::hash()(Chrono::month_day_last(Chrono::October))); + hashes.push_back(etl::hash()(Chrono::month_day_last(Chrono::November))); + hashes.push_back(etl::hash()(Chrono::month_day_last(Chrono::December))); + } + + std::sort(hashes.begin(), hashes.end()); + (void)std::unique(hashes.begin(), hashes.end()); + } +#endif + }; +} diff --git a/test/test_chrono_month_weekday.cpp b/test/test_chrono_month_weekday.cpp new file mode 100644 index 00000000..2b21a88c --- /dev/null +++ b/test/test_chrono_month_weekday.cpp @@ -0,0 +1,126 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2024 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include +#include + +// Set to 0 to reference against std::chrono +#define ETL_USING_ETL_CHRONO 1 + +#if ETL_USING_ETL_CHRONO + #define Chrono etl::chrono +#else + #if ETL_USING_CPP20 + #include + #define Chrono std::chrono + #else + #error std::chrono not supported + #endif +#endif + +namespace +{ + SUITE(test_chrono_month_weekday) + { + //************************************************************************* + TEST(test_constructor_with_month_and_day) + { + Chrono::month_weekday mwd{ Chrono::January, Chrono::weekday_indexed(Chrono::Friday, 2) }; + + CHECK_TRUE(mwd.ok()); // Valid month_weekday + CHECK_EQUAL(Chrono::January, mwd.month()); + CHECK_EQUAL(Chrono::Friday.c_encoding(), mwd.weekday_indexed().weekday().c_encoding()); + CHECK_EQUAL(2, mwd.weekday_indexed().index()); + } + + //************************************************************************* + TEST(test_invalid_month_weekday) + { + Chrono::month_weekday mwd{Chrono::month{13}, Chrono::weekday_indexed(Chrono::Friday, 2)}; // Invalid month (13) + + CHECK_FALSE(mwd.ok()); // Invalid month_weekday + } + + //************************************************************************* + TEST(test_invalid_day_in_month_weekday) + { + Chrono::month_weekday mwd{Chrono::January, Chrono::weekday_indexed(Chrono::weekday{8}, 2)}; // Invalid day (8) + + CHECK_FALSE(mwd.ok()); // Invalid month_weekday + } + + //************************************************************************* + TEST(test_month_weekday_equality_operator) + { + Chrono::month_weekday mwd1{Chrono::January, Chrono::weekday_indexed(Chrono::Friday, 2)}; + Chrono::month_weekday mwd2{Chrono::February, Chrono::weekday_indexed(Chrono::Friday, 2)}; + Chrono::month_weekday mwd3{Chrono::January, Chrono::weekday_indexed(Chrono::Saturday, 2)}; + + CHECK_TRUE(mwd1 == mwd1); // January == January + CHECK_FALSE(mwd1 == mwd2); // January != February + CHECK_FALSE(mwd1 == mwd2); // Friday != Saturday + } + + //************************************************************************* + TEST(test_month_weekday_not_equality_operator) + { + Chrono::month_weekday mwd1{Chrono::January, Chrono::weekday_indexed(Chrono::Friday, 2)}; + Chrono::month_weekday mwd2{Chrono::February, Chrono::weekday_indexed(Chrono::Friday, 2)}; + Chrono::month_weekday mwd3{Chrono::January, Chrono::weekday_indexed(Chrono::Saturday, 2)}; + + CHECK_FALSE(mwd1 != mwd1); // January == January + CHECK_TRUE(mwd1 != mwd2); // January != February + CHECK_TRUE(mwd1 != mwd2); // Friday != Saturday + } + +#if ETL_USING_ETL_CHRONO + //************************************************************************* + TEST(test_month_weekday_hashes_are_unique) + { + std::vector hashes; + + for (int i = 0; i < 256; ++i) + { + hashes.push_back(etl::hash()(Chrono::month_weekday(Chrono::month((i % 12) + 1), Chrono::weekday_indexed(Chrono::weekday(i % 7), i % 5)))); + } + + std::sort(hashes.begin(), hashes.end()); + (void)std::unique(hashes.begin(), hashes.end()); + CHECK_EQUAL(256U, hashes.size()); + } +#endif + }; +} diff --git a/test/test_chrono_month_weekday_last.cpp b/test/test_chrono_month_weekday_last.cpp new file mode 100644 index 00000000..1a95d917 --- /dev/null +++ b/test/test_chrono_month_weekday_last.cpp @@ -0,0 +1,125 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2024 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include +#include + +// Set to 0 to reference against std::chrono +#define ETL_USING_ETL_CHRONO 1 + +#if ETL_USING_ETL_CHRONO + #define Chrono etl::chrono +#else + #if ETL_USING_CPP20 + #include + #define Chrono std::chrono + #else + #error std::chrono not supported + #endif +#endif + +namespace +{ + SUITE(test_chrono_month_weekday_last) + { + //************************************************************************* + TEST(test_constructor_with_month_and_day) + { + Chrono::month_weekday_last mwdl{ Chrono::January, Chrono::weekday_last(Chrono::Friday)}; + + CHECK_TRUE(mwdl.ok()); // Valid month_weekday_last + CHECK_EQUAL(Chrono::January, mwdl.month()); + CHECK_EQUAL(Chrono::Friday.c_encoding(), mwdl.weekday_last().weekday().c_encoding()); + } + + //************************************************************************* + TEST(test_invalid_month_weekday_last) + { + Chrono::month_weekday_last mwdl{Chrono::month{13}, Chrono::weekday_last(Chrono::Friday)}; // Invalid month (13) + + CHECK_FALSE(mwdl.ok()); // Invalid month_weekday_last + } + + //************************************************************************* + TEST(test_invalid_day_in_month_weekday_last) + { + Chrono::month_weekday_last mwdl{Chrono::January, Chrono::weekday_last(Chrono::weekday(8))}; // Invalid day (8) + + CHECK_FALSE(mwdl.ok()); // Invalid month_weekday_last + } + + //************************************************************************* + TEST(test_month_weekday_last_equality_operator) + { + Chrono::month_weekday_last mwd1{Chrono::January, Chrono::weekday_last(Chrono::Friday)}; + Chrono::month_weekday_last mwd2{Chrono::February, Chrono::weekday_last(Chrono::Friday)}; + Chrono::month_weekday_last mwd3{Chrono::January, Chrono::weekday_last(Chrono::Saturday)}; + + CHECK_TRUE(mwd1 == mwd1); // January == January + CHECK_FALSE(mwd1 == mwd2); // January != February + CHECK_FALSE(mwd1 == mwd2); // Friday != Saturday + } + + //************************************************************************* + TEST(test_month_weekday_last_not_equality_operator) + { + Chrono::month_weekday_last mwd1{Chrono::January, Chrono::weekday_last(Chrono::Friday)}; + Chrono::month_weekday_last mwd2{Chrono::February, Chrono::weekday_last(Chrono::Friday)}; + Chrono::month_weekday_last mwd3{Chrono::January, Chrono::weekday_last(Chrono::Saturday)}; + + CHECK_FALSE(mwd1 != mwd1); // January == January + CHECK_TRUE(mwd1 != mwd2); // January != February + CHECK_TRUE(mwd1 != mwd2); // Friday != Saturday + } + +#if ETL_USING_ETL_CHRONO + //************************************************************************* + TEST(test_month_weekday_last_hashes_are_unique) + { + std::vector hashes; + + for (int i = 0; i < 256; ++i) + { + hashes.push_back(etl::hash()(Chrono::month_weekday_last(Chrono::month((i % 12) + 1), Chrono::weekday_last(Chrono::weekday(i % 7))))); + } + + std::sort(hashes.begin(), hashes.end()); + (void)std::unique(hashes.begin(), hashes.end()); + CHECK_EQUAL(256U, hashes.size()); + } +#endif + }; +} diff --git a/test/test_chrono_weekday.cpp b/test/test_chrono_weekday.cpp index ca65b1ce..ec6cedc8 100644 --- a/test/test_chrono_weekday.cpp +++ b/test/test_chrono_weekday.cpp @@ -34,12 +34,25 @@ SOFTWARE. #include "etl/chrono.h" -#include - #include -#include #include +#include + +// Set to 0 to reference against std::chrono +#define ETL_USING_ETL_CHRONO 1 + +#if ETL_USING_ETL_CHRONO + #define Chrono etl::chrono +#else + #if ETL_USING_CPP20 + #include + #define Chrono std::chrono + #else + #error std::chrono not supported + #endif +#endif + namespace { SUITE(test_chrono_weekday) @@ -47,7 +60,7 @@ namespace //************************************************************************* TEST(test_default_constructor) { - etl::chrono::weekday weekday; + Chrono::weekday weekday; CHECK_FALSE(weekday.ok()); } @@ -57,7 +70,7 @@ namespace { for (unsigned i = 0U; i < 7U; ++i) { - etl::chrono::weekday weekday(i); + Chrono::weekday weekday(i); CHECK_TRUE(weekday.ok()); CHECK_EQUAL(i, weekday.c_encoding()); @@ -70,7 +83,7 @@ namespace { for (unsigned i = 8U; i < 256U; ++i) { - etl::chrono::weekday weekday(i); + Chrono::weekday weekday(i); CHECK_FALSE(weekday.ok()); CHECK_EQUAL(i, weekday.c_encoding()); @@ -81,7 +94,7 @@ namespace //************************************************************************* TEST(test_pre_increment) { - etl::chrono::weekday weekday(0); + Chrono::weekday weekday(0); unsigned count = 0; for (int i = 0; i < 255; ++i) @@ -98,12 +111,12 @@ namespace //************************************************************************* TEST(test_post_increment) { - etl::chrono::weekday weekday(0); + Chrono::weekday weekday(0); unsigned count = 0; for (int i = 0; i < 255; ++i) { - etl::chrono::weekday last_weekday = weekday++; + Chrono::weekday last_weekday = weekday++; unsigned last_count = count++; CHECK_TRUE(last_weekday.ok()); @@ -119,7 +132,7 @@ namespace //************************************************************************* TEST(test_pre_decrement) { - etl::chrono::weekday weekday(255U); + Chrono::weekday weekday(255U); unsigned count = 255U; for (int i = 0; i < 255; ++i) @@ -136,12 +149,12 @@ namespace //************************************************************************* TEST(test_post_decrement) { - etl::chrono::weekday weekday(255U); + Chrono::weekday weekday(255U); unsigned count = 255U; for (int i = 0; i < 255; ++i) { - etl::chrono::weekday last_weekday = weekday--; + Chrono::weekday last_weekday = weekday--; unsigned last_count = count--; if (last_count == 255U) @@ -170,8 +183,8 @@ namespace { for (unsigned ds = 0; ds <= 14; ++ds) { - etl::chrono::weekday weekday(wd); - etl::chrono::days days(ds); + Chrono::weekday weekday(wd); + Chrono::days days(ds); weekday += days; unsigned expected = (wd + ds) % 7; @@ -190,8 +203,8 @@ namespace { for (unsigned ds = 0; ds <= 14; ++ds) { - etl::chrono::weekday weekday(wd); - etl::chrono::days days(ds); + Chrono::weekday weekday(wd); + Chrono::days days(ds); weekday = weekday + days; unsigned expected = (wd + ds) % 7; @@ -210,8 +223,8 @@ namespace { for (unsigned ds = 0; ds <= 14; ++ds) { - etl::chrono::weekday weekday(wd); - etl::chrono::days days(ds); + Chrono::weekday weekday(wd); + Chrono::days days(ds); weekday = weekday + days; unsigned expected = (ds + wd) % 7; @@ -230,8 +243,8 @@ namespace { for (unsigned ds = 0; ds <= 14; ++ds) { - etl::chrono::weekday weekday(wd); - etl::chrono::days days(ds); + Chrono::weekday weekday(wd); + Chrono::days days(ds); weekday -= days; unsigned expected = ((wd + 7U) - (ds % 7U)) % 7U; @@ -250,8 +263,8 @@ namespace { for (unsigned ds = 0; ds <= 14; ++ds) { - etl::chrono::weekday weekday(wd); - etl::chrono::days days(ds); + Chrono::weekday weekday(wd); + Chrono::days days(ds); weekday = weekday - days; unsigned expected = ((wd + 7U) - (ds % 7U)) % 7U; @@ -268,11 +281,11 @@ namespace { for (int m = 0; m < 7; ++m) { - etl::chrono::weekday weekday1(m); - etl::chrono::weekday weekday2(7 - m); + Chrono::weekday weekday1(m); + Chrono::weekday weekday2(7 - m); - std::chrono::weekday std_weekday1(m); - std::chrono::weekday std_weekday2(7 - m); + Chrono::weekday std_weekday1(m); + Chrono::weekday std_weekday2(7 - m); auto days12 = weekday1 - weekday2; auto days21 = weekday2 - weekday1; @@ -285,37 +298,48 @@ namespace } } +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_min_max_weekday) { - CHECK_EQUAL(etl::chrono::Sunday.c_encoding(), etl::chrono::weekday::min().c_encoding()); - CHECK_EQUAL(etl::chrono::Saturday.c_encoding(), etl::chrono::weekday::max().c_encoding()); + CHECK_EQUAL(Chrono::Sunday.c_encoding(), Chrono::weekday::min()); + CHECK_EQUAL(Chrono::Saturday.c_encoding(), Chrono::weekday::max()); } +#endif //************************************************************************* TEST(test_weekday_constants) { - CHECK_EQUAL(0U, etl::chrono::Sunday.c_encoding()); - CHECK_EQUAL(1U, etl::chrono::Monday.c_encoding()); - CHECK_EQUAL(2U, etl::chrono::Tuesday.c_encoding()); - CHECK_EQUAL(3U, etl::chrono::Wednesday.c_encoding()); - CHECK_EQUAL(4U, etl::chrono::Thursday.c_encoding()); - CHECK_EQUAL(5U, etl::chrono::Friday.c_encoding()); - CHECK_EQUAL(6U, etl::chrono::Saturday.c_encoding()); + CHECK_EQUAL(0U, Chrono::Sunday.c_encoding()); + CHECK_EQUAL(1U, Chrono::Monday.c_encoding()); + CHECK_EQUAL(2U, Chrono::Tuesday.c_encoding()); + CHECK_EQUAL(3U, Chrono::Wednesday.c_encoding()); + CHECK_EQUAL(4U, Chrono::Thursday.c_encoding()); + CHECK_EQUAL(5U, Chrono::Friday.c_encoding()); + CHECK_EQUAL(6U, Chrono::Saturday.c_encoding()); + + CHECK_EQUAL(7U, Chrono::Sunday.iso_encoding()); + CHECK_EQUAL(1U, Chrono::Monday.iso_encoding()); + CHECK_EQUAL(2U, Chrono::Tuesday.iso_encoding()); + CHECK_EQUAL(3U, Chrono::Wednesday.iso_encoding()); + CHECK_EQUAL(4U, Chrono::Thursday.iso_encoding()); + CHECK_EQUAL(5U, Chrono::Friday.iso_encoding()); + CHECK_EQUAL(6U, Chrono::Saturday.iso_encoding()); } +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_weekday_literals) { using namespace etl::literals::chrono_literals; - etl::chrono::weekday weekday0 = 0_weekday; - etl::chrono::weekday weekday1 = 1_weekday; - etl::chrono::weekday weekday2 = 2_weekday; - etl::chrono::weekday weekday3 = 3_weekday; - etl::chrono::weekday weekday4 = 4_weekday; - etl::chrono::weekday weekday5 = 5_weekday; - etl::chrono::weekday weekday6 = 6_weekday; + Chrono::weekday weekday0 = 0_weekday; + Chrono::weekday weekday1 = 1_weekday; + Chrono::weekday weekday2 = 2_weekday; + Chrono::weekday weekday3 = 3_weekday; + Chrono::weekday weekday4 = 4_weekday; + Chrono::weekday weekday5 = 5_weekday; + Chrono::weekday weekday6 = 6_weekday; CHECK_TRUE(weekday0.ok()); CHECK_TRUE(weekday1.ok()); @@ -333,35 +357,38 @@ namespace CHECK_EQUAL(5U, weekday5.c_encoding()); CHECK_EQUAL(6U, weekday6.c_encoding()); } +#endif //************************************************************************* TEST(test_weekday_comparison_operators) { - etl::chrono::weekday weekday1(1); - etl::chrono::weekday weekday2(2); + Chrono::weekday weekday1(1); + Chrono::weekday weekday2(2); CHECK_TRUE(weekday1 == weekday1); CHECK_FALSE(weekday1 != weekday1); - CHECK_TRUE(weekday1 < weekday2); - CHECK_FALSE(weekday1 < weekday1); - CHECK_FALSE(weekday2 < weekday1); - CHECK_TRUE(weekday1 <= weekday2); - CHECK_TRUE(weekday1 <= weekday1); - CHECK_FALSE(weekday2 <= weekday1); - CHECK_FALSE(weekday1 > weekday2); - CHECK_FALSE(weekday1 > weekday1); - CHECK_TRUE(weekday2 > weekday1); - CHECK_FALSE(weekday1 >= weekday2); - CHECK_TRUE(weekday1 >= weekday1); - CHECK_TRUE(weekday2 >= weekday1); - -#if ETL_USING_CPP20 - CHECK_TRUE((weekday1 <=> weekday1) == 0); - CHECK_TRUE((weekday1 <=> weekday2) < 0); - CHECK_TRUE((weekday2 <=> weekday1) > 0); -#endif } + //************************************************************************* + TEST(test_weekday_index_operator_returning_weekday_indexed) + { + Chrono::weekday wd(Chrono::Friday); + Chrono::weekday_indexed wi = wd[2]; + + CHECK_EQUAL(2, wi.index()); + CHECK_EQUAL(Chrono::Friday.c_encoding(), wi.weekday().c_encoding()); + } + + //************************************************************************* + TEST(test_weekday_index_operator_returning_weekday_last) + { + Chrono::weekday wd(Chrono::Friday); + Chrono::weekday_last wl = wd[Chrono::last]; + + CHECK_EQUAL(Chrono::Friday.c_encoding(), wl.weekday().c_encoding()); + } + +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_weekday_hashes_are_unique) { @@ -369,12 +396,13 @@ namespace for (int i = 0; i < 256; ++i) { - hashes.push_back(etl::hash()(etl::chrono::weekday(i))); + hashes.push_back(etl::hash()(Chrono::weekday(i))); } std::sort(hashes.begin(), hashes.end()); (void)std::unique(hashes.begin(), hashes.end()); CHECK_EQUAL(256U, hashes.size()); } +#endif }; } diff --git a/test/test_chrono_weekday_indexed.cpp b/test/test_chrono_weekday_indexed.cpp index e690fc96..abaa6aad 100644 --- a/test/test_chrono_weekday_indexed.cpp +++ b/test/test_chrono_weekday_indexed.cpp @@ -34,12 +34,23 @@ SOFTWARE. #include "etl/chrono.h" -#include - #include -#include #include +// Set to 0 to reference against std::chrono +#define ETL_USING_ETL_CHRONO 1 + +#if ETL_USING_ETL_CHRONO + #define Chrono etl::chrono +#else + #if ETL_USING_CPP20 + #include + #define Chrono std::chrono + #else + #error std::chrono not supported + #endif +#endif + namespace { SUITE(test_chrono_weekday_indexed) @@ -47,7 +58,7 @@ namespace //************************************************************************* TEST(test_default_constructor) { - etl::chrono::weekday_indexed weekday_indexed; + Chrono::weekday_indexed weekday_indexed; CHECK_FALSE(weekday_indexed.ok()); } @@ -57,13 +68,13 @@ namespace { for (unsigned i = 1U; i < 5U; ++i) { - etl::chrono::weekday_indexed weekday_indexed_monday(etl::chrono::Monday, i); - etl::chrono::weekday_indexed weekday_indexed_tuesday(etl::chrono::Tuesday, i); - etl::chrono::weekday_indexed weekday_indexed_wednesday(etl::chrono::Wednesday, i); - etl::chrono::weekday_indexed weekday_indexed_thursday(etl::chrono::Thursday, i); - etl::chrono::weekday_indexed weekday_indexed_friday(etl::chrono::Friday, i); - etl::chrono::weekday_indexed weekday_indexed_saturday(etl::chrono::Saturday, i); - etl::chrono::weekday_indexed weekday_indexed_sunday(etl::chrono::Sunday, i); + Chrono::weekday_indexed weekday_indexed_monday(Chrono::Monday, i); + Chrono::weekday_indexed weekday_indexed_tuesday(Chrono::Tuesday, i); + Chrono::weekday_indexed weekday_indexed_wednesday(Chrono::Wednesday, i); + Chrono::weekday_indexed weekday_indexed_thursday(Chrono::Thursday, i); + Chrono::weekday_indexed weekday_indexed_friday(Chrono::Friday, i); + Chrono::weekday_indexed weekday_indexed_saturday(Chrono::Saturday, i); + Chrono::weekday_indexed weekday_indexed_sunday(Chrono::Sunday, i); CHECK_TRUE(weekday_indexed_monday.ok()); CHECK_TRUE(weekday_indexed_tuesday.ok()); @@ -73,13 +84,13 @@ namespace CHECK_TRUE(weekday_indexed_saturday.ok()); CHECK_TRUE(weekday_indexed_sunday.ok()); - CHECK_EQUAL(etl::chrono::Monday.c_encoding(), weekday_indexed_monday.weekday().c_encoding()); - CHECK_EQUAL(etl::chrono::Tuesday.c_encoding(), weekday_indexed_tuesday.weekday().c_encoding()); - CHECK_EQUAL(etl::chrono::Wednesday.c_encoding(), weekday_indexed_wednesday.weekday().c_encoding()); - CHECK_EQUAL(etl::chrono::Thursday.c_encoding(), weekday_indexed_thursday.weekday().c_encoding()); - CHECK_EQUAL(etl::chrono::Friday.c_encoding(), weekday_indexed_friday.weekday().c_encoding()); - CHECK_EQUAL(etl::chrono::Saturday.c_encoding(), weekday_indexed_saturday.weekday().c_encoding()); - CHECK_EQUAL(etl::chrono::Sunday.c_encoding(), weekday_indexed_sunday.weekday().c_encoding()); + CHECK_EQUAL(Chrono::Monday.c_encoding(), weekday_indexed_monday.weekday().c_encoding()); + CHECK_EQUAL(Chrono::Tuesday.c_encoding(), weekday_indexed_tuesday.weekday().c_encoding()); + CHECK_EQUAL(Chrono::Wednesday.c_encoding(), weekday_indexed_wednesday.weekday().c_encoding()); + CHECK_EQUAL(Chrono::Thursday.c_encoding(), weekday_indexed_thursday.weekday().c_encoding()); + CHECK_EQUAL(Chrono::Friday.c_encoding(), weekday_indexed_friday.weekday().c_encoding()); + CHECK_EQUAL(Chrono::Saturday.c_encoding(), weekday_indexed_saturday.weekday().c_encoding()); + CHECK_EQUAL(Chrono::Sunday.c_encoding(), weekday_indexed_sunday.weekday().c_encoding()); CHECK_EQUAL(i, weekday_indexed_monday.index()); CHECK_EQUAL(i, weekday_indexed_tuesday.index()); @@ -96,13 +107,13 @@ namespace { for (unsigned i = 6U; i < 256U; ++i) { - etl::chrono::weekday_indexed weekday_indexed_monday(etl::chrono::Monday, i); - etl::chrono::weekday_indexed weekday_indexed_tuesday(etl::chrono::Tuesday, i); - etl::chrono::weekday_indexed weekday_indexed_wednesday(etl::chrono::Wednesday, i); - etl::chrono::weekday_indexed weekday_indexed_thursday(etl::chrono::Thursday, i); - etl::chrono::weekday_indexed weekday_indexed_friday(etl::chrono::Friday, i); - etl::chrono::weekday_indexed weekday_indexed_saturday(etl::chrono::Saturday, i); - etl::chrono::weekday_indexed weekday_indexed_sunday(etl::chrono::Sunday, i); + Chrono::weekday_indexed weekday_indexed_monday(Chrono::Monday, i); + Chrono::weekday_indexed weekday_indexed_tuesday(Chrono::Tuesday, i); + Chrono::weekday_indexed weekday_indexed_wednesday(Chrono::Wednesday, i); + Chrono::weekday_indexed weekday_indexed_thursday(Chrono::Thursday, i); + Chrono::weekday_indexed weekday_indexed_friday(Chrono::Friday, i); + Chrono::weekday_indexed weekday_indexed_saturday(Chrono::Saturday, i); + Chrono::weekday_indexed weekday_indexed_sunday(Chrono::Sunday, i); CHECK_FALSE(weekday_indexed_monday.ok()); CHECK_FALSE(weekday_indexed_tuesday.ok()); @@ -117,16 +128,17 @@ namespace //************************************************************************* TEST(test_weekday_indexed_comparison_operators) { - etl::chrono::weekday_indexed weekday_indexed1(etl::chrono::Monday, 1); - etl::chrono::weekday_indexed weekday_indexed2(etl::chrono::Monday, 1); - etl::chrono::weekday_indexed weekday_indexed3(etl::chrono::Monday, 2); - etl::chrono::weekday_indexed weekday_indexed4(etl::chrono::Tuesday, 1); + Chrono::weekday_indexed weekday_indexed1(Chrono::Monday, 1); + Chrono::weekday_indexed weekday_indexed2(Chrono::Monday, 1); + Chrono::weekday_indexed weekday_indexed3(Chrono::Monday, 2); + Chrono::weekday_indexed weekday_indexed4(Chrono::Tuesday, 1); - CHECK_TRUE(weekday_indexed1 == weekday_indexed2); + CHECK_TRUE(weekday_indexed1 == weekday_indexed2); CHECK_FALSE(weekday_indexed1 == weekday_indexed3); CHECK_FALSE(weekday_indexed1 == weekday_indexed4); } +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_weekday_indexed_hashes_are_unique) { @@ -134,17 +146,18 @@ namespace for (int i = 0; i < 6; ++i) { - hashes.push_back(etl::hash()(etl::chrono::weekday_indexed(etl::chrono::Monday, i))); - hashes.push_back(etl::hash()(etl::chrono::weekday_indexed(etl::chrono::Tuesday, i))); - hashes.push_back(etl::hash()(etl::chrono::weekday_indexed(etl::chrono::Wednesday, i))); - hashes.push_back(etl::hash()(etl::chrono::weekday_indexed(etl::chrono::Thursday, i))); - hashes.push_back(etl::hash()(etl::chrono::weekday_indexed(etl::chrono::Friday, i))); - hashes.push_back(etl::hash()(etl::chrono::weekday_indexed(etl::chrono::Saturday, i))); - hashes.push_back(etl::hash()(etl::chrono::weekday_indexed(etl::chrono::Sunday, i))); + hashes.push_back(etl::hash()(Chrono::weekday_indexed(Chrono::Monday, i))); + hashes.push_back(etl::hash()(Chrono::weekday_indexed(Chrono::Tuesday, i))); + hashes.push_back(etl::hash()(Chrono::weekday_indexed(Chrono::Wednesday, i))); + hashes.push_back(etl::hash()(Chrono::weekday_indexed(Chrono::Thursday, i))); + hashes.push_back(etl::hash()(Chrono::weekday_indexed(Chrono::Friday, i))); + hashes.push_back(etl::hash()(Chrono::weekday_indexed(Chrono::Saturday, i))); + hashes.push_back(etl::hash()(Chrono::weekday_indexed(Chrono::Sunday, i))); } std::sort(hashes.begin(), hashes.end()); (void)std::unique(hashes.begin(), hashes.end()); } +#endif }; } diff --git a/test/test_chrono_weekday_last.cpp b/test/test_chrono_weekday_last.cpp index e2787a2e..a3a2a078 100644 --- a/test/test_chrono_weekday_last.cpp +++ b/test/test_chrono_weekday_last.cpp @@ -34,12 +34,24 @@ SOFTWARE. #include "etl/chrono.h" -#include - #include #include #include +// Set to 0 to reference against std::chrono +#define ETL_USING_ETL_CHRONO 1 + +#if ETL_USING_ETL_CHRONO + #define Chrono etl::chrono +#else + #if ETL_USING_CPP20 + #include + #define Chrono std::chrono + #else + #error std::chrono not supported + #endif +#endif + namespace { SUITE(test_chrono_weekday_last) @@ -49,13 +61,13 @@ namespace { for (unsigned i = 1U; i < 5U; ++i) { - etl::chrono::weekday_last weekday_last_monday(etl::chrono::Monday); - etl::chrono::weekday_last weekday_last_tuesday(etl::chrono::Tuesday); - etl::chrono::weekday_last weekday_last_wednesday(etl::chrono::Wednesday); - etl::chrono::weekday_last weekday_last_thursday(etl::chrono::Thursday); - etl::chrono::weekday_last weekday_last_friday(etl::chrono::Friday); - etl::chrono::weekday_last weekday_last_saturday(etl::chrono::Saturday); - etl::chrono::weekday_last weekday_last_sunday(etl::chrono::Sunday); + Chrono::weekday_last weekday_last_monday(Chrono::Monday); + Chrono::weekday_last weekday_last_tuesday(Chrono::Tuesday); + Chrono::weekday_last weekday_last_wednesday(Chrono::Wednesday); + Chrono::weekday_last weekday_last_thursday(Chrono::Thursday); + Chrono::weekday_last weekday_last_friday(Chrono::Friday); + Chrono::weekday_last weekday_last_saturday(Chrono::Saturday); + Chrono::weekday_last weekday_last_sunday(Chrono::Sunday); CHECK_TRUE(weekday_last_monday.ok()); CHECK_TRUE(weekday_last_tuesday.ok()); @@ -65,13 +77,13 @@ namespace CHECK_TRUE(weekday_last_saturday.ok()); CHECK_TRUE(weekday_last_sunday.ok()); - CHECK_EQUAL(etl::chrono::Monday.c_encoding(), weekday_last_monday.weekday().c_encoding()); - CHECK_EQUAL(etl::chrono::Tuesday.c_encoding(), weekday_last_tuesday.weekday().c_encoding()); - CHECK_EQUAL(etl::chrono::Wednesday.c_encoding(), weekday_last_wednesday.weekday().c_encoding()); - CHECK_EQUAL(etl::chrono::Thursday.c_encoding(), weekday_last_thursday.weekday().c_encoding()); - CHECK_EQUAL(etl::chrono::Friday.c_encoding(), weekday_last_friday.weekday().c_encoding()); - CHECK_EQUAL(etl::chrono::Saturday.c_encoding(), weekday_last_saturday.weekday().c_encoding()); - CHECK_EQUAL(etl::chrono::Sunday.c_encoding(), weekday_last_sunday.weekday().c_encoding()); + CHECK_EQUAL(Chrono::Monday.c_encoding(), weekday_last_monday.weekday().c_encoding()); + CHECK_EQUAL(Chrono::Tuesday.c_encoding(), weekday_last_tuesday.weekday().c_encoding()); + CHECK_EQUAL(Chrono::Wednesday.c_encoding(), weekday_last_wednesday.weekday().c_encoding()); + CHECK_EQUAL(Chrono::Thursday.c_encoding(), weekday_last_thursday.weekday().c_encoding()); + CHECK_EQUAL(Chrono::Friday.c_encoding(), weekday_last_friday.weekday().c_encoding()); + CHECK_EQUAL(Chrono::Saturday.c_encoding(), weekday_last_saturday.weekday().c_encoding()); + CHECK_EQUAL(Chrono::Sunday.c_encoding(), weekday_last_sunday.weekday().c_encoding()); } } @@ -80,8 +92,8 @@ namespace { for (unsigned i = 8U; i < 256U; ++i) { - auto wd = etl::chrono::weekday(i); - etl::chrono::weekday_last weekday_last(wd); + auto wd = Chrono::weekday(i); + Chrono::weekday_last weekday_last(wd); CHECK_FALSE(weekday_last.ok()); } @@ -90,9 +102,9 @@ namespace //************************************************************************* TEST(test_weekday_last_comparison_operators) { - etl::chrono::weekday_last weekday_last1(etl::chrono::Monday); - etl::chrono::weekday_last weekday_last2(etl::chrono::Monday); - etl::chrono::weekday_last weekday_last3(etl::chrono::Tuesday); + Chrono::weekday_last weekday_last1(Chrono::Monday); + Chrono::weekday_last weekday_last2(Chrono::Monday); + Chrono::weekday_last weekday_last3(Chrono::Tuesday); CHECK_TRUE(weekday_last1 == weekday_last2); CHECK_FALSE(weekday_last1 == weekday_last3); @@ -105,13 +117,13 @@ namespace for (int i = 0; i < 6; ++i) { - hashes.push_back(etl::hash()(etl::chrono::weekday_last(etl::chrono::Monday))); - hashes.push_back(etl::hash()(etl::chrono::weekday_last(etl::chrono::Tuesday))); - hashes.push_back(etl::hash()(etl::chrono::weekday_last(etl::chrono::Wednesday))); - hashes.push_back(etl::hash()(etl::chrono::weekday_last(etl::chrono::Thursday))); - hashes.push_back(etl::hash()(etl::chrono::weekday_last(etl::chrono::Friday))); - hashes.push_back(etl::hash()(etl::chrono::weekday_last(etl::chrono::Saturday))); - hashes.push_back(etl::hash()(etl::chrono::weekday_last(etl::chrono::Sunday))); + hashes.push_back(etl::hash()(Chrono::weekday_last(Chrono::Monday))); + hashes.push_back(etl::hash()(Chrono::weekday_last(Chrono::Tuesday))); + hashes.push_back(etl::hash()(Chrono::weekday_last(Chrono::Wednesday))); + hashes.push_back(etl::hash()(Chrono::weekday_last(Chrono::Thursday))); + hashes.push_back(etl::hash()(Chrono::weekday_last(Chrono::Friday))); + hashes.push_back(etl::hash()(Chrono::weekday_last(Chrono::Saturday))); + hashes.push_back(etl::hash()(Chrono::weekday_last(Chrono::Sunday))); } std::sort(hashes.begin(), hashes.end()); diff --git a/test/test_chrono_year.cpp b/test/test_chrono_year.cpp index a3b59450..47de4f70 100644 --- a/test/test_chrono_year.cpp +++ b/test/test_chrono_year.cpp @@ -34,9 +34,22 @@ SOFTWARE. #include "etl/chrono.h" -#include #include +// Set to 0 to reference against std::chrono +#define ETL_USING_ETL_CHRONO 1 + +#if ETL_USING_ETL_CHRONO + #define Chrono etl::chrono +#else + #if ETL_USING_CPP20 + #include + #define Chrono std::chrono + #else + #error std::chrono not supported + #endif +#endif + namespace { SUITE(test_chrono_year) @@ -44,10 +57,9 @@ namespace //************************************************************************* TEST(test_default_constructor) { - std::chrono::year std_year; etl::chrono::year year; - CHECK_EQUAL(std_year.ok(), year.ok()); + CHECK_TRUE(year.ok()); } //************************************************************************* @@ -55,7 +67,6 @@ namespace { for (int32_t i = -32767; i <= 32767; ++i) { - std::chrono::year std_year(i); etl::chrono::year year(i); CHECK_TRUE(year.ok()); @@ -83,189 +94,184 @@ namespace //************************************************************************* TEST(test_post_increment) { - std::chrono::year std_year(-32767); etl::chrono::year year(-32767); + int count = -32767; - for (int32_t i = 0; i < 65536; ++i) + for (int32_t i = 0; i < 65534; ++i) { - std::chrono::year std_last_year = std_year++; - etl::chrono::year last_year = year++; + etl::chrono::year last_year = year++; - CHECK_EQUAL(std_last_year.ok(), last_year.ok()); - CHECK_EQUAL(int(std_last_year), int(last_year)); + CHECK_TRUE(last_year.ok()); + CHECK_EQUAL(count, int(last_year)); - CHECK_EQUAL(std_year.ok(), year.ok()); - CHECK_EQUAL(int(std_year), int(year)); + ++count; + + CHECK_TRUE(year.ok()); + CHECK_EQUAL(count, int(year)); } } //************************************************************************* TEST(test_pre_decrement) { - std::chrono::year std_year(256); etl::chrono::year year(256); + int count = 256; for (int i = 0; i < 255; ++i) { - --std_year; --year; + --count; - CHECK_EQUAL(std_year.ok(), year.ok()); - CHECK_EQUAL(int(std_year), int(year)); + CHECK_TRUE(year.ok()); + CHECK_EQUAL(count, int(year)); } } //************************************************************************* TEST(test_post_decrement) { - std::chrono::year std_year(256); etl::chrono::year year(256); + int count = (int)year; for (int i = 0; i < 255; ++i) { - std::chrono::year std_last_year = std_year--; etl::chrono::year last_year = year--; - CHECK_EQUAL(std_last_year.ok(), last_year.ok()); - CHECK_EQUAL(int(std_last_year), int(last_year)); + CHECK_TRUE(last_year.ok()); + CHECK_EQUAL(count, int(last_year)); - CHECK_EQUAL(std_year.ok(), year.ok()); - CHECK_EQUAL(int(std_year), int(year)); + --count; + + CHECK_TRUE(year.ok()); + CHECK_EQUAL(count, int(year)); } } //************************************************************************* TEST(test_plus_equal_years) { - std::chrono::year std_year(0); etl::chrono::year year(0); - - std::chrono::years std_years(2); etl::chrono::years years(2); for (int i = 0; i < 128; ++i) { - std_year += std_years; - year += years; + year += years; - CHECK_EQUAL(std_year.ok(), year.ok()); - CHECK_EQUAL(int(std_year), int(year)); + CHECK_TRUE(year.ok()); + CHECK_EQUAL((2 * i) + 2, int(year)); } } //************************************************************************* TEST(test_year_plus_years) { - std::chrono::year std_year(0); etl::chrono::year year(0); - - std::chrono::years std_years(2); etl::chrono::years years(2); for (int i = 0; i < 128; ++i) { - std_year = std_year + std_years; - year = year + years; + year = year + years; - CHECK_EQUAL(std_year.ok(), year.ok()); - CHECK_EQUAL(int(std_year), int(year)); + CHECK_TRUE(year.ok()); + CHECK_EQUAL((2 * i) + 2, int(year)); } } //************************************************************************* TEST(test_years_plus_year) { - std::chrono::year std_year(0); etl::chrono::year year(0); - - std::chrono::years std_years(2); etl::chrono::years years(2); for (int i = 0; i < 128; ++i) { - std_year = std_years + std_year; - year = years + year; + year = years + year; - CHECK_EQUAL(std_year.ok(), year.ok()); - CHECK_EQUAL(int(std_year), int(year)); + CHECK_TRUE(year.ok()); + CHECK_EQUAL((2 * i) + 2, int(year)); } } //************************************************************************* TEST(test_minus_equal_years) { - std::chrono::year std_year(256); etl::chrono::year year(256); - - std::chrono::years std_years(2); etl::chrono::years years(2); for (int i = 0; i < 128; ++i) { - std_year -= std_years; - year -= years; + year -= years; - CHECK_EQUAL(std_year.ok(), year.ok()); - CHECK_EQUAL(int(std_year), int(year)); + CHECK_TRUE(year.ok()); + CHECK_EQUAL((256 - (2 * i)) - 2, int(year)); } } //************************************************************************* TEST(test_year_minus_years) { - std::chrono::year std_year(0); - etl::chrono::year year(0); - - std::chrono::years std_years(2); + etl::chrono::year year(256); etl::chrono::years years(2); for (int i = 0; i < 128; ++i) { - std_year = std_year - std_years; - year = year - years; + year = year - years; - CHECK_EQUAL(std_year.ok(), year.ok()); - CHECK_EQUAL(int(std_year), int(year)); + CHECK_TRUE(year.ok()); + CHECK_EQUAL((256 - (2 * i)) - 2, int(year)); } } //************************************************************************* TEST(test_year_minus_year) { - for (int i = 1; i < 31; ++i) + etl::chrono::year year(256); + etl::chrono::years years(2); + + for (int i = 0; i < 128; ++i) { - std::chrono::year std_year1(i); - std::chrono::year std_year2(31 - i); + year = years - year; - etl::chrono::year year1(i); - etl::chrono::year year2(31 - i); - - std::chrono::years std_years = std_year1 - std_year2; - etl::chrono::years years = year1 - year2; - - CHECK_EQUAL(std_years.count(), years.count()); + CHECK_TRUE(year.ok()); + CHECK_EQUAL((256 - (2 * i)) - 2, int(year)); } } + //************************************************************************* + TEST(test_is_leap) + { + for (int i = -32767; i <= 32767; ++i) + { + bool is_leap = ((i % 4) == 0) && ((i % 400) != 0); + + etl::chrono::year year(i); + + CHECK_EQUAL(is_leap, year.is_leap()); + } + } + + +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_min_max_year) { CHECK_EQUAL(-32767, etl::chrono::year::min()); CHECK_EQUAL(32767, etl::chrono::year::max()); } +#endif +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_literal_year) { - using namespace std::literals::chrono_literals; using namespace etl::literals::chrono_literals; - std::chrono::year std_year = 25y; - etl::chrono::year year = 25_year; + etl::chrono::year year = 25_year; - CHECK_EQUAL(std_year.ok(), year.ok()); - CHECK_EQUAL(int(std_year), int(year)); + CHECK_TRUE(year.ok()); + CHECK_EQUAL(25, int(year)); } +#endif //************************************************************************* TEST(test_year_comparison_operators) @@ -275,18 +281,6 @@ namespace CHECK_TRUE(year10 == year10); CHECK_FALSE(year10 != year10); - CHECK_TRUE(year10 < year20); - CHECK_FALSE(year10 < year10); - CHECK_FALSE(year20 < year10); - CHECK_TRUE(year10 <= year20); - CHECK_TRUE(year10 <= year10); - CHECK_FALSE(year20 <= year10); - CHECK_FALSE(year10 > year20); - CHECK_FALSE(year10 > year10); - CHECK_TRUE(year20 > year10); - CHECK_FALSE(year10 >= year20); - CHECK_TRUE(year10 >= year10); - CHECK_TRUE(year20 >= year10); #if ETL_USING_CPP20 CHECK_TRUE((year10 <=> year10) == 0); @@ -295,6 +289,7 @@ namespace #endif } +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_year_hashes_are_unique) { @@ -309,5 +304,6 @@ namespace (void)std::unique(hashes.begin(), hashes.end()); CHECK_EQUAL(65535U, hashes.size()); } +#endif }; } diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 65b50b51..8a7a4374 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -3183,10 +3183,9 @@ + - - @@ -8458,6 +8457,9 @@ + + + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index ff4fbc6f..f868361e 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -1398,12 +1398,6 @@ ETL\Private\chrono - - ETL\Private\chrono - - - ETL\Private\chrono - ETL\Private\chrono @@ -1494,6 +1488,9 @@ ETL\Private\chrono + + ETL\Private\chrono + @@ -3533,6 +3530,15 @@ Tests\Chrono + + Tests\Chrono + + + Tests\Chrono + + + Tests\Chrono + From d604d40648c9cadd5631bd76d111df49d71d2999 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 25 Apr 2025 18:07:43 +0100 Subject: [PATCH 19/33] Added etl::chrono::hh_mm_ss --- include/etl/chrono.h | 18 ++ include/etl/private/chrono/duration.h | 29 ++- include/etl/private/chrono/hh_mm_ss.h | 186 +++++++++++++++ include/etl/private/chrono/month_day.h | 10 +- include/etl/private/chrono/weekday.h | 2 +- test/CMakeLists.txt | 5 + test/test_chrono_hh_mm_ss.cpp | 289 ++++++++++++++++++++++++ test/test_chrono_month.cpp | 3 - test/test_chrono_month_day.cpp | 4 +- test/test_chrono_month_weekday.cpp | 2 - test/test_chrono_month_weekday_last.cpp | 4 +- test/test_chrono_weekday.cpp | 2 + test/test_chrono_year.cpp | 1 + test/vs2022/etl.vcxproj | 13 +- test/vs2022/etl.vcxproj.filters | 12 +- 15 files changed, 554 insertions(+), 26 deletions(-) create mode 100644 include/etl/private/chrono/hh_mm_ss.h create mode 100644 test/test_chrono_hh_mm_ss.cpp diff --git a/include/etl/chrono.h b/include/etl/chrono.h index 0c35a887..84674ea5 100644 --- a/include/etl/chrono.h +++ b/include/etl/chrono.h @@ -34,6 +34,7 @@ SOFTWARE. #define ETL_IN_CHRONO_H #include "platform.h" +#include "type_traits.h" #if ETL_NOT_USING_CPP11 #error NOT SUPPORTED FOR C++03 OR BELOW @@ -42,6 +43,22 @@ SOFTWARE. #include +namespace etl +{ + namespace chrono + { + template + struct treat_as_floating_point : etl::is_floating_point + { + }; + +#if ETL_USING_CPP17 + template + constexpr bool treat_as_floating_point_v = treat_as_floating_point::value; +#endif + } +} + #include "private/chrono/last_spec.h" #include "private/chrono/duration.h" #include "private/chrono/day.h" @@ -50,6 +67,7 @@ SOFTWARE. #include "private/chrono/month_day.h" #include "private/chrono/month_weekday.h" #include "private/chrono/year.h" +#include "private/chrono/hh_mm_ss.h" #include "private/chrono/operators.h" #endif diff --git a/include/etl/private/chrono/duration.h b/include/etl/private/chrono/duration.h index df6ee983..1b929709 100644 --- a/include/etl/private/chrono/duration.h +++ b/include/etl/private/chrono/duration.h @@ -130,20 +130,23 @@ namespace etl ETL_CONSTEXPR duration(const etl::chrono::duration& other) ETL_NOEXCEPT : value(etl::chrono::duration_cast >(other).count()) { - - bool b = etl::ratio_divide::den == 1; - ETL_STATIC_ASSERT(!(etl::is_integral::value && etl::is_floating_point::value), "Cannot convert duration from floating point to integral"); } + //*********************************************************************** + ETL_CONSTEXPR14 + etl::chrono::duration operator =(const etl::chrono::duration& other) ETL_NOEXCEPT + { + value = other.count(); + + return *this; + } + //*********************************************************************** template ETL_CONSTEXPR14 - typename etl::enable_if::den == 1, etl::chrono::duration&>::type - operator =(const etl::chrono::duration& other) ETL_NOEXCEPT + etl::chrono::duration operator =(const etl::chrono::duration& other) ETL_NOEXCEPT { - bool b = etl::ratio_divide::den == 1; - value = etl::chrono::duration_cast >(other).count(); return *this; @@ -185,6 +188,12 @@ namespace etl return etl::chrono::duration(etl::chrono::duration_values::max()); } + //*********************************************************************** + ETL_CONSTEXPR etl::chrono::duration absolute() const ETL_NOEXCEPT + { + return etl::chrono::duration(value < 0 ? -value : value); + } + //*********************************************************************** ETL_CONSTEXPR duration& operator ++() { @@ -350,6 +359,12 @@ namespace etl return TToDuration(static_cast((ct_count * ct_num) / ct_den)); } } + + template + struct is_duration : etl::false_type {}; + + template + struct is_duration> : etl::true_type {}; } //************************************************************************* diff --git a/include/etl/private/chrono/hh_mm_ss.h b/include/etl/private/chrono/hh_mm_ss.h new file mode 100644 index 00000000..b987c96d --- /dev/null +++ b/include/etl/private/chrono/hh_mm_ss.h @@ -0,0 +1,186 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +#include "../../absolute.h" +#include "../../power.h" + +namespace etl +{ + //*********************************************************************** + /// absolute + /// Enabled for etl::chrono::duration + //*********************************************************************** + template + ETL_NODISCARD + ETL_CONSTEXPR + typename etl::enable_if::value, TDuration>::type + absolute(TDuration dur) ETL_NOEXCEPT + { + return TDuration((dur.count() < 0) ? -dur.count() : dur.count()); + } + + namespace chrono + { + //*********************************************************************** + /// hh_mm_ss + //*********************************************************************** + template + class hh_mm_ss + { + public: + + //*********************************************************************** + // Fractional width for the duration's subseconds + //*********************************************************************** + static constexpr int fractional_width = []() constexpr + { + if (TDuration::period::den == 1) + { + return 0; + } + + int width = 0; + + for (auto den = TDuration::period::den; den > 1; den /= 10) + { + ++width; + } + + return width; + }(); + + //*********************************************************************** + /// The return type for to_duration. + //*********************************************************************** + using precision = etl::chrono::duration, + ratio<1, etl::power<10, fractional_width>::value>>; + + //*********************************************************************** + /// Default constructor. + //*********************************************************************** + ETL_NODISCARD + ETL_CONSTEXPR + hh_mm_ss() ETL_NOEXCEPT + : d(TDuration::zero()) + { + } + + //*********************************************************************** + /// Construct from duration. + //*********************************************************************** + ETL_NODISCARD + ETL_CONSTEXPR + explicit hh_mm_ss(TDuration d_) ETL_NOEXCEPT + : d(d_) + { + } + + //*********************************************************************** + /// Checks for negative duration. + //*********************************************************************** + ETL_NODISCARD + ETL_CONSTEXPR + bool is_negative() const ETL_NOEXCEPT + { + return d < TDuration::zero(); + } + + //*********************************************************************** + /// Returns the hours. + //*********************************************************************** + ETL_NODISCARD + ETL_CONSTEXPR + etl::chrono::hours hours() const ETL_NOEXCEPT + { + auto dur = etl::absolute(d); + + return etl::chrono::duration_cast(dur); + } + + //*********************************************************************** + /// Returns the minutes. + //*********************************************************************** + ETL_NODISCARD + ETL_CONSTEXPR etl::chrono::minutes minutes() const ETL_NOEXCEPT + { + auto dur = etl::absolute(d) - hours(); + + return etl::chrono::duration_cast(dur); + } + + //*********************************************************************** + /// Returns the seconds. + //*********************************************************************** + ETL_NODISCARD + ETL_CONSTEXPR + etl::chrono::seconds seconds() const ETL_NOEXCEPT + { + auto dur = etl::absolute(d) - hours() - minutes(); + + return etl::chrono::duration_cast(dur); + } + + //*********************************************************************** + /// Returns the subseconds. + //*********************************************************************** + ETL_NODISCARD + ETL_CONSTEXPR precision subseconds() const ETL_NOEXCEPT + { + return etl::absolute(d) - etl::chrono::duration_cast(etl::absolute(d)); + } + + //*********************************************************************** + /// Returns the duration. + //*********************************************************************** + ETL_CONSTEXPR explicit operator precision() const ETL_NOEXCEPT + { + return to_duration(); + } + + //*********************************************************************** + /// Returns the duration. + //*********************************************************************** + ETL_NODISCARD + ETL_CONSTEXPR + precision to_duration() const ETL_NOEXCEPT + { + return d; + } + + private: + + TDuration d; + }; + } +} diff --git a/include/etl/private/chrono/month_day.h b/include/etl/private/chrono/month_day.h index e58f62f0..171480b4 100644 --- a/include/etl/private/chrono/month_day.h +++ b/include/etl/private/chrono/month_day.h @@ -116,7 +116,7 @@ namespace etl //************************************************************************* /// Less-than operator. //************************************************************************* - friend ETL_NODISCARD ETL_CONSTEXPR + ETL_NODISCARD friend ETL_CONSTEXPR bool operator <(const etl::chrono::month_day& lhs, const etl::chrono::month_day& rhs) ETL_NOEXCEPT { @@ -137,7 +137,7 @@ namespace etl //************************************************************************* /// Less-than-equal operator. //************************************************************************* - friend ETL_NODISCARD ETL_CONSTEXPR + ETL_NODISCARD friend ETL_CONSTEXPR bool operator <=(const etl::chrono::month_day& lhs, const etl::chrono::month_day& rhs) ETL_NOEXCEPT { @@ -147,7 +147,7 @@ namespace etl //************************************************************************* /// Greater-than operator. //************************************************************************* - friend ETL_NODISCARD ETL_CONSTEXPR + ETL_NODISCARD friend ETL_CONSTEXPR bool operator >(const etl::chrono::month_day& lhs, const etl::chrono::month_day& rhs) ETL_NOEXCEPT { @@ -157,7 +157,7 @@ namespace etl //************************************************************************* /// Greater-than-equal operator. //************************************************************************* - friend ETL_NODISCARD ETL_CONSTEXPR + ETL_NODISCARD friend ETL_CONSTEXPR bool operator >=(const etl::chrono::month_day& lhs, const etl::chrono::month_day& rhs) ETL_NOEXCEPT { @@ -168,7 +168,7 @@ namespace etl /// Spaceship operator //*********************************************************************** #if ETL_USING_CPP20 - friend [[nodiscard]] constexpr auto operator <=>(const etl::chrono::month_day& lhs, + [[nodiscard]] friend constexpr auto operator <=>(const etl::chrono::month_day& lhs, const etl::chrono::month_day& rhs) noexcept { auto cmp = lhs.month() <=> rhs.month(); diff --git a/include/etl/private/chrono/weekday.h b/include/etl/private/chrono/weekday.h index e434ef56..f5e763ef 100644 --- a/include/etl/private/chrono/weekday.h +++ b/include/etl/private/chrono/weekday.h @@ -468,7 +468,7 @@ namespace etl //*********************************************************************** /// Index operator from etl::chrono::last_spec //*********************************************************************** - ETL_CONSTEXPR etl::chrono::weekday_last etl::chrono::weekday::operator[](etl::chrono::last_spec last) const ETL_NOEXCEPT + ETL_CONSTEXPR etl::chrono::weekday_last etl::chrono::weekday::operator[](etl::chrono::last_spec) const ETL_NOEXCEPT { return etl::chrono::weekday_last(*this); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bac99736..d5781a44 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -60,7 +60,12 @@ add_executable(etl_tests # test_checksum.cpp test_chrono_day.cpp test_chrono_duration.cpp + test_chrono_hh_mm_ss.cpp test_chrono_month.cpp + test_chrono_month_day.cpp + test_chrono_month_day_last.cpp + test_chrono_month_weekday.cpp + test_chrono_month_weekday_last.cpp test_chrono_weekday.cpp test_chrono_weekday_indexed.cpp test_chrono_weekday_last.cpp diff --git a/test/test_chrono_hh_mm_ss.cpp b/test/test_chrono_hh_mm_ss.cpp new file mode 100644 index 00000000..887bb42f --- /dev/null +++ b/test/test_chrono_hh_mm_ss.cpp @@ -0,0 +1,289 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +// Set to 0 to reference against std::chrono +#define ETL_USING_ETL_CHRONO 1 + +#if ETL_USING_ETL_CHRONO + #define Chrono etl::chrono + #define Ratio etl::ratio +#else + #if ETL_USING_CPP20 + #include + #define Chrono std::chrono + #define Ratio std::ratio + #else + #error std::chrono not supported + #endif +#endif + +namespace +{ + SUITE(test_chrono_hh_mm_ss) + { + //************************************************************************* + TEST(test_default_constructor) + { + using duration_type = Chrono::seconds; + + // Create a duration of 0 hour, 0 minutes, 0 seconds + Chrono::hh_mm_ss time; + + auto h = time.hours(); + auto m = time.minutes(); + auto s = time.seconds(); + auto sub = time.subseconds(); + auto dur = time.to_duration(); + + CHECK_EQUAL(Chrono::hours(0).count(), h.count()); + CHECK_EQUAL(Chrono::minutes(0).count(), m.count()); + CHECK_EQUAL(Chrono::seconds(0).count(), s.count()); + CHECK_EQUAL(duration_type(0).count(), sub.count()); + CHECK_EQUAL(0, dur.count()); + CHECK_FALSE(time.is_negative()); + CHECK_EQUAL(0, time.fractional_width); + CHECK_TRUE((std::is_same::precision>::value)); + } + + //************************************************************************* + TEST(test_construction_with_seconds) + { + using duration_type = Chrono::seconds; + + // Create a duration of 1 hour, 2 minutes, 3 seconds + duration_type duration = Chrono::hours(1) + Chrono::minutes(2) + Chrono::seconds(3); + + Chrono::hh_mm_ss time(duration); + + auto h = time.hours(); + auto m = time.minutes(); + auto s = time.seconds(); + auto sub = time.subseconds(); + auto dur = time.to_duration(); + + CHECK_EQUAL(Chrono::hours(1).count(), h.count()); + CHECK_EQUAL(Chrono::minutes(2).count(), m.count()); + CHECK_EQUAL(Chrono::seconds(3).count(), s.count()); + CHECK_EQUAL(duration_type(0).count(), sub.count()); + CHECK_EQUAL(3723, dur.count()); + CHECK_FALSE(time.is_negative()); + CHECK_EQUAL(0, time.fractional_width); + CHECK_TRUE((std::is_same::precision>::value)); + } + + //************************************************************************* + TEST(test_construction_with_negative_seconds) + { + using duration_type = Chrono::seconds; + + // Create a duration of minus 1 hour, 2 minutes, 3 seconds + duration_type duration = -(Chrono::hours(1) + Chrono::minutes(2) + Chrono::seconds(3)); + + Chrono::hh_mm_ss time(duration); + + auto h = time.hours(); + auto m = time.minutes(); + auto s = time.seconds(); + auto sub = time.subseconds(); + auto dur = time.to_duration(); + + CHECK_EQUAL(Chrono::hours(1).count(), h.count()); + CHECK_EQUAL(Chrono::minutes(2).count(), m.count()); + CHECK_EQUAL(Chrono::seconds(3).count(), s.count()); + CHECK_EQUAL(duration_type(0).count(), sub.count()); + CHECK_EQUAL(-3723, dur.count()); + CHECK_TRUE(time.is_negative()); + CHECK_EQUAL(0, time.fractional_width); + CHECK_TRUE((std::is_same::precision>::value)); + } + + //************************************************************************* + TEST(test_construction_with_milliseconds) + { + using duration_type = Chrono::milliseconds; + + // Create a duration of 1 hour, 2 minutes, 3 seconds, 456 milliseconds + duration_type duration = Chrono::hours(1) + Chrono::minutes(2) + Chrono::seconds(3) + duration_type(456); + + Chrono::hh_mm_ss time(duration); + + auto h = time.hours(); + auto m = time.minutes(); + auto s = time.seconds(); + auto sub = time.subseconds(); + auto dur = time.to_duration(); + + CHECK_EQUAL(Chrono::hours(1).count(), h.count()); + CHECK_EQUAL(Chrono::minutes(2).count(), m.count()); + CHECK_EQUAL(Chrono::seconds(3).count(), s.count()); + CHECK_EQUAL(duration_type(456).count(), sub.count()); + CHECK_EQUAL(3723456, dur.count()); + CHECK_FALSE(time.is_negative()); + CHECK_EQUAL(3, time.fractional_width); + CHECK_TRUE((std::is_same::precision>::value)); + } + + //************************************************************************* + TEST(test_construction_with_negative_milliseconds) + { + using duration_type = Chrono::milliseconds; + + // Create a duration of minus 1 hour, 2 minutes, 3 seconds, 456 milliseconds + duration_type duration = -(Chrono::hours(1) + Chrono::minutes(2) + Chrono::seconds(3) + duration_type(456)); + + Chrono::hh_mm_ss time(duration); + + auto h = time.hours(); + auto m = time.minutes(); + auto s = time.seconds(); + auto sub = time.subseconds(); + auto dur = time.to_duration(); + + CHECK_EQUAL(Chrono::hours(1).count(), h.count()); + CHECK_EQUAL(Chrono::minutes(2).count(), m.count()); + CHECK_EQUAL(Chrono::seconds(3).count(), s.count()); + CHECK_EQUAL(duration_type(456).count(), sub.count()); + CHECK_EQUAL(-3723456, dur.count()); + CHECK_TRUE(time.is_negative()); + CHECK_EQUAL(3, time.fractional_width); + CHECK_TRUE((std::is_same::precision>::value)); + } + + //************************************************************************* + TEST(test_construction_with_float_seconds) + { + using duration_type = Chrono::duration>; + + // Create a duration of 1 hour, 2 minutes, 3.456 seconds + duration_type duration = Chrono::hours(1) + Chrono::minutes(2) + duration_type(3.456); + + Chrono::hh_mm_ss time(duration); + + auto h = time.hours(); + auto m = time.minutes(); + auto s = time.seconds(); + auto sub = time.subseconds(); + auto dur = time.to_duration(); + + CHECK_EQUAL(1, h.count()); + CHECK_EQUAL(2, m.count()); + CHECK_EQUAL(3, s.count()); + CHECK_CLOSE(0.456f, sub.count(), 0.0001f); + CHECK_CLOSE(3723.456f, dur.count(), 0.0001f); + CHECK_FALSE(time.is_negative()); + CHECK_EQUAL(0, time.fractional_width); + CHECK_TRUE((std::is_same::precision>::value)); + } + + //************************************************************************* + TEST(test_construction_with_negative_float_seconds) + { + using duration_type = Chrono::duration>; + + // Create a duration of 1 hour, 2 minutes, 3.456 seconds + duration_type duration = -(Chrono::hours(1) + Chrono::minutes(2) + duration_type(3.456)); + + Chrono::hh_mm_ss time(duration); + + auto h = time.hours(); + auto m = time.minutes(); + auto s = time.seconds(); + auto sub = time.subseconds(); + auto dur = time.to_duration(); + + CHECK_EQUAL(1, h.count()); + CHECK_EQUAL(2, m.count()); + CHECK_EQUAL(3, s.count()); + CHECK_CLOSE(0.456f, sub.count(), 0.0001f); + CHECK_CLOSE(-3723.456f, dur.count(), 0.0001f); + CHECK_TRUE(time.is_negative()); + CHECK_EQUAL(0, time.fractional_width); + CHECK_TRUE((std::is_same::precision>::value)); + } + + //************************************************************************* + TEST(test_construction_with_double_seconds) + { + using duration_type = Chrono::duration>; + + // Create a duration of 1 hour, 2 minutes, 3.456 seconds + duration_type duration = Chrono::hours(1) + Chrono::minutes(2) + duration_type(3.456); + + Chrono::hh_mm_ss time(duration); + + auto h = time.hours(); + auto m = time.minutes(); + auto s = time.seconds(); + auto sub = time.subseconds(); + auto dur = time.to_duration(); + + CHECK_EQUAL(1, h.count()); + CHECK_EQUAL(2, m.count()); + CHECK_EQUAL(3, s.count()); + CHECK_CLOSE(0.456, sub.count(), 0.0001); + CHECK_CLOSE(3723.456, dur.count(), 0.0001); + CHECK_FALSE(time.is_negative()); + CHECK_EQUAL(0, time.fractional_width); + CHECK_TRUE((std::is_same::precision>::value)); + } + + //************************************************************************* + TEST(test_construction_with_negative_double_seconds) + { + using duration_type = Chrono::duration>; + + // Create a duration of 1 hour, 2 minutes, 3.456 seconds + duration_type duration = -(Chrono::hours(1) + Chrono::minutes(2) + duration_type(3.456)); + + Chrono::hh_mm_ss time(duration); + + auto h = time.hours(); + auto m = time.minutes(); + auto s = time.seconds(); + auto sub = time.subseconds(); + auto dur = time.to_duration(); + + CHECK_EQUAL(1, h.count()); + CHECK_EQUAL(2, m.count()); + CHECK_EQUAL(3, s.count()); + CHECK_CLOSE(0.456, sub.count(), 0.0001); + CHECK_CLOSE(-3723.456, dur.count(), 0.0001); + CHECK_TRUE(time.is_negative()); + CHECK_EQUAL(0, time.fractional_width); + CHECK_TRUE((std::is_same::precision>::value)); + } + }; +} diff --git a/test/test_chrono_month.cpp b/test/test_chrono_month.cpp index 058f260a..2a5f2531 100644 --- a/test/test_chrono_month.cpp +++ b/test/test_chrono_month.cpp @@ -258,9 +258,6 @@ namespace Chrono::months months12 = month1 - month2; Chrono::months months21 = month2 - month1; - int m12 = months12.count(); - int m21 = months21.count(); - int difference12 = expected_month(m1) - expected_month(m2); int difference21 = expected_month(m2) - expected_month(m1); diff --git a/test/test_chrono_month_day.cpp b/test/test_chrono_month_day.cpp index af5d00fc..edd32e0e 100644 --- a/test/test_chrono_month_day.cpp +++ b/test/test_chrono_month_day.cpp @@ -126,7 +126,7 @@ namespace CHECK_TRUE(md1 == md1); // January == January CHECK_FALSE(md1 == md2); // January != February - CHECK_FALSE(md1 == md2); // 20th != 15th in the same month + CHECK_FALSE(md1 == md3); // 20th != 15th in the same month } //************************************************************************* @@ -138,7 +138,7 @@ namespace CHECK_FALSE(md1 != md1); // January == January CHECK_TRUE(md1 != md2); // January != February - CHECK_TRUE(md1 != md2); // 20th != 15th in the same month + CHECK_TRUE(md1 != md3); // 20th != 15th in the same month } //************************************************************************* diff --git a/test/test_chrono_month_weekday.cpp b/test/test_chrono_month_weekday.cpp index 2b21a88c..29b532ab 100644 --- a/test/test_chrono_month_weekday.cpp +++ b/test/test_chrono_month_weekday.cpp @@ -87,7 +87,6 @@ namespace { Chrono::month_weekday mwd1{Chrono::January, Chrono::weekday_indexed(Chrono::Friday, 2)}; Chrono::month_weekday mwd2{Chrono::February, Chrono::weekday_indexed(Chrono::Friday, 2)}; - Chrono::month_weekday mwd3{Chrono::January, Chrono::weekday_indexed(Chrono::Saturday, 2)}; CHECK_TRUE(mwd1 == mwd1); // January == January CHECK_FALSE(mwd1 == mwd2); // January != February @@ -99,7 +98,6 @@ namespace { Chrono::month_weekday mwd1{Chrono::January, Chrono::weekday_indexed(Chrono::Friday, 2)}; Chrono::month_weekday mwd2{Chrono::February, Chrono::weekday_indexed(Chrono::Friday, 2)}; - Chrono::month_weekday mwd3{Chrono::January, Chrono::weekday_indexed(Chrono::Saturday, 2)}; CHECK_FALSE(mwd1 != mwd1); // January == January CHECK_TRUE(mwd1 != mwd2); // January != February diff --git a/test/test_chrono_month_weekday_last.cpp b/test/test_chrono_month_weekday_last.cpp index 1a95d917..a79fe0e1 100644 --- a/test/test_chrono_month_weekday_last.cpp +++ b/test/test_chrono_month_weekday_last.cpp @@ -90,7 +90,7 @@ namespace CHECK_TRUE(mwd1 == mwd1); // January == January CHECK_FALSE(mwd1 == mwd2); // January != February - CHECK_FALSE(mwd1 == mwd2); // Friday != Saturday + CHECK_FALSE(mwd1 == mwd3); // Friday != Saturday } //************************************************************************* @@ -102,7 +102,7 @@ namespace CHECK_FALSE(mwd1 != mwd1); // January == January CHECK_TRUE(mwd1 != mwd2); // January != February - CHECK_TRUE(mwd1 != mwd2); // Friday != Saturday + CHECK_TRUE(mwd1 != mwd3); // Friday != Saturday } #if ETL_USING_ETL_CHRONO diff --git a/test/test_chrono_weekday.cpp b/test/test_chrono_weekday.cpp index ec6cedc8..d6a4a3e8 100644 --- a/test/test_chrono_weekday.cpp +++ b/test/test_chrono_weekday.cpp @@ -367,6 +367,8 @@ namespace CHECK_TRUE(weekday1 == weekday1); CHECK_FALSE(weekday1 != weekday1); + CHECK_FALSE(weekday1 == weekday2); + CHECK_TRUE(weekday1 != weekday2); } //************************************************************************* diff --git a/test/test_chrono_year.cpp b/test/test_chrono_year.cpp index 47de4f70..70c17c8a 100644 --- a/test/test_chrono_year.cpp +++ b/test/test_chrono_year.cpp @@ -34,6 +34,7 @@ SOFTWARE. #include "etl/chrono.h" +#include #include // Set to 0 to reference against std::chrono diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 8a7a4374..90fa9853 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -1419,7 +1419,7 @@ /Zc:__cplusplus %(AdditionalOptions) true EnableFastChecks - true + false Console @@ -1444,6 +1444,7 @@ ProgramDatabase /Zc:__cplusplus %(AdditionalOptions) true + false Console @@ -1470,6 +1471,7 @@ /Zc:__cplusplus %(AdditionalOptions) true Default + false Console @@ -1494,6 +1496,7 @@ ProgramDatabase /Zc:__cplusplus %(AdditionalOptions) true + false Console @@ -1518,6 +1521,7 @@ ProgramDatabase /Zc:__cplusplus %(AdditionalOptions) true + false Console @@ -1542,6 +1546,7 @@ ProgramDatabase /Zc:__cplusplus %(AdditionalOptions) true + false Console @@ -1566,6 +1571,7 @@ EditAndContinue /Zc:__cplusplus %(AdditionalOptions) true + false Console @@ -1591,6 +1597,7 @@ /Zc:__cplusplus %(AdditionalOptions) true Default + false Console @@ -1616,6 +1623,7 @@ /Zc:__cplusplus %(AdditionalOptions) true Default + false Console @@ -1825,6 +1833,7 @@ ProgramDatabase /Zc:__cplusplus %(AdditionalOptions) true + false Console @@ -3180,6 +3189,7 @@ + @@ -8455,6 +8465,7 @@ + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index f868361e..4f5baf9e 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -1491,6 +1491,9 @@ ETL\Private\chrono + + ETL\Private\chrono + @@ -3512,9 +3515,6 @@ Tests\Containers - - Tests - Tests\Chrono @@ -3539,6 +3539,12 @@ Tests\Chrono + + Tests\Chrono + + + Tests\Syntax Checks\Source + From 4485a90c0497d299b10ad97177da72a4e2b68da7 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Fri, 25 Apr 2025 19:21:41 +0100 Subject: [PATCH 20/33] Added etl::chrono::year_month --- include/etl/chrono.h | 2 + include/etl/private/chrono/hh_mm_ss.h | 2 + include/etl/private/chrono/year.h | 2 +- include/etl/private/chrono/year_month.h | 233 ++++++++++++++++++++++++ test/CMakeLists.txt | 1 + test/test_chrono_operators.cpp | 64 +++++++ test/test_chrono_year_month.cpp | 144 +++++++++++++++ test/vs2022/etl.vcxproj | 2 + test/vs2022/etl.vcxproj.filters | 6 + 9 files changed, 455 insertions(+), 1 deletion(-) create mode 100644 include/etl/private/chrono/year_month.h create mode 100644 test/test_chrono_operators.cpp create mode 100644 test/test_chrono_year_month.cpp diff --git a/include/etl/chrono.h b/include/etl/chrono.h index 84674ea5..2d20db82 100644 --- a/include/etl/chrono.h +++ b/include/etl/chrono.h @@ -35,6 +35,7 @@ SOFTWARE. #include "platform.h" #include "type_traits.h" +#include "integral_limits.h" #if ETL_NOT_USING_CPP11 #error NOT SUPPORTED FOR C++03 OR BELOW @@ -67,6 +68,7 @@ namespace etl #include "private/chrono/month_day.h" #include "private/chrono/month_weekday.h" #include "private/chrono/year.h" +#include "private/chrono/year_month.h" #include "private/chrono/hh_mm_ss.h" #include "private/chrono/operators.h" #endif diff --git a/include/etl/private/chrono/hh_mm_ss.h b/include/etl/private/chrono/hh_mm_ss.h index b987c96d..90b9eeb7 100644 --- a/include/etl/private/chrono/hh_mm_ss.h +++ b/include/etl/private/chrono/hh_mm_ss.h @@ -60,6 +60,8 @@ namespace etl { public: + ETL_STATIC_ASSERT(etl::chrono::is_duration::value, "TDuration not etl::chrono::duration"); + //*********************************************************************** // Fractional width for the duration's subseconds //*********************************************************************** diff --git a/include/etl/private/chrono/year.h b/include/etl/private/chrono/year.h index 84306f78..df90770d 100644 --- a/include/etl/private/chrono/year.h +++ b/include/etl/private/chrono/year.h @@ -144,7 +144,7 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR bool ok() const ETL_NOEXCEPT { - return (value != -32768); + return (value != etl::integral_limits::min); } //*********************************************************************** diff --git a/include/etl/private/chrono/year_month.h b/include/etl/private/chrono/year_month.h new file mode 100644 index 00000000..3c76033b --- /dev/null +++ b/include/etl/private/chrono/year_month.h @@ -0,0 +1,233 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2023 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +namespace etl +{ + namespace chrono + { + class year_month + { + public: + + //************************************************************************* + /// Default constructor. + //************************************************************************* + year_month() + : y(etl::integral_limits::min) + , m(0) + { + } + + //************************************************************************* + /// Construct from month and day. + //************************************************************************* + ETL_CONSTEXPR year_month(const etl::chrono::year& y_, const etl::chrono::month& m_) ETL_NOEXCEPT + : y(y_) + , m(m_) + { + } + + //************************************************************************* + /// Returns the year. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::year year() const ETL_NOEXCEPT + { + return y; + } + + //************************************************************************* + /// Returns the month. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::month month() const ETL_NOEXCEPT + { + return m; + } + + //************************************************************************* + /// Returns true if the month/day is valid. + //************************************************************************* + ETL_CONSTEXPR14 bool ok() const ETL_NOEXCEPT + { + return y.ok() && m.ok(); + } + + //************************************************************************* + /// Adds etl::chrono::years + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month operator +(const etl::chrono::year_month& ym, + const etl::chrono::years& dy) ETL_NOEXCEPT + { + return etl::chrono::year_month(ym.year() + dy, ym.month()); + } + + //************************************************************************* + /// Adds etl::chrono::years + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month operator +(const etl::chrono::years& dy, + const etl::chrono::year_month& ym) ETL_NOEXCEPT + { + return etl::chrono::year_month(ym.year() + dy, ym.month()); + } + + //************************************************************************* + /// Adds etl::chrono::months + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month operator +(const etl::chrono::year_month& ym, + const etl::chrono::months& dm) ETL_NOEXCEPT + { + return etl::chrono::year_month(ym.year(), ym.month() + dm); + } + + //************************************************************************* + /// Adds etl::chrono::months + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month operator +(const etl::chrono::months& dm, + const etl::chrono::year_month& ym) ETL_NOEXCEPT + { + return etl::chrono::year_month(ym.year(), ym.month() + dm); + } + + //************************************************************************* + /// Subtracts etl::chrono::years + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month operator -(const etl::chrono::year_month& ym, + const etl::chrono::years& dy) ETL_NOEXCEPT + { + return etl::chrono::year_month(ym.year() - dy, ym.month()); + } + + //************************************************************************* + /// Subtracts etl::chrono::months + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month operator -(const etl::chrono::year_month& ym, + const etl::chrono::months& dm) ETL_NOEXCEPT + { + return etl::chrono::year_month(ym.year(), ym.month() - dm); + } + + //************************************************************************* + /// Subtracts etl::chrono::year_month + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::months operator -(const etl::chrono::year_month& ym1, + const etl::chrono::year_month& ym2) ETL_NOEXCEPT + { + return etl::chrono::months(static_cast(((int(ym1.year()) - int(ym2.year())) * 12) + (unsigned(ym1.month()) - unsigned(ym2.month())))); + } + + //************************************************************************* + /// Equality operator. + //************************************************************************* + friend ETL_CONSTEXPR bool operator ==(const etl::chrono::year_month& lhs, + const etl::chrono::year_month& rhs) ETL_NOEXCEPT + { + return (lhs.y == rhs.y) && (lhs.m == rhs.m); + } + + //************************************************************************* + /// Inequality operator. + //************************************************************************* + friend ETL_CONSTEXPR bool operator !=(const etl::chrono::year_month& lhs, + const etl::chrono::year_month& rhs) ETL_NOEXCEPT + { + return !(lhs == rhs); + } + + //*********************************************************************** + /// Spaceship operator + //*********************************************************************** +#if ETL_USING_CPP20 + [[nodiscard]] friend constexpr auto operator <=>(const etl::chrono::year_month& lhs, + const etl::chrono::year_month& rhs) ETL_NOEXCEPT + { + auto cmp = lhs.year()<=> rhs.year(); + + if (cmp != 0) + { + return cmp; + } + else + { + return lhs.month() <=> rhs.month(); + } + } +#endif + + //*********************************************************************** + /// Compare year_month with another. + /// if month < other.month, returns -1; + /// else if month > other.month, returns 1; + /// else if day < other.day, returns -1; + /// else if day > other.day, returns 1; + /// else returns 0; + //*********************************************************************** + ETL_CONSTEXPR14 int compare(const year_month& other) const ETL_NOEXCEPT + { + if (y < other.y) return -1; + if (y > other.y) return 1; + if (m < other.m) return -1; + if (m > other.m) return 1; + + return 0; + } + + private: + + etl::chrono::year y; + etl::chrono::month m; + }; + } + + //************************************************************************* + /// Hash function for etl::chrono::year_month + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::year_month& md) const + { + uint8_t buffer[sizeof(unsigned int) + sizeof(unsigned int)]; + + unsigned int y = md.year(); + unsigned int m = md.month(); + + memcpy(buffer, &y, sizeof(y)); + memcpy(buffer + sizeof(y), &m, sizeof(m)); + + return etl::private_hash::generic_hash(buffer, buffer + sizeof(unsigned int) + sizeof(unsigned int)); + } + }; +#endif +} + diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index d5781a44..5729a1b7 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -70,6 +70,7 @@ add_executable(etl_tests test_chrono_weekday_indexed.cpp test_chrono_weekday_last.cpp test_chrono_year.cpp + test_chrono_year_month.cpp # test_circular_buffer.cpp # test_circular_buffer_external_buffer.cpp # test_circular_iterator.cpp diff --git a/test/test_chrono_operators.cpp b/test/test_chrono_operators.cpp new file mode 100644 index 00000000..30e398d3 --- /dev/null +++ b/test/test_chrono_operators.cpp @@ -0,0 +1,64 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include +#include + +// Set to 0 to reference against std::chrono +#define ETL_USING_ETL_CHRONO 1 + +#if ETL_USING_ETL_CHRONO + #define Chrono etl::chrono +#else + #if ETL_USING_CPP20 + #include + #define Chrono std::chrono + #else + #error std::chrono not supported + #endif +#endif + +namespace +{ + SUITE(test_chrono_operators) + { + //************************************************************************* + TEST(test_operator_for_year_month) + { + + } + }; +} diff --git a/test/test_chrono_year_month.cpp b/test/test_chrono_year_month.cpp new file mode 100644 index 00000000..bd3a87f5 --- /dev/null +++ b/test/test_chrono_year_month.cpp @@ -0,0 +1,144 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2024 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include +#include + +// Set to 0 to reference against std::chrono +#define ETL_USING_ETL_CHRONO 1 + +#if ETL_USING_ETL_CHRONO + #define Chrono etl::chrono +#else + #if ETL_USING_CPP20 + #include + #define Chrono std::chrono + #else + #error std::chrono not supported + #endif +#endif + +namespace +{ + SUITE(test_chrono_year_month) + { + //************************************************************************* + TEST(test_default_constructor) + { + Chrono::year_month ym; + + CHECK_FALSE(ym.ok()); // Default-constructed year_month is not valid + } + + //************************************************************************* + TEST(test_constructor_with_month_and_day) + { + Chrono::year_month ym{Chrono::year(2000), Chrono::January}; + + CHECK_TRUE(ym.ok()); // Valid year_month + CHECK_EQUAL(2000, (int)ym.year()); + CHECK_EQUAL((unsigned)Chrono::January, (unsigned)ym.month()); + } + + //************************************************************************* + TEST(test_invalid_year_month) + { + Chrono::year_month ym{Chrono::year{32768}, Chrono::January}; // Invalid year + + CHECK_FALSE(ym.ok()); // Invalid year_month + } + + //************************************************************************* + TEST(test_invalid_month_in_year_month) + { + Chrono::year_month ym{Chrono::year{2000}, Chrono::month{13}}; // Invalid month (13) + + CHECK_FALSE(ym.ok()); // Invalid year_month + } + +#if ETL_USING_CPP20 + //************************************************************************* + TEST(test_year_month_spaceship_operator) + { + Chrono::year_month ym1{Chrono::year(2000), Chrono::January}; + Chrono::year_month ym2{Chrono::year(2001), Chrono::February}; + Chrono::year_month ym3{Chrono::year(2000), Chrono::January}; + + CHECK_TRUE((ym1 <=> ym3) == std::strong_ordering::equal); + CHECK_TRUE((ym1 <=> ym2) == std::strong_ordering::less); + CHECK_TRUE((ym2 <=> ym1) == std::strong_ordering::greater); + } +#endif + +#if ETL_USING_ETL_CHRONO + //************************************************************************* + TEST(test_year_month_compare) + { + Chrono::year_month ym1{Chrono::year(2000), Chrono::January}; + Chrono::year_month ym2{Chrono::year(2001), Chrono::February}; + Chrono::year_month ym3{Chrono::year(2000), Chrono::January}; + + CHECK_TRUE(ym1.compare(ym3) == 0); + CHECK_TRUE(ym1.compare(ym2) == -1); + CHECK_TRUE(ym2.compare(ym1) == 1); + } +#endif + + //************************************************************************* + TEST(test_year_month_equality_operator) + { + Chrono::year_month ym1{Chrono::year(2000), Chrono::January}; + Chrono::year_month ym2{Chrono::year(2001), Chrono::February}; + Chrono::year_month ym3{Chrono::year(2000), Chrono::February}; + + CHECK_TRUE(ym1 == ym1); // 2000/January + CHECK_FALSE(ym1 == ym2); // 2000/January != 2001/February + CHECK_FALSE(ym1 == ym3); // 2000/January != 2000/February + } + + //************************************************************************* + TEST(test_year_month_not_equality_operator) + { + Chrono::year_month ym1{Chrono::year(2000), Chrono::January}; + Chrono::year_month ym2{Chrono::year(2001), Chrono::February}; + Chrono::year_month ym3{Chrono::year(2000), Chrono::February}; + + CHECK_FALSE(ym1 != ym1); // 2000/January + CHECK_TRUE(ym1 != ym2); // 2000/January != 2001/February + CHECK_TRUE(ym1 != ym3); // 2000/January != 2000/February + } + }; +} diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 90fa9853..af492705 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -3197,6 +3197,7 @@ + @@ -8475,6 +8476,7 @@ + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 4f5baf9e..02a49851 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -1494,6 +1494,9 @@ ETL\Private\chrono + + ETL\Private\chrono + @@ -3545,6 +3548,9 @@ Tests\Syntax Checks\Source + + Tests\Chrono + From 279ce8f0dc20c5f8dd7260fbbcb4226531499cca Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 27 Apr 2025 20:22:45 +0100 Subject: [PATCH 21/33] Added more chrono classes and operators --- include/etl/chrono.h | 6 +- include/etl/private/chrono/month.h | 13 + include/etl/private/chrono/month_day.h | 8 +- include/etl/private/chrono/month_weekday.h | 6 +- include/etl/private/chrono/operators.h | 361 ++++++++---- include/etl/private/chrono/system_clock.h | 51 ++ include/etl/private/chrono/time_point.h | 232 ++++++++ include/etl/private/chrono/weekday.h | 2 +- include/etl/private/chrono/year.h | 4 +- include/etl/private/chrono/year_month.h | 7 +- include/etl/private/chrono/year_month_day.h | 538 ++++++++++++++++++ .../etl/private/chrono/year_month_weekday.h | 518 +++++++++++++++++ test/test_chrono_month_day_last.cpp | 13 + test/test_chrono_operators.cpp | 256 ++++++++- test/test_chrono_year.cpp | 2 +- test/vs2022/etl.vcxproj | 5 + test/vs2022/etl.vcxproj.filters | 15 + 17 files changed, 1896 insertions(+), 141 deletions(-) create mode 100644 include/etl/private/chrono/system_clock.h create mode 100644 include/etl/private/chrono/time_point.h create mode 100644 include/etl/private/chrono/year_month_day.h create mode 100644 include/etl/private/chrono/year_month_weekday.h diff --git a/include/etl/chrono.h b/include/etl/chrono.h index 2d20db82..8fce7d57 100644 --- a/include/etl/chrono.h +++ b/include/etl/chrono.h @@ -60,8 +60,10 @@ namespace etl } } +#include "private/chrono/time_point.h" #include "private/chrono/last_spec.h" #include "private/chrono/duration.h" +#include "private/chrono/system_clock.h" #include "private/chrono/day.h" #include "private/chrono/weekday.h" #include "private/chrono/month.h" @@ -69,8 +71,10 @@ namespace etl #include "private/chrono/month_weekday.h" #include "private/chrono/year.h" #include "private/chrono/year_month.h" +#include "private/chrono/year_month_day.h" +#include "private/chrono/year_month_weekday.h" #include "private/chrono/hh_mm_ss.h" -#include "private/chrono/operators.h" +#include "private/chrono/operators.h" #endif #undef ETL_IN_CHRONO_H diff --git a/include/etl/private/chrono/month.h b/include/etl/private/chrono/month.h index 1359c555..5b1e3678 100644 --- a/include/etl/private/chrono/month.h +++ b/include/etl/private/chrono/month.h @@ -42,6 +42,11 @@ namespace etl ETL_CONSTEXPR etl::chrono::month operator +(const etl::chrono::months& ms, const etl::chrono::month& m) ETL_NOEXCEPT; ETL_CONSTEXPR etl::chrono::month operator -(const etl::chrono::month& m, const etl::chrono::months& ms) ETL_NOEXCEPT; + namespace private_chrono + { + static ETL_CONSTANT unsigned char days_in_month[13] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + } + //*********************************************************************** /// month //*********************************************************************** @@ -380,6 +385,14 @@ namespace etl return m; } + //************************************************************************* + /// Returns the last day of the month + //************************************************************************* + ETL_CONSTEXPR etl::chrono::day day() const ETL_NOEXCEPT + { + return etl::chrono::day(private_chrono::days_in_month[static_cast(m)]); + } + //************************************************************************* /// Is the contained month OK? //************************************************************************* diff --git a/include/etl/private/chrono/month_day.h b/include/etl/private/chrono/month_day.h index 171480b4..97ce4def 100644 --- a/include/etl/private/chrono/month_day.h +++ b/include/etl/private/chrono/month_day.h @@ -36,11 +36,6 @@ namespace etl { namespace chrono { - namespace private_chrono - { - static ETL_CONSTANT unsigned char days_in_month[13] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; - } - class month_day { public: @@ -53,7 +48,8 @@ namespace etl //************************************************************************* /// Construct from month and day. //************************************************************************* - ETL_CONSTEXPR month_day(const etl::chrono::month& m_, const etl::chrono::day& d_) ETL_NOEXCEPT + ETL_CONSTEXPR month_day(const etl::chrono::month& m_, + const etl::chrono::day& d_) ETL_NOEXCEPT : m(m_) , d(d_) { diff --git a/include/etl/private/chrono/month_weekday.h b/include/etl/private/chrono/month_weekday.h index e1f99d95..a7d895fc 100644 --- a/include/etl/private/chrono/month_weekday.h +++ b/include/etl/private/chrono/month_weekday.h @@ -43,7 +43,8 @@ namespace etl //************************************************************************* /// Construct from month and weekday_indexed. //************************************************************************* - ETL_CONSTEXPR month_weekday(const etl::chrono::month& m_, const etl::chrono::weekday_indexed& wdi_) ETL_NOEXCEPT + ETL_CONSTEXPR month_weekday(const etl::chrono::month& m_, + const etl::chrono::weekday_indexed& wdi_) ETL_NOEXCEPT : m(m_) , wdi(wdi_) { @@ -107,7 +108,8 @@ namespace etl //************************************************************************* /// Construct from month and weekday_indexed. //************************************************************************* - ETL_CONSTEXPR month_weekday_last(const etl::chrono::month& m_, const etl::chrono::weekday_last& wdl_) ETL_NOEXCEPT + ETL_CONSTEXPR month_weekday_last(const etl::chrono::month& m_, + const etl::chrono::weekday_last& wdl_) ETL_NOEXCEPT : m(m_) , wdl(wdl_) { diff --git a/include/etl/private/chrono/operators.h b/include/etl/private/chrono/operators.h index 169217e7..7872c88c 100644 --- a/include/etl/private/chrono/operators.h +++ b/include/etl/private/chrono/operators.h @@ -36,154 +36,293 @@ namespace etl { namespace chrono { - //// year_month - //constexpr auto operator/(const etl::chrono::year& y, - // const etl::chrono::month& m ) noexcept - // -> etl::chrono::year_month; + //************************************************************************* + // month_day + ETL_CONSTEXPR14 etl::chrono::month_day operator /(const etl::chrono::month& m, + const etl::chrono::day& d) ETL_NOEXCEPT + { + return etl::chrono::month_day(m, d); + } - //constexpr auto operator/( const etl::chrono::year& y, int m ) noexcept - // -> etl::chrono::year_month; + // month_day + ETL_CONSTEXPR14 etl::chrono::month_day operator /(const etl::chrono::month& m, + int d) ETL_NOEXCEPT + { + return etl::chrono::month_day(m, etl::chrono::day(d)); + } - //// month_day - //constexpr auto operator/( const etl::chrono::month& m, - // const etl::chrono::day& d ) noexcept - // -> etl::chrono::month_day; + // month_day + ETL_CONSTEXPR14 etl::chrono::month_day operator /(int m, + const etl::chrono::day& d) ETL_NOEXCEPT + { + return etl::chrono::month_day(etl::chrono::month(m), d); + } - //constexpr auto operator/( const etl::chrono::month& m, int d ) noexcept - // -> etl::chrono::month_day; + // month_day + ETL_CONSTEXPR14 etl::chrono::month_day operator /(const etl::chrono::day& d, + const etl::chrono::month& m) ETL_NOEXCEPT + { + return etl::chrono::month_day(m, d); + } - //constexpr auto operator/( int m, const etl::chrono::day& d ) noexcept - // -> etl::chrono::month_day; + // month_day + ETL_CONSTEXPR14 etl::chrono::month_day operator /(const etl::chrono::day& d, + int m) ETL_NOEXCEPT + { + return etl::chrono::month_day(etl::chrono::month(m), d); + } - //constexpr auto operator/( const etl::chrono::day& d, - // const etl::chrono::month& m ) noexcept - // -> etl::chrono::month_day; + //************************************************************************* + // month_day_last + ETL_CONSTEXPR14 etl::chrono::month_day_last operator /(const etl::chrono::month& m, + etl::chrono::last_spec) ETL_NOEXCEPT + { + return etl::chrono::month_day_last(m); + } - //constexpr auto operator/( const etl::chrono::day& d, int m ) noexcept - // -> etl::chrono::month_day; + // month_day_last + ETL_CONSTEXPR14 etl::chrono::month_day_last operator /(int m, + etl::chrono::last_spec) ETL_NOEXCEPT + { + return etl::chrono::month_day_last(etl::chrono::month(m)); + } - //// month_day_last - //constexpr auto operator/( const etl::chrono::month& m, - // etl::chrono::last_spec ) noexcept - // -> etl::chrono::month_day_last; + // month_day_last + ETL_CONSTEXPR14 etl::chrono::month_day_last operator /(etl::chrono::last_spec, + const etl::chrono::month& m) ETL_NOEXCEPT + { + return etl::chrono::month_day_last(m); + } + + // month_day_last + ETL_CONSTEXPR14 etl::chrono::month_day_last operator/(etl::chrono::last_spec, + int m) ETL_NOEXCEPT + { + return etl::chrono::month_day_last(etl::chrono::month(m)); + } - //constexpr auto operator/( int m, etl::chrono::last_spec ) noexcept - // -> etl::chrono::month_day_last; + //************************************************************************* + // month_weekday + ETL_CONSTEXPR14 etl::chrono::month_weekday operator /(const etl::chrono::month& m, + const etl::chrono::weekday_indexed& wdi) ETL_NOEXCEPT + { + return etl::chrono::month_weekday(m, wdi); + } - //constexpr auto operator/( etl::chrono::last_spec, - // const etl::chrono::month& m ) noexcept - // -> etl::chrono::month_day_last; + // month_weekday + ETL_CONSTEXPR14 etl::chrono::month_weekday operator /(int m, + const etl::chrono::weekday_indexed& wdi) ETL_NOEXCEPT + { + return etl::chrono::month_weekday(etl::chrono::month(m), wdi); + } - //constexpr auto operator/( etl::chrono::last_spec, int m ) noexcept - // -> etl::chrono::month_day_last; + // month_weekday + ETL_CONSTEXPR14 etl::chrono::month_weekday operator /(const etl::chrono::weekday_indexed& wdi, + const etl::chrono::month& m) ETL_NOEXCEPT + { + return etl::chrono::month_weekday(m, wdi); + } - //// month_weekday - //constexpr auto operator/( const etl::chrono::month& m, - // const etl::chrono::weekday_indexed& wdi ) noexcept - // -> etl::chrono::month_weekday; + // month_weekday + ETL_CONSTEXPR14 etl::chrono::month_weekday operator /(const etl::chrono::weekday_indexed& wdi, + int m) ETL_NOEXCEPT + { + return etl::chrono::month_weekday(etl::chrono::month(m), wdi); + } - //constexpr auto operator/( int m, const etl::chrono::weekday_indexed& wdi ) noexcept - // -> etl::chrono::month_weekday; + //************************************************************************* + // month_weekday_last + ETL_CONSTEXPR14 etl::chrono::month_weekday_last operator /(const etl::chrono::month& m, + const etl::chrono::weekday_last& wdl) ETL_NOEXCEPT + { + return etl::chrono::month_weekday_last(m, wdl); + } - //constexpr auto operator/(const etl::chrono::weekday_indexed& wdi, - // const etl::chrono::month& m ) noexcept - // -> etl::chrono::month_weekday; + // month_weekday_last + ETL_CONSTEXPR14 etl::chrono::month_weekday_last operator /(int m, + const etl::chrono::weekday_last& wdl) ETL_NOEXCEPT + { + return etl::chrono::month_weekday_last(etl::chrono::month(m), wdl); + } - //constexpr auto operator/( const etl::chrono::weekday_indexed& wdi, int m ) noexcept - // -> etl::chrono::month_weekday; + // month_weekday_last + ETL_CONSTEXPR14 etl::chrono::month_weekday_last operator /(const etl::chrono::weekday_last& wdl, + const etl::chrono::month& m) ETL_NOEXCEPT + { + return etl::chrono::month_weekday_last(m, wdl); + } - //// month_weekday_last - //constexpr auto operator/( const etl::chrono::month& m, - // const etl::chrono::weekday_last& wdl ) noexcept - // -> etl::chrono::month_weekday_last; + // month_weekday_last + ETL_CONSTEXPR14 etl::chrono::month_weekday_last operator /(const etl::chrono::weekday_last& wdl, + int m) ETL_NOEXCEPT + { + return etl::chrono::month_weekday_last(etl::chrono::month(m), wdl); + } - //constexpr auto operator/( int m, const etl::chrono::weekday_last& wdl ) noexcept - // -> etl::chrono::month_weekday_last; + //************************************************************************* + // year_month + ETL_CONSTEXPR14 etl::chrono::year_month operator /(const etl::chrono::year& y, + const etl::chrono::month& m) ETL_NOEXCEPT + { + return etl::chrono::year_month(y, m); + } - //constexpr auto operator/( const etl::chrono::weekday_last& wdl, - // const etl::chrono::month& m ) noexcept - // -> etl::chrono::month_weekday_last; + // year_month + ETL_CONSTEXPR14 etl::chrono::year_month operator /(const etl::chrono::year& y, + int m) ETL_NOEXCEPT + { + return etl::chrono::year_month(y, etl::chrono::month(m)); + } - //constexpr auto operator/( const etl::chrono::weekday_last& wdl, int m ) noexcept - // -> etl::chrono::month_weekday_last; + ////************************************************************************* + // year_month_day + ETL_CONSTEXPR14 etl::chrono::year_month_day operator /(const etl::chrono::year_month& ym, + const etl::chrono::day& d) ETL_NOEXCEPT + { + return etl::chrono::year_month_day(ym.year(), ym.month(), d); + } - //// year_month_day - //constexpr auto operator/( const etl::chrono::year_month& ym, - // const etl::chrono::day& d ) noexcept - // -> etl::chrono::year_month_day; + // year_month_day + ETL_CONSTEXPR14 etl::chrono::year_month_day operator /(const etl::chrono::year_month& ym, + int d ) ETL_NOEXCEPT + { + return etl::chrono::year_month_day(ym.year(), ym.month(), etl::chrono::day(d)); + } - //constexpr auto operator/( const etl::chrono::year_month& ym, int d ) noexcept - // -> etl::chrono::year_month_day; + // year_month_day + ETL_CONSTEXPR14 etl::chrono::year_month_day operator /(const etl::chrono::year& y, + const etl::chrono::month_day& md) ETL_NOEXCEPT + { + return etl::chrono::year_month_day(y, md.month(), md.day()); + } - //constexpr auto operator/( const etl::chrono::year& y, - // const etl::chrono::month_day& md ) noexcept - // -> etl::chrono::year_month_day; + // year_month_day + ETL_CONSTEXPR14 etl::chrono::year_month_day operator/(int y, + const etl::chrono::month_day& md) ETL_NOEXCEPT + { + return etl::chrono::year_month_day(etl::chrono::year(y), md.month(), md.day()); + } - //constexpr auto operator/( int y, const etl::chrono::month_day& md ) noexcept - // -> etl::chrono::year_month_day; + // year_month_day + ETL_CONSTEXPR14 etl::chrono::year_month_day operator /(const etl::chrono::month_day& md, + const etl::chrono::year& y) ETL_NOEXCEPT + { + return etl::chrono::year_month_day(y, md.month(), md.day()); + } - //constexpr auto operator/( const etl::chrono::month_day& md, - // const etl::chrono::year& y ) noexcept - // -> etl::chrono::year_month_day; + // year_month_day + ETL_CONSTEXPR14 etl::chrono::year_month_day operator /(const etl::chrono::month_day& md, + int y) ETL_NOEXCEPT + { + return etl::chrono::year_month_day(etl::chrono::year(y), md.month(), md.day()); + } - //constexpr auto operator/( const etl::chrono::month_day& md, int y ) noexcept - // -> etl::chrono::year_month_day; + //************************************************************************* + // year_month_day_last + ETL_CONSTEXPR14 etl::chrono::year_month_day_last operator /(const etl::chrono::year_month& ym, + etl::chrono::last_spec) ETL_NOEXCEPT + { + return etl::chrono::year_month_day_last(ym.year(), etl::chrono::month_day_last(ym.month())); + } - //// year_month_day_last - //constexpr auto operator/( const etl::chrono::year_month& ym, - // etl::chrono::last_spec ) noexcept - // -> etl::chrono::year_month_day_last; + // year_month_day_last + ETL_CONSTEXPR14 etl::chrono::year_month_day_last operator /(const etl::chrono::year& y, + const etl::chrono::month_day_last& mdl) ETL_NOEXCEPT + { + return etl::chrono::year_month_day_last(y, mdl); + } - //constexpr auto operator/( const etl::chrono::year& y, - // const etl::chrono::month_day_last& mdl ) noexcept - // -> etl::chrono::year_month_day_last; + // year_month_day_last + ETL_CONSTEXPR14 etl::chrono::year_month_day_last operator /(int y, + const etl::chrono::month_day_last& mdl) ETL_NOEXCEPT + { + return etl::chrono::year_month_day_last(etl::chrono::year(y), mdl); + } - //constexpr auto operator/( int y, const etl::chrono::month_day_last& mdl ) noexcept - // -> etl::chrono::year_month_day_last; + // year_month_day_last + ETL_CONSTEXPR14 etl::chrono::year_month_day_last operator /(const etl::chrono::month_day_last& mdl, + const etl::chrono::year& y) ETL_NOEXCEPT + { + return etl::chrono::year_month_day_last(y, mdl); + } - //constexpr auto operator/( const etl::chrono::month_day_last& mdl, - // const etl::chrono::year& y ) noexcept - // -> etl::chrono::year_month_day_last; + // year_month_day_last + ETL_CONSTEXPR14 etl::chrono::year_month_day_last operator /(const etl::chrono::month_day_last& mdl, + int y) ETL_NOEXCEPT + { + return etl::chrono::year_month_day_last(etl::chrono::year(y), mdl); + } - //constexpr auto operator/( const etl::chrono::month_day_last& mdl, int y ) noexcept - // -> etl::chrono::year_month_day_last; + //************************************************************************* + // year_month_weekday + ETL_CONSTEXPR14 etl::chrono::year_month_weekday operator /(const etl::chrono::year_month& ym, + const etl::chrono::weekday_indexed& wdi) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday(ym.year(), ym.month(), wdi); + } - //// year_month_weekday - //constexpr auto operator/( const etl::chrono::year_month& ym, - // const etl::chrono::weekday_indexed& wdi ) noexcept - // -> etl::chrono::year_month_weekday; + // year_month_weekday + ETL_CONSTEXPR14 etl::chrono::year_month_weekday operator /(const etl::chrono::year& y, + const etl::chrono::month_weekday& mwd) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday(y, mwd.month(), mwd.weekday_indexed()); + } - //constexpr auto operator/( const etl::chrono::year& y, - // const etl::chrono::month_weekday& mwd ) noexcept - // -> etl::chrono::year_month_weekday; + // year_month_weekday + ETL_CONSTEXPR14 etl::chrono::year_month_weekday operator/(int y, + const etl::chrono::month_weekday& mwd) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday(etl::chrono::year(y), mwd.month(), mwd.weekday_indexed()); + } - //constexpr auto operator/( int y, const etl::chrono::month_weekday& mwd ) noexcept - // -> etl::chrono::year_month_weekday; + // year_month_weekday + ETL_CONSTEXPR14 etl::chrono::year_month_weekday operator /(const etl::chrono::month_weekday& mwd, + const etl::chrono::year& y) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday(y, mwd.month(), mwd.weekday_indexed()); + } - //constexpr auto operator/( const etl::chrono::month_weekday& mwd, - // const etl::chrono::year& y ) noexcept - // -> etl::chrono::year_month_weekday; + // year_month_weekday + ETL_CONSTEXPR14 etl::chrono::year_month_weekday operator /(const etl::chrono::month_weekday& mwd, + int y) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday(etl::chrono::year(y), mwd.month(), mwd.weekday_indexed()); + } - //constexpr auto operator/( const etl::chrono::month_weekday& mwd, int y ) noexcept - // -> etl::chrono::year_month_weekday; + //************************************************************************* + // year_month_weekday_last + ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last operator /(const etl::chrono::year_month& ym, + const etl::chrono::weekday_last& wdl) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday_last(ym.year(), ym.month(), wdl); + } - //// year_month_weekday_last - //constexpr auto operator/( const etl::chrono::year_month& ym, - // const etl::chrono::weekday_last& wdl ) noexcept - // -> etl::chrono::year_month_weekday_last; + // year_month_weekday_last + ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last operator /(const etl::chrono::year& y, + const etl::chrono::month_weekday_last& mwdl) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday_last(y, mwdl.month(), mwdl.weekday_last()); + } - //constexpr auto operator/( const etl::chrono::year& y, - // const etl::chrono::month_weekday_last& mwdl ) noexcept - // -> etl::chrono::year_month_weekday_last; + // year_month_weekday_last + ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last operator/(int y, + const etl::chrono::month_weekday_last& mwdl) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday_last(etl::chrono::year(y), mwdl.month(), mwdl.weekday_last()); + } - //constexpr auto operator/( int y, const etl::chrono::month_weekday_last& mwdl ) noexcept - // -> etl::chrono::year_month_weekday_last; + // year_month_weekday_last + ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last operator /(const etl::chrono::month_weekday_last& mwdl, + const etl::chrono::year& y) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday_last(y, mwdl.month(), mwdl.weekday_last()); + } - //constexpr auto operator/( const etl::chrono::month_weekday_last& mwdl, - // const etl::chrono::year& y ) noexcept - // -> etl::chrono::year_month_weekday_last; - - //constexpr auto operator/( const etl::chrono::month_weekday_last& mwdl, int y ) noexcept - // -> etl::chrono::year_month_weekday_last; + // year_month_weekday_last + ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last operator /(const etl::chrono::month_weekday_last& mwdl, + int y) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday_last(etl::chrono::year(y), mwdl.month(), mwdl.weekday_last()); + } } } \ No newline at end of file diff --git a/include/etl/private/chrono/system_clock.h b/include/etl/private/chrono/system_clock.h new file mode 100644 index 00000000..99341313 --- /dev/null +++ b/include/etl/private/chrono/system_clock.h @@ -0,0 +1,51 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +namespace etl +{ + namespace chrono + { + class system_clock + { + + }; + + template + using sys_time = etl::chrono::time_point; + + using sys_seconds = sys_time; + + using sys_days = sys_time; + } +} diff --git a/include/etl/private/chrono/time_point.h b/include/etl/private/chrono/time_point.h new file mode 100644 index 00000000..0d48acb3 --- /dev/null +++ b/include/etl/private/chrono/time_point.h @@ -0,0 +1,232 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +namespace etl +{ + namespace chrono + { + //*************************************************************************** + /// Represents a point in time storing a TDuration indicating the time + /// interval from the start of the TClock's epoch. + //*************************************************************************** + template + class time_point + { + public: + + using clock = TClock; + using duration = TDuration; + using rep = typename TDuration::rep; + using period = typename TDuration::period; + + //*************************************************************************** + /// Default constructor. + //*************************************************************************** + ETL_CONSTEXPR time_point() ETL_NOEXCEPT + : dur(duration::zero()) + { + } + + //*************************************************************************** + /// Construct from a duration. + //*************************************************************************** + ETL_CONSTEXPR explicit time_point(const duration& dur_) ETL_NOEXCEPT + : dur(dur_) + { + } + + //*************************************************************************** + /// Copy constructor. + //*************************************************************************** + ETL_CONSTEXPR time_point(const time_point& rhs) ETL_NOEXCEPT + : dur(rhs.dur) + { + } + + //*************************************************************************** + /// Copy construct from another time_point with a different duration type. + //*************************************************************************** + template + explicit time_point(const time_point& rhs) ETL_NOEXCEPT + : dur(rhs.time_since_epoch()) + { + } + + //*************************************************************************** + /// Assignment operator. + //*************************************************************************** + time_point& operator =(const time_point& rhs) ETL_NOEXCEPT + { + dur = rhs.dur; + + return *this; + } + + //*************************************************************************** + /// Returns a duration representing the amount of time between this and the clock's epoch. + //*************************************************************************** + ETL_CONSTEXPR duration time_since_epoch() const ETL_NOEXCEPT + { + return dur; + } + + //*************************************************************************** + /// Adds a duration. + //*************************************************************************** + time_point& operator +=(const duration& rhs) ETL_NOEXCEPT + { + dur += rhs; + + return *this; + } + + //*************************************************************************** + /// Subtracts a duration. + //*************************************************************************** + time_point& operator -=(const duration& rhs) ETL_NOEXCEPT + { + dur -= rhs; + + return *this; + } + + //*************************************************************************** + /// Returns a time_point with the smallest possible duration. + //*************************************************************************** + static ETL_CONSTEXPR time_point min() ETL_NOEXCEPT + { + return time_point(duration::min()); + } + + //*************************************************************************** + /// Returns a time_point with the largest possible duration. + //*************************************************************************** + static ETL_CONSTEXPR time_point max() ETL_NOEXCEPT + { + return time_point(duration::max()); + } + + private: + + duration dur; + }; + + //*************************************************************************** + /// Equality operator + //*************************************************************************** + template + ETL_CONSTEXPR bool operator ==(const time_point& lhs, const time_point& rhs) + { + return lhs.time_since_epoch() == rhs.time_since_epoch(); + } + + //*************************************************************************** + /// Inequality operator + //*************************************************************************** + template + ETL_CONSTEXPR bool operator !=(const time_point& lhs, const time_point& rhs) + { + return !(lhs == rhs); + } + + //*************************************************************************** + /// Less-than operator + //*************************************************************************** + template + ETL_CONSTEXPR bool operator <(const time_point& lhs, const time_point& rhs) + { + return lhs.time_since_epoch() < rhs.time_since_epoch(); + } + + //*************************************************************************** + /// Less-than-equal operator + //*************************************************************************** + template + ETL_CONSTEXPR bool operator <=(const time_point& lhs, const time_point& rhs) + { + return !(rhs < lhs); + } + + //*************************************************************************** + /// Greater-than operator + //*************************************************************************** + template + ETL_CONSTEXPR bool operator >(const time_point& lhs, const time_point& rhs) + { + return rhs < lhs; + } + + //*************************************************************************** + /// Greater-than-equal operator + //*************************************************************************** + template + ETL_CONSTEXPR bool operator >=(const time_point& lhs, const time_point& rhs) + { + return !(lhs < rhs); + } + + //*************************************************************************** + /// Local time + //*************************************************************************** + //struct local_t + //{ + // using rep = size_t; + // using period = etl::chrono::seconds; + // using duration = etl::chrono::duration; + // using time_point = etl::chrono::time_point; + + // const bool is_steady = true; + + // time_point now() + // { + // return time_point(); + // } + //}; + + //template + //using local_time = etl::chrono::time_point; + + //using local_seconds = local_time; + //using local_days = local_time; + } + + //*************************************************************************** + /// Defines type, which is the common type of two std::chrono::time_points. + //*************************************************************************** + template + struct common_type, etl::chrono::time_point> + { + using type = etl::chrono::time_point::type>; + }; +} diff --git a/include/etl/private/chrono/weekday.h b/include/etl/private/chrono/weekday.h index f5e763ef..794edbce 100644 --- a/include/etl/private/chrono/weekday.h +++ b/include/etl/private/chrono/weekday.h @@ -384,7 +384,7 @@ namespace etl ETL_CONSTEXPR bool operator ==(const etl::chrono::weekday_indexed& wd1, const etl::chrono::weekday_indexed& wd2) ETL_NOEXCEPT { return (wd1.weekday() == wd2.weekday()) && - (wd1.index() == wd2.index()); + (wd1.index() == wd2.index()); } //*********************************************************************** diff --git a/include/etl/private/chrono/year.h b/include/etl/private/chrono/year.h index df90770d..ce723be2 100644 --- a/include/etl/private/chrono/year.h +++ b/include/etl/private/chrono/year.h @@ -168,7 +168,9 @@ namespace etl //*********************************************************************** ETL_CONSTEXPR bool is_leap() const ETL_NOEXCEPT { - return ((value % 4) == 0) && !((value % 400) == 0); + return ((value % 4) == 0) && // Divisible by 4 + (((value % 100) != 0) || // but not divisible by 100 + ((value % 400) == 0)); // unless divisible by 400 } //*********************************************************************** diff --git a/include/etl/private/chrono/year_month.h b/include/etl/private/chrono/year_month.h index 3c76033b..ef4ebe18 100644 --- a/include/etl/private/chrono/year_month.h +++ b/include/etl/private/chrono/year_month.h @@ -44,15 +44,16 @@ namespace etl /// Default constructor. //************************************************************************* year_month() - : y(etl::integral_limits::min) - , m(0) + : y() + , m() { } //************************************************************************* /// Construct from month and day. //************************************************************************* - ETL_CONSTEXPR year_month(const etl::chrono::year& y_, const etl::chrono::month& m_) ETL_NOEXCEPT + ETL_CONSTEXPR year_month(const etl::chrono::year& y_, + const etl::chrono::month& m_) ETL_NOEXCEPT : y(y_) , m(m_) { diff --git a/include/etl/private/chrono/year_month_day.h b/include/etl/private/chrono/year_month_day.h new file mode 100644 index 00000000..101dcfb3 --- /dev/null +++ b/include/etl/private/chrono/year_month_day.h @@ -0,0 +1,538 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +namespace etl +{ + namespace chrono + { + //************************************************************************* + /// year_month_day + //************************************************************************* + class year_month_day + { + public: + + //************************************************************************* + /// Default constructor. + //************************************************************************* + year_month_day() + : y() + , m() + , d() + { + } + + //************************************************************************* + /// Construct from month and day. + //************************************************************************* + ETL_CONSTEXPR year_month_day(const etl::chrono::year& y_, + const etl::chrono::month& m_, + const etl::chrono::day& d_) ETL_NOEXCEPT + : y(y_) + , m(m_) + , d(d_) + { + } + + //************************************************************************* + /// Returns the year. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::year year() const ETL_NOEXCEPT + { + return y; + } + + //************************************************************************* + /// Returns the month. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::month month() const ETL_NOEXCEPT + { + return m; + } + + //************************************************************************* + /// Returns the day. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::day day() const ETL_NOEXCEPT + { + return d; + } + + //************************************************************************* + /// Returns true if the year/month/day is valid. + //************************************************************************* + ETL_CONSTEXPR14 bool ok() const ETL_NOEXCEPT + { + // Check if the year, month, and day are valid individually + return y.ok() && + m.ok() && + d.ok() && + d <= etl::chrono::month_day_last(m).day(); + } + + //************************************************************************* + /// Adds etl::chrono::years + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_day operator +(const etl::chrono::year_month_day& ymd, + const etl::chrono::years& dy) ETL_NOEXCEPT + { + return etl::chrono::year_month_day(ymd.year() + dy, ymd.month(), ymd.day()); + } + + //************************************************************************* + /// Adds etl::chrono::years + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_day operator +(const etl::chrono::years& dy, + const etl::chrono::year_month_day& ymd) ETL_NOEXCEPT + { + return etl::chrono::year_month_day(ymd.year() + dy, ymd.month(), ymd.day()); + } + + //************************************************************************* + /// Adds etl::chrono::months + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_day operator +(const etl::chrono::year_month_day& ymd, + const etl::chrono::months& dm) ETL_NOEXCEPT + { + return etl::chrono::year_month_day(ymd.year(), ymd.month() + dm, ymd.day()); + } + + //************************************************************************* + /// Adds etl::chrono::months + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_day operator +(const etl::chrono::months& dm, + const etl::chrono::year_month_day& ymd) ETL_NOEXCEPT + { + return etl::chrono::year_month_day(ymd.year(), ymd.month() + dm, ymd.day()); + } + + //************************************************************************* + /// Subtracts etl::chrono::years + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_day operator -(const etl::chrono::year_month_day& ymd, + const etl::chrono::years& dy) ETL_NOEXCEPT + { + return etl::chrono::year_month_day(ymd.year() - dy, ymd.month(), ymd.day()); + } + + //************************************************************************* + /// Subtracts etl::chrono::months + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_day operator -(const etl::chrono::year_month_day& ymd, + const etl::chrono::months& dm) ETL_NOEXCEPT + { + return etl::chrono::year_month_day(ymd.year(), ymd.month() - dm, ymd.day()); + } + + //************************************************************************* + /// Equality operator. + //************************************************************************* + friend ETL_CONSTEXPR bool operator ==(const etl::chrono::year_month_day& lhs, + const etl::chrono::year_month_day& rhs) ETL_NOEXCEPT + { + return (lhs.y == rhs.y) && (lhs.m == rhs.m) && (lhs.d == rhs.d); + } + + //************************************************************************* + /// Inequality operator. + //************************************************************************* + friend ETL_CONSTEXPR bool operator !=(const etl::chrono::year_month_day& lhs, + const etl::chrono::year_month_day& rhs) ETL_NOEXCEPT + { + return !(lhs == rhs); + } + + //*********************************************************************** + /// Spaceship operator + //*********************************************************************** +#if ETL_USING_CPP20 + [[nodiscard]] friend constexpr auto operator <=>(const etl::chrono::year_month_day& lhs, + const etl::chrono::year_month_day& rhs) ETL_NOEXCEPT + { + auto cmp = lhs.year() <=> rhs.year(); + + if (cmp != 0) + { + return cmp; + } + + cmp = lhs.month() <=> rhs.month(); + + if (cmp != 0) + { + return cmp; + } + + return lhs.day() <=> rhs.day(); + } +#endif + + //*********************************************************************** + /// Compare year_month_day with another. + /// if year < other.year, returns -1; + /// else if year > other.year, returns 1; + /// if month < other.month, returns -1; + /// else if month > other.month, returns 1; + /// else if day < other.day, returns -1; + /// else if day > other.day, returns 1; + /// else returns 0; + //*********************************************************************** + ETL_CONSTEXPR14 int compare(const year_month_day& other) const ETL_NOEXCEPT + { + if (y < other.y) return -1; + if (y > other.y) return 1; + if (m < other.m) return -1; + if (m > other.m) return 1; + if (d < other.d) return -1; + if (d > other.d) return 1; + + return 0; + } + + //*********************************************************************** + /// Converts *this to etl::chrono::sys_days + //*********************************************************************** + //ETL_CONSTEXPR14 operator etl::chrono::sys_days() const ETL_NOEXCEPT + //{ + // // Start with the first day of the year + // etl::chrono::sys_days first_day_of_year = etl::chrono::sys_days(y / etl::chrono::January / etl::chrono::day(1)); + + // // Add the number of days in the months before the current month + // for (etl::chrono::month m = etl::chrono::January; m < m; ++m) + // { + // first_day_of_year += etl::chrono::days((unsigned)etl::chrono::month_day_last(m).day()); + // } + + // // Add the days in the current month + // first_day_of_year += d - etl::chrono::day(1); + + // return first_day_of_year; + //} + + ////*********************************************************************** + ///// Converts *this to etl::chrono::local_days + ////*********************************************************************** + //ETL_CONSTEXPR14 explicit operator etl::chrono::local_days() const ETL_NOEXCEPT + //{ + // return etl::chrono::local_days(); + //} + + private: + + etl::chrono::year y; + etl::chrono::month m; + etl::chrono::day d; + }; + + //************************************************************************* + /// year_month_day_last + //************************************************************************* + class year_month_day_last + { + public: + + //************************************************************************* + /// + //************************************************************************* + ETL_CONSTEXPR year_month_day_last(const etl::chrono::year& y, + const etl::chrono::month_day_last& mdl) ETL_NOEXCEPT + : y(y) + , m(mdl.month()) + { + + } + + //************************************************************************* + /// + //************************************************************************* + ETL_CONSTEXPR etl::chrono::year year() const ETL_NOEXCEPT + { + return y; + } + + //************************************************************************* + /// + //************************************************************************* + ETL_CONSTEXPR etl::chrono::month month() const ETL_NOEXCEPT + { + return m; + } + + //************************************************************************* + /// + //************************************************************************* + ETL_CONSTEXPR etl::chrono::day day() const ETL_NOEXCEPT + { + return etl::chrono::month_day_last(m).day(); + } + + //************************************************************************* + /// + //************************************************************************* + ETL_CONSTEXPR etl::chrono::month_day_last month_day_last() const ETL_NOEXCEPT + { + return etl::chrono::month_day_last(m); + } + + //************************************************************************* + /// + //************************************************************************* + ETL_CONSTEXPR etl::chrono::year_month_day_last& operator +=(const etl::chrono::years& dy) ETL_NOEXCEPT + { + y += dy; + + return *this; + } + + //************************************************************************* + /// + //************************************************************************* + ETL_CONSTEXPR etl::chrono::year_month_day_last& operator +=(const etl::chrono::months& dm) ETL_NOEXCEPT + { + m += dm; + + return *this; + } + + //************************************************************************* + /// + //************************************************************************* + ETL_CONSTEXPR etl::chrono::year_month_day_last& operator -=(const etl::chrono::years& dy) ETL_NOEXCEPT + { + y -= dy; + + return *this; + } + + //************************************************************************* + /// + //************************************************************************* + ETL_CONSTEXPR etl::chrono::year_month_day_last& operator -=(const etl::chrono::months& dm) ETL_NOEXCEPT + { + m -= dm; + + return *this; + } + + //************************************************************************* + /// Adds etl::chrono::years + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_day_last operator +(const etl::chrono::year_month_day_last& ymdl, + const etl::chrono::years& dy) ETL_NOEXCEPT + { + return etl::chrono::year_month_day_last(ymdl.year() + dy, ymdl.month_day_last()); + } + + //************************************************************************* + /// Adds etl::chrono::years + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_day_last operator +(const etl::chrono::years& dy, + const etl::chrono::year_month_day_last& ymdl) ETL_NOEXCEPT + { + return etl::chrono::year_month_day_last(ymdl.year() + dy, ymdl.month_day_last()); + } + + //************************************************************************* + /// Adds etl::chrono::months + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_day_last operator +(const etl::chrono::year_month_day_last& ymdl, + const etl::chrono::months& dm) ETL_NOEXCEPT + { + return etl::chrono::year_month_day_last(ymdl.year(), etl::chrono::month_day_last(ymdl.month() + dm)); + } + + //************************************************************************* + /// Adds etl::chrono::months + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_day_last operator +(const etl::chrono::months& dm, + const etl::chrono::year_month_day_last& ymdl) ETL_NOEXCEPT + { + return etl::chrono::year_month_day_last(ymdl.year(), etl::chrono::month_day_last(ymdl.month() + dm)); + } + + //************************************************************************* + /// Subtracts etl::chrono::years + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_day_last operator -(const etl::chrono::year_month_day_last& ymdl, + const etl::chrono::years& dy) ETL_NOEXCEPT + { + return etl::chrono::year_month_day_last(ymdl.year() - dy, ymdl.month_day_last()); + } + + //************************************************************************* + /// Subtracts etl::chrono::months + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_day_last operator -(const etl::chrono::year_month_day_last& ymdl, + const etl::chrono::months& dm) ETL_NOEXCEPT + { + return etl::chrono::year_month_day_last(ymdl.year(), etl::chrono::month_day_last(ymdl.month() - dm)); + } + + //************************************************************************* + /// Equality operator. + //************************************************************************* + friend ETL_CONSTEXPR bool operator ==(const etl::chrono::year_month_day_last& lhs, + const etl::chrono::year_month_day_last& rhs) ETL_NOEXCEPT + { + return (lhs.y == rhs.y) && (lhs.m == rhs.m); + } + + //************************************************************************* + /// Inequality operator. + //************************************************************************* + friend ETL_CONSTEXPR bool operator !=(const etl::chrono::year_month_day_last& lhs, + const etl::chrono::year_month_day_last& rhs) ETL_NOEXCEPT + { + return !(lhs == rhs); + } + + //*********************************************************************** + /// Spaceship operator + //*********************************************************************** +#if ETL_USING_CPP20 + [[nodiscard]] friend constexpr auto operator <=>(const etl::chrono::year_month_day_last& lhs, + const etl::chrono::year_month_day_last& rhs) ETL_NOEXCEPT + { + auto cmp = lhs.year() <=> rhs.year(); + + if (cmp != 0) + { + return cmp; + } + else + { + auto cmp = lhs.month() <=> rhs.month(); + + if (cmp != 0) + { + return cmp; + } + else + { + return lhs.month() <=> rhs.month(); + } + } + } +#endif + + //*********************************************************************** + /// Compare year_month_day with another. + /// if year < other.year, returns -1; + /// else if year > other.year, returns 1; + /// if month < other.month, returns -1; + /// else if month > other.month, returns 1; + /// else returns 0; + //*********************************************************************** + ETL_CONSTEXPR14 int compare(const year_month_day_last& other) const ETL_NOEXCEPT + { + if (y < other.y) return -1; + if (y > other.y) return 1; + if (m < other.m) return -1; + if (m > other.m) return 1; + + return 0; + } + + //************************************************************************* + /// + //************************************************************************* + //ETL_CONSTEXPR operator etl::chrono::sys_days() const ETL_NOEXCEPT + //{ + // etl::chrono::sys_days(); + //} + + //************************************************************************* + /// + //************************************************************************* + //ETL_CONSTEXPR explicit operator etl::chrono::local_days() const ETL_NOEXCEPT + //{ + + //} + + private: + + etl::chrono::year y; + etl::chrono::month m; + }; + } + + //************************************************************************* + /// Hash function for etl::chrono::year_month_day + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::year_month_day& ymd) const + { + uint8_t buffer[sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned int)]; + + unsigned int y = ymd.year(); + unsigned int m = ymd.month(); + unsigned int d = ymd.day(); + + memcpy(buffer, &y, sizeof(y)); + memcpy(buffer + sizeof(y), &m, sizeof(m)); + memcpy(buffer + sizeof(y) + sizeof(m), &d, sizeof(d)); + + return etl::private_hash::generic_hash(buffer, buffer + sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned int)); + } + }; +#endif + + //************************************************************************* + /// Hash function for etl::chrono::year_month_day_last + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::year_month_day_last& ymdl) const + { + uint8_t buffer[sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned int)]; + + unsigned int y = ymdl.year(); + unsigned int m = ymdl.month(); + unsigned int d = ymdl.day(); + + memcpy(buffer, &y, sizeof(y)); + memcpy(buffer + sizeof(y), &m, sizeof(m)); + memcpy(buffer + sizeof(y) + sizeof(m), &d, sizeof(d)); + + return etl::private_hash::generic_hash(buffer, buffer + sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned int)); + } + }; +#endif +} + diff --git a/include/etl/private/chrono/year_month_weekday.h b/include/etl/private/chrono/year_month_weekday.h new file mode 100644 index 00000000..03242c6e --- /dev/null +++ b/include/etl/private/chrono/year_month_weekday.h @@ -0,0 +1,518 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +namespace etl +{ + namespace chrono + { + //************************************************************************* + /// year_month_weekday + //************************************************************************* + class year_month_weekday + { + public: + + //************************************************************************* + /// Default constructor. + //************************************************************************* + year_month_weekday() + : y() + , m() + , wdi() + { + } + + //************************************************************************* + /// Construct from month and day. + //************************************************************************* + ETL_CONSTEXPR year_month_weekday(const etl::chrono::year& y_, + const etl::chrono::month& m_, + const etl::chrono::weekday_indexed& wdi_) ETL_NOEXCEPT + : y(y_) + , m(m_) + , wdi(wdi_) + { + } + + //************************************************************************* + /// Returns the year. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::year year() const ETL_NOEXCEPT + { + return y; + } + + //************************************************************************* + /// Returns the month. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::month month() const ETL_NOEXCEPT + { + return m; + } + + //************************************************************************* + /// Returns the weekday. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::weekday weekday() const ETL_NOEXCEPT + { + return wdi.weekday(); + } + + //************************************************************************* + /// Returns the weekday index. + //************************************************************************* + ETL_CONSTEXPR unsigned index() const ETL_NOEXCEPT + { + return wdi.index(); + } + + //************************************************************************* + /// Returns the weekday_indexed. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::weekday_indexed weekday_indexed() const ETL_NOEXCEPT + { + return wdi; + } + + //************************************************************************* + /// Returns true if the year/month/day is valid. + //************************************************************************* + ETL_CONSTEXPR14 bool ok() const ETL_NOEXCEPT + { + return y.ok() && m.ok() && wdi.ok(); + } + + //************************************************************************* + /// Adds etl::chrono::years + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_weekday operator +(const etl::chrono::year_month_weekday& ymwd, + const etl::chrono::years& dy) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday(ymwd.year() + dy, ymwd.month(), ymwd.weekday_indexed()); + } + + //************************************************************************* + /// Adds etl::chrono::years + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_weekday operator +(const etl::chrono::years& dy, + const etl::chrono::year_month_weekday& ymwd) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday(ymwd.year() + dy, ymwd.month(), ymwd.weekday_indexed()); + } + + //************************************************************************* + /// Adds etl::chrono::months + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_weekday operator +(const etl::chrono::year_month_weekday& ymwd, + const etl::chrono::months& dm) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday(ymwd.year(), ymwd.month() + dm, ymwd.weekday_indexed()); + } + + //************************************************************************* + /// Adds etl::chrono::months + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_weekday operator +(const etl::chrono::months& dm, + const etl::chrono::year_month_weekday& ymwd) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday(ymwd.year(), ymwd.month() + dm, ymwd.weekday_indexed()); + } + + //************************************************************************* + /// Subtracts etl::chrono::years + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_weekday operator -(const etl::chrono::year_month_weekday& ymwd, + const etl::chrono::years& dy) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday(ymwd.year() - dy, ymwd.month(), ymwd.weekday_indexed()); + } + + //************************************************************************* + /// Subtracts etl::chrono::months + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_weekday operator -(const etl::chrono::year_month_weekday& ymwd, + const etl::chrono::months& dm) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday(ymwd.year(), ymwd.month() - dm, ymwd.weekday_indexed()); + } + + //************************************************************************* + /// Equality operator. + //************************************************************************* + friend ETL_CONSTEXPR bool operator ==(const etl::chrono::year_month_weekday& lhs, + const etl::chrono::year_month_weekday& rhs) ETL_NOEXCEPT + { + return (lhs.y == rhs.y) && (lhs.m == rhs.m) && (lhs.wdi == rhs.wdi); + } + + //************************************************************************* + /// Inequality operator. + //************************************************************************* + friend ETL_CONSTEXPR bool operator !=(const etl::chrono::year_month_weekday& lhs, + const etl::chrono::year_month_weekday& rhs) ETL_NOEXCEPT + { + return !(lhs == rhs); + } + + //*********************************************************************** + /// Converts *this to etl::chrono::sys_days + //*********************************************************************** + //ETL_CONSTEXPR14 operator etl::chrono::sys_days() const ETL_NOEXCEPT + //{ + // // Start with the first day of the given year and month + // etl::chrono::year_month_day first_day_of_month(y, m, etl::chrono::day(1)); + + // // Convert the first day of the month to sys_days + // etl::chrono::sys_days first_day_sys_days = static_cast(first_day_of_month); + + // // Determine the weekday of the first day of the month + // etl::chrono::weekday first_weekday = etl::chrono::weekday(first_day_sys_days); + + // // Calculate the offset to the desired weekday + // int offset = (wd.weekday().c_encoding() - first_weekday.c_encoding() + 7) % 7; + + // // Calculate the day of the month for the desired weekday_indexed + // int day_of_month = 1 + offset + (wdi.index() - 1) * 7; + + // // Ensure the calculated day is valid for the given month + // if (day_of_month > etl::chrono::month_day_last(m).day().count()) + // { + // day_of_month = 0; // Invalid day + // } + + // // Create a year_month_day object for the calculated day + // etl::chrono::year_month_day ymwd(y, m, etl::chrono::day(day_of_month)); + + // // Convert the year_month_day to sys_days + // return static_cast(ymwd); + //} + + ////*********************************************************************** + ///// Converts *this to etl::chrono::local_days + ////*********************************************************************** + //ETL_CONSTEXPR14 explicit operator etl::chrono::local_days() const ETL_NOEXCEPT + //{ + // return etl::chrono::local_days(); + //} + + private: + + etl::chrono::year y; + etl::chrono::month m; + etl::chrono::weekday_indexed wdi; + }; + + //************************************************************************* + /// year_month_weekday_last + //************************************************************************* + class year_month_weekday_last + { + public: + + //************************************************************************* + /// Construct from year, month, weekday_last + //************************************************************************* + ETL_CONSTEXPR year_month_weekday_last(const etl::chrono::year& y_, + const etl::chrono::month& m_, + const etl::chrono::weekday_last& wdl_) ETL_NOEXCEPT + : y(y_) + , m(m_) + , wdl(wdl_) + { + } + + //************************************************************************* + /// Returns the year. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::year year() const ETL_NOEXCEPT + { + return y; + } + + //************************************************************************* + /// Returns the month. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::month month() const ETL_NOEXCEPT + { + return m; + } + + //************************************************************************* + /// Returns the weekday. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::weekday weekday() const ETL_NOEXCEPT + { + return wdl.weekday(); + } + + //************************************************************************* + /// Returns the weekday_last. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::weekday_last weekday_last() const ETL_NOEXCEPT + { + return wdl; + } + + //************************************************************************* + /// Adds etl::chrono::years. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::year_month_weekday_last& operator +=(const etl::chrono::years& dy) ETL_NOEXCEPT + { + y += dy; + + return *this; + } + + //************************************************************************* + /// Adds etl::chrono::months. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::year_month_weekday_last& operator +=(const etl::chrono::months& dm) ETL_NOEXCEPT + { + m += dm; + + return *this; + } + + //************************************************************************* + /// Subtracts etl::chrono::years. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::year_month_weekday_last& operator -=(const etl::chrono::years& dy) ETL_NOEXCEPT + { + y -= dy; + + return *this; + } + + //************************************************************************* + /// Subtracts etl::chrono::months. + //************************************************************************* + ETL_CONSTEXPR etl::chrono::year_month_weekday_last& operator -=(const etl::chrono::months& dm) ETL_NOEXCEPT + { + m -= dm; + + return *this; + } + + //************************************************************************* + /// Adds etl::chrono::years and const etl::chrono::year_month_weekday_last. + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last operator +(const etl::chrono::year_month_weekday_last& ymwdl, + const etl::chrono::years& dy) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday_last(ymwdl.year() + dy, ymwdl.month(), ymwdl.weekday_last()); + } + + //************************************************************************* + /// Adds etl::chrono::years and const etl::chrono::year_month_weekday_last. + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last operator +(const etl::chrono::years& dy, + const etl::chrono::year_month_weekday_last& ymwdl) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday_last(ymwdl.year() + dy, ymwdl.month(), ymwdl.weekday_last()); + } + + //************************************************************************* + /// Adds const etl::chrono::year_month_weekday_last and etl::chrono::months. + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last operator +(const etl::chrono::year_month_weekday_last& ymwdl, + const etl::chrono::months& dm) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday_last(ymwdl.year(), ymwdl.month() + dm, ymwdl.weekday_last()); + } + + //************************************************************************* + /// Adds etl::chrono::months and const etl::chrono::year_month_weekday_last. + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last operator +(const etl::chrono::months& dm, + const etl::chrono::year_month_weekday_last& ymwdl) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday_last(ymwdl.year(), ymwdl.month() + dm, ymwdl.weekday_last()); + } + + //************************************************************************* + /// Subtracts etl::chrono::years from const etl::chrono::year_month_weekday_last. + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last operator -(const etl::chrono::year_month_weekday_last& ymwdl, + const etl::chrono::years& dy) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday_last(ymwdl.year() - dy, ymwdl.month(), ymwdl.weekday_last()); + } + + //************************************************************************* + /// Subtracts etl::chrono::months from const etl::chrono::year_month_weekday_last + //************************************************************************* + friend ETL_CONSTEXPR14 etl::chrono::year_month_weekday_last operator -(const etl::chrono::year_month_weekday_last& ymwdl, + const etl::chrono::months& dm) ETL_NOEXCEPT + { + return etl::chrono::year_month_weekday_last(ymwdl.year(), ymwdl.month() - dm, ymwdl.weekday_last()); + } + + //************************************************************************* + /// Equality operator. + //************************************************************************* + friend ETL_CONSTEXPR bool operator ==(const etl::chrono::year_month_weekday_last& lhs, + const etl::chrono::year_month_weekday_last& rhs) ETL_NOEXCEPT + { + return (lhs.y == rhs.y) && (lhs.m == rhs.m) && (lhs.weekday() == rhs.weekday()); + } + + //************************************************************************* + /// Inequality operator. + //************************************************************************* + friend ETL_CONSTEXPR bool operator !=(const etl::chrono::year_month_weekday_last& lhs, + const etl::chrono::year_month_weekday_last& rhs) ETL_NOEXCEPT + { + return !(lhs == rhs); + } + + //*********************************************************************** + /// Spaceship operator + //*********************************************************************** +#if ETL_USING_CPP20 + [[nodiscard]] friend constexpr auto operator <=>(const etl::chrono::year_month_weekday_last& lhs, + const etl::chrono::year_month_weekday_last& rhs) ETL_NOEXCEPT + { + auto cmp = lhs.year() <=> rhs.year(); + + if (cmp != 0) + { + return cmp; + } + else + { + auto cmp = lhs.month() <=> rhs.month(); + + if (cmp != 0) + { + return cmp; + } + else + { + return lhs.weekday().c_encoding() <=> rhs.weekday().c_encoding(); + } + } + } +#endif + + //*********************************************************************** + /// Compare year_month_weekday with another. + /// if year < other.year, returns -1; + /// else if year > other.year, returns 1; + /// if month < other.month, returns -1; + /// else if month > other.month, returns 1; + /// else returns 0; + //*********************************************************************** + ETL_CONSTEXPR14 int compare(const year_month_weekday_last& other) const ETL_NOEXCEPT + { + if (y < other.y) return -1; + if (y > other.y) return 1; + if (m < other.m) return -1; + if (m > other.m) return 1; + + return 0; + } + + //************************************************************************* + /// + //************************************************************************* + //ETL_CONSTEXPR operator etl::chrono::sys_days() const ETL_NOEXCEPT + //{ + // etl::chrono::sys_days(); + //} + + //************************************************************************* + /// + //************************************************************************* + //ETL_CONSTEXPR explicit operator etl::chrono::local_days() const ETL_NOEXCEPT + //{ + + //} + + private: + + etl::chrono::year y; + etl::chrono::month m; + etl::chrono::weekday_last wdl; + }; + } + + //************************************************************************* + /// Hash function for etl::chrono::year_month_weekday + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::year_month_weekday& ymwd) const + { + uint8_t buffer[sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned int)]; + + unsigned int y = ymwd.year(); + unsigned int m = ymwd.month(); + unsigned int d = ymwd.weekday().c_encoding(); + + memcpy(buffer, &y, sizeof(y)); + memcpy(buffer + sizeof(y), &m, sizeof(m)); + memcpy(buffer + sizeof(y) + sizeof(m), &d, sizeof(d)); + + return etl::private_hash::generic_hash(buffer, buffer + sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned int)); + } + }; +#endif + + //************************************************************************* + /// Hash function for etl::chrono::year_month_weekday_last + //************************************************************************* +#if ETL_USING_8BIT_TYPES + template <> + struct hash + { + size_t operator()(const etl::chrono::year_month_weekday_last& ymwdl) const + { + uint8_t buffer[sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned int)]; + + unsigned int y = ymwdl.year(); + unsigned int m = ymwdl.month(); + unsigned int d = ymwdl.weekday_last().weekday().c_encoding(); + + memcpy(buffer, &y, sizeof(y)); + memcpy(buffer + sizeof(y), &m, sizeof(m)); + memcpy(buffer + sizeof(y) + sizeof(m), &d, sizeof(d)); + + return etl::private_hash::generic_hash(buffer, buffer + sizeof(unsigned int) + sizeof(unsigned int) + sizeof(unsigned int)); + } + }; +#endif +} + diff --git a/test/test_chrono_month_day_last.cpp b/test/test_chrono_month_day_last.cpp index ec9b6ae4..f47792c7 100644 --- a/test/test_chrono_month_day_last.cpp +++ b/test/test_chrono_month_day_last.cpp @@ -84,6 +84,19 @@ namespace CHECK_TRUE(month_day_last_october.ok()); CHECK_TRUE(month_day_last_november.ok()); CHECK_TRUE(month_day_last_december.ok()); + + CHECK_EQUAL(31, month_day_last_january.day()); + CHECK_EQUAL(29, month_day_last_february.day()); + CHECK_EQUAL(31, month_day_last_march.day()); + CHECK_EQUAL(30, month_day_last_april.day()); + CHECK_EQUAL(31, month_day_last_may.day()); + CHECK_EQUAL(30, month_day_last_june.day()); + CHECK_EQUAL(31, month_day_last_july.day()); + CHECK_EQUAL(31, month_day_last_august.day()); + CHECK_EQUAL(30, month_day_last_september.day()); + CHECK_EQUAL(31, month_day_last_october.day()); + CHECK_EQUAL(30, month_day_last_november.day()); + CHECK_EQUAL(31, month_day_last_december.day()); } //************************************************************************* diff --git a/test/test_chrono_operators.cpp b/test/test_chrono_operators.cpp index 30e398d3..f9fca7ff 100644 --- a/test/test_chrono_operators.cpp +++ b/test/test_chrono_operators.cpp @@ -37,28 +37,254 @@ SOFTWARE. #include #include -// Set to 0 to reference against std::chrono -#define ETL_USING_ETL_CHRONO 1 - -#if ETL_USING_ETL_CHRONO - #define Chrono etl::chrono -#else - #if ETL_USING_CPP20 - #include - #define Chrono std::chrono - #else - #error std::chrono not supported - #endif -#endif +using namespace etl::literals::chrono_literals; namespace { SUITE(test_chrono_operators) { //************************************************************************* - TEST(test_operator_for_year_month) + TEST(test_construction_operator_for_month_day) { + etl::chrono::month_day md1 = etl::chrono::January / etl::chrono::day(2); + etl::chrono::month_day md2 = etl::chrono::February / 3; + etl::chrono::month_day md3 = 3 / etl::chrono::day(4); + etl::chrono::month_day md4 = etl::chrono::day(5) / etl::chrono::April; + etl::chrono::month_day md5 = etl::chrono::day(6) / 5; + CHECK_EQUAL(etl::chrono::January, md1.month()); + CHECK_EQUAL(etl::chrono::day(2), md1.day()); + + CHECK_EQUAL(etl::chrono::February, md2.month()); + CHECK_EQUAL(etl::chrono::day(3), md2.day()); + + CHECK_EQUAL(etl::chrono::March, md3.month()); + CHECK_EQUAL(etl::chrono::day(4), md3.day()); + + CHECK_EQUAL(etl::chrono::April, md4.month()); + CHECK_EQUAL(etl::chrono::day(5), md4.day()); + + CHECK_EQUAL(etl::chrono::May, md5.month()); + CHECK_EQUAL(etl::chrono::day(6), md5.day()); + } + + //************************************************************************* + TEST(test_construction_operator_for_month_day_last) + { + etl::chrono::month_day_last mdl1 = etl::chrono::January / etl::chrono::last; + etl::chrono::month_day_last mdl2 = 2 / etl::chrono::last; + etl::chrono::month_day_last mdl3 = etl::chrono::last / etl::chrono::March; + etl::chrono::month_day_last mdl4 = etl::chrono::last / 4; + + CHECK_EQUAL(etl::chrono::January, mdl1.month()); + CHECK_EQUAL(etl::chrono::February, mdl2.month()); + CHECK_EQUAL(etl::chrono::March, mdl3.month()); + CHECK_EQUAL(etl::chrono::April, mdl4.month()); + } + + //************************************************************************* + TEST(test_construction_operator_for_month_weekday) + { + etl::chrono::month_weekday mwd1 = etl::chrono::January / etl::chrono::weekday_indexed(etl::chrono::Monday, 0); + etl::chrono::month_weekday mwd2 = 2 / etl::chrono::weekday_indexed(etl::chrono::Wednesday, 1); + etl::chrono::month_weekday mwd3 = etl::chrono::weekday_indexed(etl::chrono::Friday, 2) / etl::chrono::March; + etl::chrono::month_weekday mwd4 = etl::chrono::weekday_indexed(etl::chrono::Sunday, 3) / 4; + + CHECK_EQUAL(etl::chrono::January, mwd1.month()); + CHECK_EQUAL(etl::chrono::weekday_indexed(etl::chrono::Monday, 0).weekday().c_encoding(), + mwd1.weekday_indexed().weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::weekday_indexed(etl::chrono::Monday, 0).index(), + mwd1.weekday_indexed().index()); + + CHECK_EQUAL(etl::chrono::February, mwd2.month()); + CHECK_EQUAL(etl::chrono::weekday_indexed(etl::chrono::Wednesday, 1).weekday().c_encoding(), + mwd2.weekday_indexed().weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::weekday_indexed(etl::chrono::Wednesday, 1).index(), + mwd2.weekday_indexed().index()); + + + CHECK_EQUAL(etl::chrono::March, mwd3.month()); + CHECK_EQUAL(etl::chrono::weekday_indexed(etl::chrono::Friday, 2).weekday().c_encoding(), + mwd3.weekday_indexed().weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::weekday_indexed(etl::chrono::Friday, 2).index(), + mwd3.weekday_indexed().index()); + + CHECK_EQUAL(etl::chrono::April, mwd4.month()); + CHECK_EQUAL(etl::chrono::weekday_indexed(etl::chrono::Sunday, 3).weekday().c_encoding(), + mwd4.weekday_indexed().weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::weekday_indexed(etl::chrono::Sunday, 3).index(), + mwd4.weekday_indexed().index()); + } + + //************************************************************************* + TEST(test_construction_operator_for_month_weekday_last) + { + etl::chrono::month_weekday_last mdl1 = etl::chrono::January / etl::chrono::weekday_last(etl::chrono::Monday); + etl::chrono::month_weekday_last mdl2 = 2 / etl::chrono::weekday_last(etl::chrono::Tuesday); + etl::chrono::month_weekday_last mdl3 = etl::chrono::weekday_last(etl::chrono::Wednesday) / etl::chrono::March; + etl::chrono::month_weekday_last mdl4 = etl::chrono::weekday_last(etl::chrono::Thursday) / 4; + + CHECK_EQUAL(etl::chrono::January, mdl1.month()); + CHECK_EQUAL(etl::chrono::Monday.c_encoding(), mdl1.weekday_last().weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::February, mdl2.month()); + CHECK_EQUAL(etl::chrono::Tuesday.c_encoding(), mdl2.weekday_last().weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::March, mdl3.month()); + CHECK_EQUAL(etl::chrono::Wednesday.c_encoding(), mdl3.weekday_last().weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::April, mdl4.month()); + CHECK_EQUAL(etl::chrono::Thursday.c_encoding(), mdl4.weekday_last().weekday().c_encoding()); + } + + //************************************************************************* + TEST(test_construction_operator_for_year_month) + { + etl::chrono::year_month ym1 = 2000_year / etl::chrono::April; + etl::chrono::year_month ym2 = 2001_year / 5; + + CHECK_EQUAL(2000_year, ym1.year()); + CHECK_EQUAL(etl::chrono::April, ym1.month()); + + CHECK_EQUAL(2001_year, ym2.year()); + CHECK_EQUAL(etl::chrono::May, ym2.month()); + } + + //************************************************************************* + TEST(test_construction_operator_for_year_month_day) + { + etl::chrono::year_month_day ymd1 = etl::chrono::year_month(etl::chrono::year(2000), etl::chrono::January) / etl::chrono::day(1); + etl::chrono::year_month_day ymd2 = etl::chrono::year_month(etl::chrono::year(2001), etl::chrono::February) / 2; + etl::chrono::year_month_day ymd3 = etl::chrono::year(2002) / etl::chrono::month_day(etl::chrono::March, etl::chrono::day(3)); + etl::chrono::year_month_day ymd4 = 2003 / etl::chrono::month_day(etl::chrono::April, etl::chrono::day(4)); + etl::chrono::year_month_day ymd5 = etl::chrono::month_day(etl::chrono::May, etl::chrono::day(5)) / etl::chrono::year(2004); + etl::chrono::year_month_day ymd6 = etl::chrono::month_day(etl::chrono::June, etl::chrono::day(6)) / 2005; + + CHECK_EQUAL(etl::chrono::year(2000), ymd1.year()); + CHECK_EQUAL(etl::chrono::January, ymd1.month()); + CHECK_EQUAL(etl::chrono::day(1), ymd1.day()); + + CHECK_EQUAL(etl::chrono::year(2001), ymd2.year()); + CHECK_EQUAL(etl::chrono::February, ymd2.month()); + CHECK_EQUAL(etl::chrono::day(2), ymd2.day()); + + CHECK_EQUAL(etl::chrono::year(2002), ymd3.year()); + CHECK_EQUAL(etl::chrono::March, ymd3.month()); + CHECK_EQUAL(etl::chrono::day(3), ymd3.day()); + + CHECK_EQUAL(etl::chrono::year(2003), ymd4.year()); + CHECK_EQUAL(etl::chrono::April, ymd4.month()); + CHECK_EQUAL(etl::chrono::day(4), ymd4.day()); + + CHECK_EQUAL(etl::chrono::year(2004), ymd5.year()); + CHECK_EQUAL(etl::chrono::May, ymd5.month()); + CHECK_EQUAL(etl::chrono::day(5), ymd5.day()); + + CHECK_EQUAL(etl::chrono::year(2005), ymd6.year()); + CHECK_EQUAL(etl::chrono::June, ymd6.month()); + CHECK_EQUAL(etl::chrono::day(6), ymd6.day()); + } + + //************************************************************************* + TEST(test_construction_operator_for_year_month_day_last) + { + etl::chrono::year_month_day_last ymdl1 = etl::chrono::year_month(etl::chrono::year(2000), etl::chrono::January) / etl::chrono::last; + etl::chrono::year_month_day_last ymdl2 = etl::chrono::year(2001) / etl::chrono::month_day_last(etl::chrono::February); + etl::chrono::year_month_day_last ymdl3 = 2002 / etl::chrono::month_day_last(etl::chrono::March); + etl::chrono::year_month_day_last ymdl4 = etl::chrono::month_day_last(etl::chrono::April) / etl::chrono::year(2003); + etl::chrono::year_month_day_last ymdl5 = etl::chrono::month_day_last(etl::chrono::May) / 2004; + + CHECK_EQUAL(etl::chrono::year(2000), ymdl1.year()); + CHECK_EQUAL(etl::chrono::January, ymdl1.month()); + CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::January).day(), ymdl1.day()); + CHECK_TRUE(etl::chrono::month_day_last(etl::chrono::January) == ymdl1.month_day_last()); + + CHECK_EQUAL(etl::chrono::year(2001), ymdl2.year()); + CHECK_EQUAL(etl::chrono::February, ymdl2.month()); + CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::February).day(), ymdl2.day()); + CHECK_TRUE(etl::chrono::month_day_last(etl::chrono::February) == ymdl2.month_day_last()); + + CHECK_EQUAL(etl::chrono::year(2002), ymdl3.year()); + CHECK_EQUAL(etl::chrono::March, ymdl3.month()); + CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::March).day(), ymdl3.day()); + CHECK_TRUE(etl::chrono::month_day_last(etl::chrono::March) == ymdl3.month_day_last()); + + CHECK_EQUAL(etl::chrono::year(2003), ymdl4.year()); + CHECK_EQUAL(etl::chrono::April, ymdl4.month()); + CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::April).day(), ymdl4.day()); + CHECK_TRUE(etl::chrono::month_day_last(etl::chrono::April) == ymdl4.month_day_last()); + + CHECK_EQUAL(etl::chrono::year(2004), ymdl5.year()); + CHECK_EQUAL(etl::chrono::May, ymdl5.month()); + CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::May).day(), ymdl5.day()); + CHECK_TRUE(etl::chrono::month_day_last(etl::chrono::May) == ymdl5.month_day_last()); + } + + //************************************************************************* + TEST(test_construction_operator_for_year_month_weekday) + { + etl::chrono::year_month_weekday ymwd1 = etl::chrono::year_month(etl::chrono::year(2000), etl::chrono::January) / etl::chrono::weekday_indexed(etl::chrono::Monday, 0); + etl::chrono::year_month_weekday ymwd2 = etl::chrono::year(2001) / etl::chrono::month_weekday(etl::chrono::February, etl::chrono::weekday_indexed(etl::chrono::Tuesday, 1)); + etl::chrono::year_month_weekday ymwd3 = 2002 / etl::chrono::month_weekday(etl::chrono::March, etl::chrono::weekday_indexed(etl::chrono::Wednesday, 2)); + etl::chrono::year_month_weekday ymwd4 = etl::chrono::month_weekday(etl::chrono::April, etl::chrono::weekday_indexed(etl::chrono::Thursday, 3)) / etl::chrono::year(2003); + etl::chrono::year_month_weekday ymwd5 = etl::chrono::month_weekday(etl::chrono::May, etl::chrono::weekday_indexed(etl::chrono::Friday, 4)) / 2004; + + CHECK_EQUAL(etl::chrono::year(2000), ymwd1.year()); + CHECK_EQUAL(etl::chrono::January, ymwd1.month()); + CHECK_EQUAL(etl::chrono::Monday.c_encoding(), ymwd1.weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::Monday.c_encoding(), ymwd1.weekday_indexed().weekday().c_encoding()); + CHECK_EQUAL(0, ymwd1.weekday_indexed().index()); + + CHECK_EQUAL(etl::chrono::year(2001), ymwd2.year()); + CHECK_EQUAL(etl::chrono::February, ymwd2.month()); + CHECK_EQUAL(etl::chrono::Tuesday.c_encoding(), ymwd2.weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::Tuesday.c_encoding(), ymwd2.weekday_indexed().weekday().c_encoding()); + CHECK_EQUAL(1, ymwd2.weekday_indexed().index()); + + CHECK_EQUAL(etl::chrono::year(2002), ymwd3.year()); + CHECK_EQUAL(etl::chrono::March, ymwd3.month()); + CHECK_EQUAL(etl::chrono::Wednesday.c_encoding(), ymwd3.weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::Wednesday.c_encoding(), ymwd3.weekday_indexed().weekday().c_encoding()); + CHECK_EQUAL(2, ymwd3.weekday_indexed().index()); + + CHECK_EQUAL(etl::chrono::year(2003), ymwd4.year()); + CHECK_EQUAL(etl::chrono::April, ymwd4.month()); + CHECK_EQUAL(etl::chrono::Thursday.c_encoding(), ymwd4.weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::Thursday.c_encoding(), ymwd4.weekday_indexed().weekday().c_encoding()); + CHECK_EQUAL(3, ymwd4.weekday_indexed().index()); + + CHECK_EQUAL(etl::chrono::year(2004), ymwd5.year()); + CHECK_EQUAL(etl::chrono::May, ymwd5.month()); + CHECK_EQUAL(etl::chrono::Friday.c_encoding(), ymwd5.weekday().c_encoding()); + CHECK_EQUAL(etl::chrono::Friday.c_encoding(), ymwd5.weekday_indexed().weekday().c_encoding()); + CHECK_EQUAL(4, ymwd5.weekday_indexed().index()); + } + + //************************************************************************* + TEST(test_construction_operator_for_year_month_weekday_last) + { + etl::chrono::year_month_weekday_last ymdl1 = etl::chrono::year_month(etl::chrono::year(2000), etl::chrono::January) / etl::chrono::weekday_last(etl::chrono::Monday); + etl::chrono::year_month_weekday_last ymdl2 = etl::chrono::year(2001) / etl::chrono::month_weekday_last(etl::chrono::February, etl::chrono::weekday_last(etl::chrono::Tuesday)); + etl::chrono::year_month_weekday_last ymdl3 = 2002 / etl::chrono::month_weekday_last(etl::chrono::March, etl::chrono::weekday_last(etl::chrono::Wednesday)); + etl::chrono::year_month_weekday_last ymdl4 = etl::chrono::month_weekday_last(etl::chrono::April, etl::chrono::weekday_last(etl::chrono::Thursday)) / etl::chrono::year(2003); + etl::chrono::year_month_weekday_last ymdl5 = etl::chrono::month_weekday_last(etl::chrono::May, etl::chrono::weekday_last(etl::chrono::Friday))/ 2004; + + CHECK_EQUAL(etl::chrono::year(2000), ymdl1.year()); + CHECK_EQUAL(etl::chrono::January, ymdl1.month()); + CHECK_EQUAL(etl::chrono::weekday_last(etl::chrono::Monday).weekday().c_encoding(), ymdl1.weekday().c_encoding()); + + CHECK_EQUAL(etl::chrono::year(2001), ymdl2.year()); + CHECK_EQUAL(etl::chrono::February, ymdl2.month()); + CHECK_EQUAL(etl::chrono::weekday_last(etl::chrono::Tuesday).weekday().c_encoding(), ymdl2.weekday().c_encoding()); + + CHECK_EQUAL(etl::chrono::year(2002), ymdl3.year()); + CHECK_EQUAL(etl::chrono::March, ymdl3.month()); + CHECK_EQUAL(etl::chrono::weekday_last(etl::chrono::Wednesday).weekday().c_encoding(), ymdl3.weekday().c_encoding()); + + CHECK_EQUAL(etl::chrono::year(2003), ymdl4.year()); + CHECK_EQUAL(etl::chrono::April, ymdl4.month()); + CHECK_EQUAL(etl::chrono::weekday_last(etl::chrono::Thursday).weekday().c_encoding(), ymdl4.weekday().c_encoding()); + + CHECK_EQUAL(etl::chrono::year(2004), ymdl5.year()); + CHECK_EQUAL(etl::chrono::May, ymdl5.month()); + CHECK_EQUAL(etl::chrono::weekday_last(etl::chrono::Friday).weekday().c_encoding(), ymdl5.weekday().c_encoding()); } }; -} +} \ No newline at end of file diff --git a/test/test_chrono_year.cpp b/test/test_chrono_year.cpp index 70c17c8a..90f909a6 100644 --- a/test/test_chrono_year.cpp +++ b/test/test_chrono_year.cpp @@ -243,7 +243,7 @@ namespace { for (int i = -32767; i <= 32767; ++i) { - bool is_leap = ((i % 4) == 0) && ((i % 400) != 0); + bool is_leap = ((i % 4) == 0) && (((i % 100) != 0) || ((i % 400) == 0)); etl::chrono::year year(i); diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index af492705..8489c79f 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -3195,9 +3195,13 @@ + + + + @@ -8472,6 +8476,7 @@ + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 02a49851..7dea846b 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -1497,6 +1497,18 @@ ETL\Private\chrono + + ETL\Private\chrono + + + ETL\Private\chrono + + + ETL\Private\chrono + + + ETL\Private\chrono + @@ -3551,6 +3563,9 @@ Tests\Chrono + + Tests\Chrono + From 39f17a94b8ddf79f4b713955be5a3bb99bd4dbf2 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 28 Apr 2025 19:58:39 +0100 Subject: [PATCH 22/33] Added floating point duration types --- include/etl/private/chrono/duration.h | 48 +++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/include/etl/private/chrono/duration.h b/include/etl/private/chrono/duration.h index 1b929709..409a2486 100644 --- a/include/etl/private/chrono/duration.h +++ b/include/etl/private/chrono/duration.h @@ -628,6 +628,14 @@ namespace etl return etl::chrono::hours(static_cast(h)); } + //*********************************************************************** + /// Literal for floating point hours duration + //*********************************************************************** + inline ETL_CONSTEXPR etl::chrono::duration> operator""_h(long double h) noexcept + { + return etl::chrono::duration>(h); + } + //*********************************************************************** /// Literal for minutes duration //*********************************************************************** @@ -636,6 +644,14 @@ namespace etl return etl::chrono::minutes(static_cast(m)); } + //*********************************************************************** + /// Literal for floating point minutes duration + //*********************************************************************** + inline ETL_CONSTEXPR etl::chrono::duration> operator ""_minutes(long double m) noexcept + { + return etl::chrono::duration>(m); + } + //*********************************************************************** /// Literal for seconds duration //*********************************************************************** @@ -644,6 +660,14 @@ namespace etl return etl::chrono::seconds(static_cast(s)); } + //*********************************************************************** + /// Literal for floating point seconds duration + //*********************************************************************** + inline ETL_CONSTEXPR etl::chrono::duration operator ""_seconds(long double s) noexcept + { + return etl::chrono::duration(s); + } + //*********************************************************************** /// Literal for milliseconds duration //*********************************************************************** @@ -652,6 +676,14 @@ namespace etl return etl::chrono::milliseconds(static_cast(s)); } + //*********************************************************************** + /// Literal for floating point milliseconds duration + //*********************************************************************** + inline ETL_CONSTEXPR etl::chrono::duration operator ""_milliseconds(long double s) noexcept + { + return etl::chrono::duration(s); + } + //*********************************************************************** /// Literal for microseconds duration //*********************************************************************** @@ -660,6 +692,14 @@ namespace etl return etl::chrono::microseconds(static_cast(s)); } + //*********************************************************************** + /// Literal for floating point microseconds duration + //*********************************************************************** + inline ETL_CONSTEXPR etl::chrono::duration operator ""_microseconds(long double s) noexcept + { + return etl::chrono::duration(s); + } + //*********************************************************************** /// Literal for nanoseconds duration //*********************************************************************** @@ -667,6 +707,14 @@ namespace etl { return etl::chrono::nanoseconds(static_cast(s)); } + + //*********************************************************************** + /// Literal for floating point microseconds duration + //*********************************************************************** + inline ETL_CONSTEXPR etl::chrono::duration operator ""_nanoseconds(long double s) noexcept + { + return etl::chrono::duration(s); + } } } } From e7cbc10df8095eca4bccc653f7703ed3b05341fe Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 28 Apr 2025 19:59:32 +0100 Subject: [PATCH 23/33] Added experimental system_clock, time_point, and time_zone classes --- include/etl/private/chrono/system_clock.h | 2 +- include/etl/private/chrono/time_point.h | 2 +- include/etl/private/chrono/time_zone.h | 80 +++++++++++++++++++++++ 3 files changed, 82 insertions(+), 2 deletions(-) create mode 100644 include/etl/private/chrono/time_zone.h diff --git a/include/etl/private/chrono/system_clock.h b/include/etl/private/chrono/system_clock.h index 99341313..a9d6f714 100644 --- a/include/etl/private/chrono/system_clock.h +++ b/include/etl/private/chrono/system_clock.h @@ -38,7 +38,7 @@ namespace etl { class system_clock { - + using duration = etl::chrono::seconds; }; template diff --git a/include/etl/private/chrono/time_point.h b/include/etl/private/chrono/time_point.h index 0d48acb3..2ee0159f 100644 --- a/include/etl/private/chrono/time_point.h +++ b/include/etl/private/chrono/time_point.h @@ -78,7 +78,7 @@ namespace etl /// Copy construct from another time_point with a different duration type. //*************************************************************************** template - explicit time_point(const time_point& rhs) ETL_NOEXCEPT + explicit time_point(const time_point& rhs) ETL_NOEXCEPT : dur(rhs.time_since_epoch()) { } diff --git a/include/etl/private/chrono/time_zone.h b/include/etl/private/chrono/time_zone.h new file mode 100644 index 00000000..a01154a9 --- /dev/null +++ b/include/etl/private/chrono/time_zone.h @@ -0,0 +1,80 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_IN_CHRONO_H + #error DO NOT DIRECTLY INCLUDE THIS FILE. USE CHRONO.H +#endif + +namespace etl +{ + namespace chrono + { + //class time_zone + //{ + //public: + + // /// Obtains the name of this time_zone. + // etl::string_view name() const ETL_NOEXCEPT + // { + // return etl::string_view(tz_name, etl::strlen(tz_name)); + // } + + // template + // etl::chrono::sys_info get_info(const etl::chrono::sys_time& tp) const + // { + + // } + + // template + // etl::chrono::local_info get_info(const etl::chrono::local_time& tp) const + // { + // return etl::chrono::local_info(); + // } + + // template + // etl::chrono::sys_time> to_sys(const etl::chrono::local_time& tp) const + // { + // etl::chrono::sys_time>() + // } + + // template + // etl::chrono::sys_time> to_sys(const etl::chrono::local_time& tp, + // etl::chrono::choose z) const + // { + // etl::chrono::sys_time>(); + // } + + //private: + + // static const char *tz_name; + + //}; + } +} \ No newline at end of file From 5143aa7f530ba4b150ce9fdca82b2bbd6067d781 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 28 Apr 2025 20:00:18 +0100 Subject: [PATCH 24/33] Added year_month_day and year_month_day_last classes and tests --- include/etl/chrono.h | 2 + include/etl/private/chrono/year_month_day.h | 17 +- test/test_chrono_operators.cpp | 10 +- test/test_chrono_year_month.cpp | 32 ++-- test/test_chrono_year_month_day.cpp | 167 ++++++++++++++++++++ test/test_chrono_year_month_day_last.cpp | 145 +++++++++++++++++ test/vs2022/etl.vcxproj | 3 + test/vs2022/etl.vcxproj.filters | 9 ++ 8 files changed, 364 insertions(+), 21 deletions(-) create mode 100644 test/test_chrono_year_month_day.cpp create mode 100644 test/test_chrono_year_month_day_last.cpp diff --git a/include/etl/chrono.h b/include/etl/chrono.h index 8fce7d57..fbc0b47d 100644 --- a/include/etl/chrono.h +++ b/include/etl/chrono.h @@ -36,6 +36,7 @@ SOFTWARE. #include "platform.h" #include "type_traits.h" #include "integral_limits.h" +#include "string_view.h" #if ETL_NOT_USING_CPP11 #error NOT SUPPORTED FOR C++03 OR BELOW @@ -75,6 +76,7 @@ namespace etl #include "private/chrono/year_month_weekday.h" #include "private/chrono/hh_mm_ss.h" #include "private/chrono/operators.h" +#include "private/chrono/time_zone.h" #endif #undef ETL_IN_CHRONO_H diff --git a/include/etl/private/chrono/year_month_day.h b/include/etl/private/chrono/year_month_day.h index 101dcfb3..0cae2211 100644 --- a/include/etl/private/chrono/year_month_day.h +++ b/include/etl/private/chrono/year_month_day.h @@ -245,7 +245,11 @@ namespace etl ////*********************************************************************** //ETL_CONSTEXPR14 explicit operator etl::chrono::local_days() const ETL_NOEXCEPT //{ - // return etl::chrono::local_days(); + //// Convert the year_month_day to sys_days first + //etl::chrono::sys_days sys_days_representation = static_cast(*this); + + //// Convert sys_days to local_days (assuming local_days is a wrapper around sys_days) + //return etl::chrono::local_days(sys_days_representation); //} private: @@ -270,7 +274,6 @@ namespace etl : y(y) , m(mdl.month()) { - } //************************************************************************* @@ -305,6 +308,16 @@ namespace etl return etl::chrono::month_day_last(m); } + //************************************************************************* + /// + //************************************************************************* + ETL_CONSTEXPR14 bool ok() const ETL_NOEXCEPT + { + return y.ok() && + m.ok() && + day() == etl::chrono::month_day_last(m).day(); + } + //************************************************************************* /// //************************************************************************* diff --git a/test/test_chrono_operators.cpp b/test/test_chrono_operators.cpp index f9fca7ff..f9f55b78 100644 --- a/test/test_chrono_operators.cpp +++ b/test/test_chrono_operators.cpp @@ -194,27 +194,27 @@ namespace CHECK_EQUAL(etl::chrono::year(2000), ymdl1.year()); CHECK_EQUAL(etl::chrono::January, ymdl1.month()); CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::January).day(), ymdl1.day()); - CHECK_TRUE(etl::chrono::month_day_last(etl::chrono::January) == ymdl1.month_day_last()); + CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::January).month(), ymdl1.month_day_last().month()); CHECK_EQUAL(etl::chrono::year(2001), ymdl2.year()); CHECK_EQUAL(etl::chrono::February, ymdl2.month()); CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::February).day(), ymdl2.day()); - CHECK_TRUE(etl::chrono::month_day_last(etl::chrono::February) == ymdl2.month_day_last()); + CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::February).month(), ymdl2.month_day_last().month()); CHECK_EQUAL(etl::chrono::year(2002), ymdl3.year()); CHECK_EQUAL(etl::chrono::March, ymdl3.month()); CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::March).day(), ymdl3.day()); - CHECK_TRUE(etl::chrono::month_day_last(etl::chrono::March) == ymdl3.month_day_last()); + CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::March).month(), ymdl3.month_day_last().month()); CHECK_EQUAL(etl::chrono::year(2003), ymdl4.year()); CHECK_EQUAL(etl::chrono::April, ymdl4.month()); CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::April).day(), ymdl4.day()); - CHECK_TRUE(etl::chrono::month_day_last(etl::chrono::April) == ymdl4.month_day_last()); + CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::April).month(), ymdl4.month_day_last().month()); CHECK_EQUAL(etl::chrono::year(2004), ymdl5.year()); CHECK_EQUAL(etl::chrono::May, ymdl5.month()); CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::May).day(), ymdl5.day()); - CHECK_TRUE(etl::chrono::month_day_last(etl::chrono::May) == ymdl5.month_day_last()); + CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::May).month(), ymdl5.month_day_last().month()); } //************************************************************************* diff --git a/test/test_chrono_year_month.cpp b/test/test_chrono_year_month.cpp index bd3a87f5..a0e8ab7f 100644 --- a/test/test_chrono_year_month.cpp +++ b/test/test_chrono_year_month.cpp @@ -94,12 +94,14 @@ namespace TEST(test_year_month_spaceship_operator) { Chrono::year_month ym1{Chrono::year(2000), Chrono::January}; - Chrono::year_month ym2{Chrono::year(2001), Chrono::February}; - Chrono::year_month ym3{Chrono::year(2000), Chrono::January}; + Chrono::year_month ym2{Chrono::year(2001), Chrono::January}; + Chrono::year_month ym3{Chrono::year(2000), Chrono::February}; - CHECK_TRUE((ym1 <=> ym3) == std::strong_ordering::equal); + 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); } #endif @@ -108,12 +110,14 @@ namespace TEST(test_year_month_compare) { Chrono::year_month ym1{Chrono::year(2000), Chrono::January}; - Chrono::year_month ym2{Chrono::year(2001), Chrono::February}; - Chrono::year_month ym3{Chrono::year(2000), Chrono::January}; + Chrono::year_month ym2{Chrono::year(2001), Chrono::January}; + Chrono::year_month ym3{Chrono::year(2000), Chrono::February}; - CHECK_TRUE(ym1.compare(ym3) == 0); + CHECK_TRUE(ym1.compare(ym1) == 0); CHECK_TRUE(ym1.compare(ym2) == -1); CHECK_TRUE(ym2.compare(ym1) == 1); + CHECK_TRUE(ym1.compare(ym3) == -1); + CHECK_TRUE(ym3.compare(ym1) == 1); } #endif @@ -121,24 +125,24 @@ namespace TEST(test_year_month_equality_operator) { Chrono::year_month ym1{Chrono::year(2000), Chrono::January}; - Chrono::year_month ym2{Chrono::year(2001), Chrono::February}; + Chrono::year_month ym2{Chrono::year(2001), Chrono::January}; Chrono::year_month ym3{Chrono::year(2000), Chrono::February}; - CHECK_TRUE(ym1 == ym1); // 2000/January - CHECK_FALSE(ym1 == ym2); // 2000/January != 2001/February - CHECK_FALSE(ym1 == ym3); // 2000/January != 2000/February + CHECK_TRUE(ym1 == ym1); // Same year/month/day + CHECK_FALSE(ym1 == ym2); // Different year + CHECK_FALSE(ym1 == ym3); // Different month } //************************************************************************* TEST(test_year_month_not_equality_operator) { Chrono::year_month ym1{Chrono::year(2000), Chrono::January}; - Chrono::year_month ym2{Chrono::year(2001), Chrono::February}; + Chrono::year_month ym2{Chrono::year(2001), Chrono::January}; Chrono::year_month ym3{Chrono::year(2000), Chrono::February}; - CHECK_FALSE(ym1 != ym1); // 2000/January - CHECK_TRUE(ym1 != ym2); // 2000/January != 2001/February - CHECK_TRUE(ym1 != ym3); // 2000/January != 2000/February + CHECK_FALSE(ym1 != ym1); // Same year/month/day + CHECK_TRUE(ym1 != ym2); // Different year + CHECK_TRUE(ym1 != ym3); // Different month } }; } diff --git a/test/test_chrono_year_month_day.cpp b/test/test_chrono_year_month_day.cpp new file mode 100644 index 00000000..77641c7d --- /dev/null +++ b/test/test_chrono_year_month_day.cpp @@ -0,0 +1,167 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include +#include + +// Set to 0 to reference against std::chrono +#define ETL_USING_ETL_CHRONO 1 + +#if ETL_USING_ETL_CHRONO + #define Chrono etl::chrono +#else + #if ETL_USING_CPP20 + #include + #define Chrono std::chrono + #else + #error std::chrono not supported + #endif +#endif + +namespace +{ + SUITE(test_chrono_year_month_day) + { + //************************************************************************* + TEST(test_default_constructor) + { + Chrono::year_month_day ymd; + + CHECK_FALSE(ymd.ok()); // Default-constructed year_month_day is not valid + } + + //************************************************************************* + TEST(test_constructor_with_month_and_day) + { + Chrono::year_month_day ymd{Chrono::year(2000), Chrono::January, Chrono::day(1)}; + + CHECK_TRUE(ymd.ok()); // Valid year_month_day + CHECK_EQUAL(2000, (int)ymd.year()); + CHECK_EQUAL((unsigned)Chrono::January, (unsigned)ymd.month()); + CHECK_EQUAL(Chrono::day(1), ymd.day()); + } + + //************************************************************************* + TEST(test_invalid_year_month) + { + Chrono::year_month_day ymd{Chrono::year{32768}, Chrono::January, Chrono::day(1)}; // Invalid year + + CHECK_FALSE(ymd.ok()); // Invalid year_month_day + } + + //************************************************************************* + TEST(test_invalid_month_in_year_month) + { + Chrono::year_month_day ymd{Chrono::year{2000}, Chrono::month{13}, Chrono::day(1)}; // Invalid month (13) + + CHECK_FALSE(ymd.ok()); // Invalid year_month_day + } + + //************************************************************************* + TEST(test_invalid_day_in_year_month) + { + Chrono::year_month_day ymd{Chrono::year{2000}, Chrono::January, Chrono::day(32)}; // Invalid day (32) + + CHECK_FALSE(ymd.ok()); // Invalid year_month_day + } + +#if ETL_USING_CPP20 + //************************************************************************* + TEST(test_year_month_day_spaceship_operator) + { + Chrono::year_month_day ym1{Chrono::year(2000), Chrono::January, Chrono::day(1)}; + Chrono::year_month_day ym2{Chrono::year(2001), Chrono::January, Chrono::day(1)}; + 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); + } +#endif + +#if ETL_USING_ETL_CHRONO + //************************************************************************* + TEST(test_year_month_day_compare) + { + Chrono::year_month_day ym1{Chrono::year(2000), Chrono::January, Chrono::day(1)}; + Chrono::year_month_day ym2{Chrono::year(2001), Chrono::January, Chrono::day(1)}; + 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.compare(ym1) == 0); + CHECK_TRUE(ym1.compare(ym2) == -1); + CHECK_TRUE(ym2.compare(ym1) == 1); + CHECK_TRUE(ym1.compare(ym3) == -1); + CHECK_TRUE(ym3.compare(ym1) == 1); + CHECK_TRUE(ym1.compare(ym4) == -1); + CHECK_TRUE(ym4.compare(ym1) == 1); + } +#endif + + //************************************************************************* + TEST(test_year_month_day_equality_operator) + { + Chrono::year_month_day ym1{Chrono::year(2000), Chrono::January, Chrono::day(1)}; + Chrono::year_month_day ym2{Chrono::year(2001), Chrono::January, Chrono::day(1)}; + 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); // Same year/month/day + CHECK_FALSE(ym1 == ym2); // Different year + CHECK_FALSE(ym1 == ym3); // Different month + CHECK_FALSE(ym1 == ym4); // Different day + } + + //************************************************************************* + TEST(test_year_month_day_not_equality_operator) + { + Chrono::year_month_day ym1{Chrono::year(2000), Chrono::January, Chrono::day(1)}; + Chrono::year_month_day ym2{Chrono::year(2001), Chrono::January, Chrono::day(1)}; + 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_FALSE(ym1 != ym1); // Same year/month/day + CHECK_TRUE(ym1 != ym2); // Different year + CHECK_TRUE(ym1 != ym3); // Different month + CHECK_TRUE(ym1 != ym4); // Different day + } + }; +} diff --git a/test/test_chrono_year_month_day_last.cpp b/test/test_chrono_year_month_day_last.cpp new file mode 100644 index 00000000..28df871a --- /dev/null +++ b/test/test_chrono_year_month_day_last.cpp @@ -0,0 +1,145 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Documentation: + +Copyright(c) 2025 John Wellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "etl/platform.h" + +#include "unit_test_framework.h" + +#include "etl/chrono.h" + +#include +#include +#include + +// Set to 0 to reference against std::chrono +#define ETL_USING_ETL_CHRONO 1 + +#if ETL_USING_ETL_CHRONO + #define Chrono etl::chrono +#else + #if ETL_USING_CPP20 + #include + #define Chrono std::chrono + #else + #error std::chrono not supported + #endif +#endif + +namespace +{ + SUITE(test_chrono_year_month_day_last) + { + //************************************************************************* + TEST(test_constructor_in_range) + { + Chrono::year_month_day_last year_month_day_last_2000_january(Chrono::year(2000), Chrono::month_day_last(Chrono::January)); + Chrono::year_month_day_last year_month_day_last_2001_february(Chrono::year(2001), Chrono::month_day_last(Chrono::February)); + Chrono::year_month_day_last year_month_day_last_2002_march(Chrono::year(2002), Chrono::month_day_last(Chrono::March)); + Chrono::year_month_day_last year_month_day_last_2003_april(Chrono::year(2003), Chrono::month_day_last(Chrono::April)); + Chrono::year_month_day_last year_month_day_last_2004_may(Chrono::year(2004), Chrono::month_day_last(Chrono::May)); + Chrono::year_month_day_last year_month_day_last_2005_june(Chrono::year(2005), Chrono::month_day_last(Chrono::June)); + Chrono::year_month_day_last year_month_day_last_2006_july(Chrono::year(2006), Chrono::month_day_last(Chrono::July)); + Chrono::year_month_day_last year_month_day_last_2007_august(Chrono::year(2007), Chrono::month_day_last(Chrono::August)); + Chrono::year_month_day_last year_month_day_last_2008_september(Chrono::year(2008), Chrono::month_day_last(Chrono::September)); + Chrono::year_month_day_last year_month_day_last_2009_october(Chrono::year(2009), Chrono::month_day_last(Chrono::October)); + Chrono::year_month_day_last year_month_day_last_2010_november(Chrono::year(2010), Chrono::month_day_last(Chrono::November)); + Chrono::year_month_day_last year_month_day_last_2011_december(Chrono::year(2011), Chrono::month_day_last(Chrono::December)); + + CHECK_TRUE(year_month_day_last_2000_january.ok()); + CHECK_TRUE(year_month_day_last_2001_february.ok()); + CHECK_TRUE(year_month_day_last_2002_march.ok()); + CHECK_TRUE(year_month_day_last_2003_april.ok()); + CHECK_TRUE(year_month_day_last_2004_may.ok()); + CHECK_TRUE(year_month_day_last_2005_june.ok()); + CHECK_TRUE(year_month_day_last_2006_july.ok()); + CHECK_TRUE(year_month_day_last_2007_august.ok()); + CHECK_TRUE(year_month_day_last_2008_september.ok()); + CHECK_TRUE(year_month_day_last_2009_october.ok()); + CHECK_TRUE(year_month_day_last_2010_november.ok()); + CHECK_TRUE(year_month_day_last_2011_december.ok()); + + CHECK_EQUAL(31, year_month_day_last_2000_january.day()); + CHECK_EQUAL(29, year_month_day_last_2001_february.day()); + CHECK_EQUAL(31, year_month_day_last_2002_march.day()); + CHECK_EQUAL(30, year_month_day_last_2003_april.day()); + CHECK_EQUAL(31, year_month_day_last_2004_may.day()); + CHECK_EQUAL(30, year_month_day_last_2005_june.day()); + CHECK_EQUAL(31, year_month_day_last_2006_july.day()); + CHECK_EQUAL(31, year_month_day_last_2007_august.day()); + CHECK_EQUAL(30, year_month_day_last_2008_september.day()); + CHECK_EQUAL(31, year_month_day_last_2009_october.day()); + CHECK_EQUAL(30, year_month_day_last_2010_november.day()); + CHECK_EQUAL(31, year_month_day_last_2011_december.day()); + } + + //************************************************************************* + TEST(test_year_month_day_last_comparison_operators) + { + 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)); + + CHECK_TRUE(year_month_day_last1 == year_month_day_last1); + CHECK_FALSE(year_month_day_last1 == year_month_day_last2); + CHECK_FALSE(year_month_day_last1 == year_month_day_last3); + + CHECK_FALSE(year_month_day_last1 != year_month_day_last1); + CHECK_TRUE(year_month_day_last1 != year_month_day_last2); + CHECK_TRUE(year_month_day_last1 != year_month_day_last3); + } + +#if ETL_USING_ETL_CHRONO + //************************************************************************* + TEST(test_year_month_day_last_hashes_are_unique) + { + std::vector hashes; + + for (int i = 0; i < 6; ++i) + { + hashes.push_back(etl::hash()(Chrono::year_month_day_last(Chrono::year(2000), Chrono::month_day_last(Chrono::January)))); + hashes.push_back(etl::hash()(Chrono::year_month_day_last(Chrono::year(2001), Chrono::month_day_last(Chrono::February)))); + hashes.push_back(etl::hash()(Chrono::year_month_day_last(Chrono::year(2002), Chrono::month_day_last(Chrono::March)))); + hashes.push_back(etl::hash()(Chrono::year_month_day_last(Chrono::year(2003), Chrono::month_day_last(Chrono::April)))); + hashes.push_back(etl::hash()(Chrono::year_month_day_last(Chrono::year(2004), Chrono::month_day_last(Chrono::May)))); + hashes.push_back(etl::hash()(Chrono::year_month_day_last(Chrono::year(2005), Chrono::month_day_last(Chrono::January)))); + hashes.push_back(etl::hash()(Chrono::year_month_day_last(Chrono::year(2006), Chrono::month_day_last(Chrono::January)))); + hashes.push_back(etl::hash()(Chrono::year_month_day_last(Chrono::year(2007), Chrono::month_day_last(Chrono::January)))); + hashes.push_back(etl::hash()(Chrono::year_month_day_last(Chrono::year(2008), Chrono::month_day_last(Chrono::January)))); + hashes.push_back(etl::hash()(Chrono::year_month_day_last(Chrono::year(2009), Chrono::month_day_last(Chrono::January)))); + hashes.push_back(etl::hash()(Chrono::year_month_day_last(Chrono::year(2010), Chrono::month_day_last(Chrono::January)))); + hashes.push_back(etl::hash()(Chrono::year_month_day_last(Chrono::year(2011), Chrono::month_day_last(Chrono::January)))); + } + + std::sort(hashes.begin(), hashes.end()); + (void)std::unique(hashes.begin(), hashes.end()); + } +#endif + }; +} diff --git a/test/vs2022/etl.vcxproj b/test/vs2022/etl.vcxproj index 8489c79f..e94c20bc 100644 --- a/test/vs2022/etl.vcxproj +++ b/test/vs2022/etl.vcxproj @@ -3197,6 +3197,7 @@ + @@ -8482,6 +8483,8 @@ + + diff --git a/test/vs2022/etl.vcxproj.filters b/test/vs2022/etl.vcxproj.filters index 7dea846b..04a09031 100644 --- a/test/vs2022/etl.vcxproj.filters +++ b/test/vs2022/etl.vcxproj.filters @@ -1509,6 +1509,9 @@ ETL\Private\chrono + + ETL\Private\chrono + @@ -3566,6 +3569,12 @@ Tests\Chrono + + Tests\Chrono + + + Tests\Chrono + From 42ba4d824841fc002524c3d51221e4f7bcac19dd Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 30 Apr 2025 09:26:34 +0100 Subject: [PATCH 25/33] Updated tests --- test/test_chrono_year_month_day_last.cpp | 27 +++++++++++++----------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/test/test_chrono_year_month_day_last.cpp b/test/test_chrono_year_month_day_last.cpp index 28df871a..3fc82f1a 100644 --- a/test/test_chrono_year_month_day_last.cpp +++ b/test/test_chrono_year_month_day_last.cpp @@ -60,6 +60,7 @@ namespace TEST(test_constructor_in_range) { Chrono::year_month_day_last year_month_day_last_2000_january(Chrono::year(2000), Chrono::month_day_last(Chrono::January)); + Chrono::year_month_day_last year_month_day_last_2000_february(Chrono::year(2000), Chrono::month_day_last(Chrono::February)); Chrono::year_month_day_last year_month_day_last_2001_february(Chrono::year(2001), Chrono::month_day_last(Chrono::February)); Chrono::year_month_day_last year_month_day_last_2002_march(Chrono::year(2002), Chrono::month_day_last(Chrono::March)); Chrono::year_month_day_last year_month_day_last_2003_april(Chrono::year(2003), Chrono::month_day_last(Chrono::April)); @@ -73,6 +74,7 @@ namespace Chrono::year_month_day_last year_month_day_last_2011_december(Chrono::year(2011), Chrono::month_day_last(Chrono::December)); CHECK_TRUE(year_month_day_last_2000_january.ok()); + CHECK_TRUE(year_month_day_last_2000_february.ok()); CHECK_TRUE(year_month_day_last_2001_february.ok()); CHECK_TRUE(year_month_day_last_2002_march.ok()); CHECK_TRUE(year_month_day_last_2003_april.ok()); @@ -85,18 +87,19 @@ namespace CHECK_TRUE(year_month_day_last_2010_november.ok()); CHECK_TRUE(year_month_day_last_2011_december.ok()); - CHECK_EQUAL(31, year_month_day_last_2000_january.day()); - CHECK_EQUAL(29, year_month_day_last_2001_february.day()); - CHECK_EQUAL(31, year_month_day_last_2002_march.day()); - CHECK_EQUAL(30, year_month_day_last_2003_april.day()); - CHECK_EQUAL(31, year_month_day_last_2004_may.day()); - CHECK_EQUAL(30, year_month_day_last_2005_june.day()); - CHECK_EQUAL(31, year_month_day_last_2006_july.day()); - CHECK_EQUAL(31, year_month_day_last_2007_august.day()); - CHECK_EQUAL(30, year_month_day_last_2008_september.day()); - CHECK_EQUAL(31, year_month_day_last_2009_october.day()); - CHECK_EQUAL(30, year_month_day_last_2010_november.day()); - CHECK_EQUAL(31, year_month_day_last_2011_december.day()); + CHECK_EQUAL(31, (unsigned)year_month_day_last_2000_january.day()); + CHECK_EQUAL(29, (unsigned)year_month_day_last_2000_february.day()); + CHECK_EQUAL(28, (unsigned)year_month_day_last_2001_february.day()); + CHECK_EQUAL(31, (unsigned)year_month_day_last_2002_march.day()); + CHECK_EQUAL(30, (unsigned)year_month_day_last_2003_april.day()); + CHECK_EQUAL(31, (unsigned)year_month_day_last_2004_may.day()); + CHECK_EQUAL(30, (unsigned)year_month_day_last_2005_june.day()); + CHECK_EQUAL(31, (unsigned)year_month_day_last_2006_july.day()); + CHECK_EQUAL(31, (unsigned)year_month_day_last_2007_august.day()); + CHECK_EQUAL(30, (unsigned)year_month_day_last_2008_september.day()); + CHECK_EQUAL(31, (unsigned)year_month_day_last_2009_october.day()); + CHECK_EQUAL(30, (unsigned)year_month_day_last_2010_november.day()); + CHECK_EQUAL(31, (unsigned)year_month_day_last_2011_december.day()); } //************************************************************************* From 2b141e0f22cc35092d8dea5a7047846513741d47 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 30 Apr 2025 12:07:15 +0100 Subject: [PATCH 26/33] Fixed tests to be compatible with std::chrono --- include/etl/private/chrono/duration.h | 56 +++++++++++++-------- include/etl/private/chrono/month.h | 10 +--- include/etl/private/chrono/year_month_day.h | 33 ++++++++++-- test/test_chrono_duration.cpp | 46 ++++++++++++----- test/test_chrono_month_day_last.cpp | 13 ----- test/test_chrono_operators.cpp | 5 -- test/test_chrono_weekday_last.cpp | 2 + 7 files changed, 100 insertions(+), 65 deletions(-) diff --git a/include/etl/private/chrono/duration.h b/include/etl/private/chrono/duration.h index 409a2486..5494c8e5 100644 --- a/include/etl/private/chrono/duration.h +++ b/include/etl/private/chrono/duration.h @@ -412,7 +412,8 @@ namespace etl /// Check equality. //*********************************************************************** template - ETL_CONSTEXPR14 bool operator ==(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + ETL_CONSTEXPR14 bool operator ==(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) { typedef typename etl::common_type, etl::chrono::duration >::type common_t; @@ -426,7 +427,8 @@ namespace etl /// Check inequality. //*********************************************************************** template - ETL_CONSTEXPR14 bool operator !=(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + ETL_CONSTEXPR14 bool operator !=(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) { return !(lhs == rhs); } @@ -435,7 +437,8 @@ namespace etl /// Less-than. //*********************************************************************** template - ETL_CONSTEXPR14 bool operator <(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + ETL_CONSTEXPR14 bool operator <(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) { typedef typename etl::common_type, etl::chrono::duration >::type common_t; @@ -449,7 +452,8 @@ namespace etl /// Less-than-or-equal. //*********************************************************************** template - ETL_CONSTEXPR14 bool operator <=(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + ETL_CONSTEXPR14 bool operator <=(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) { return !(rhs < lhs); } @@ -458,7 +462,8 @@ namespace etl /// Greater-than. //*********************************************************************** template - ETL_CONSTEXPR14 bool operator >(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + ETL_CONSTEXPR14 bool operator >(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) { return rhs < lhs; } @@ -467,7 +472,8 @@ namespace etl /// Greater-than-or-equal. //*********************************************************************** template - ETL_CONSTEXPR14 bool operator >=(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + ETL_CONSTEXPR14 bool operator >=(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) { return !(lhs < rhs); } @@ -477,7 +483,8 @@ namespace etl //*********************************************************************** #if ETL_USING_CPP20 template - [[nodiscard]] constexpr auto operator <=>(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) noexcept + [[nodiscard]] constexpr auto operator <=>(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) noexcept { typedef typename etl::common_type, etl::chrono::duration >::type common_t; @@ -493,7 +500,8 @@ namespace etl //*********************************************************************** template ETL_CONSTEXPR14 typename etl::common_type, etl::chrono::duration >::type - operator +(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + operator +(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) { // Determine the common type of the two durations. using common_duration = typename etl::common_type, etl::chrono::duration>::type; @@ -511,7 +519,8 @@ namespace etl //*********************************************************************** template ETL_CONSTEXPR14 typename etl::common_type, etl::chrono::duration >::type - operator -(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + operator -(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) { // Determine the common type of the two durations. using common_duration = typename etl::common_type, etl::chrono::duration>::type; @@ -529,7 +538,8 @@ namespace etl //*********************************************************************** template ETL_CONSTEXPR14 etl::chrono::duration::type, TPeriod1> - operator *(const etl::chrono::duration& lhs, const TRep2& rhs) + operator *(const etl::chrono::duration& lhs, + const TRep2& rhs) { using common_rep = typename etl::common_type::type; using result_duration = etl::chrono::duration; @@ -543,7 +553,8 @@ namespace etl //*********************************************************************** template ETL_CONSTEXPR14 etl::chrono::duration::type, TPeriod2> - operator *(const TRep1& lhs, const etl::chrono::duration& rhs) + operator *(const TRep1& lhs, + const etl::chrono::duration& rhs) { using common_rep = typename etl::common_type::type; using result_duration = etl::chrono::duration; @@ -557,7 +568,8 @@ namespace etl //*********************************************************************** template ETL_CONSTEXPR14 etl::chrono::duration::type, TPeriod1> - operator /(const etl::chrono::duration& lhs, const TRep2& rhs) + operator /(const etl::chrono::duration& lhs, + const TRep2& rhs) { using common_rep = typename etl::common_type::type; using result_duration = etl::chrono::duration; @@ -571,7 +583,8 @@ namespace etl //*********************************************************************** template ETL_CONSTEXPR14 typename etl::common_type::type - operator /(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + operator /(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) { // Determine the common type of the two durations. using common_duration = typename etl::common_type, etl::chrono::duration>::type; @@ -586,22 +599,23 @@ namespace etl /// Operator % //*********************************************************************** template - ETL_CONSTEXPR14 etl::chrono::duration::type, TPeriod1> - operator %(const etl::chrono::duration& lhs, const TRep2& rhs) + ETL_CONSTEXPR14 typename etl::common_type::type + operator %(const etl::chrono::duration& lhs, + const TRep2& rhs) { - using common_rep = typename etl::common_type::type; - using result_duration = etl::chrono::duration; + using common_rep = typename etl::common_type::type; // Mod the count of the duration by the scalar value - return result_duration(static_cast(lhs.count()) % static_cast(rhs)); + return common_rep(static_cast(lhs.count()) % static_cast(rhs)); } //*********************************************************************** /// Operator % //*********************************************************************** template - ETL_CONSTEXPR14 typename etl::common_type::type - operator %(const etl::chrono::duration& lhs, const etl::chrono::duration& rhs) + ETL_CONSTEXPR14 typename etl::common_type, etl::chrono::duration>::type + operator %(const etl::chrono::duration& lhs, + const etl::chrono::duration& rhs) { // Determine the common type of the two durations. using common_duration = typename etl::common_type, etl::chrono::duration>::type; @@ -609,7 +623,7 @@ namespace etl common_duration lhs_converted = etl::chrono::duration_cast(lhs); common_duration rhs_converted = etl::chrono::duration_cast(rhs); - return typename etl::common_type::type(lhs_converted.count() % rhs_converted.count()); + return common_duration(lhs_converted.count() % rhs_converted.count()); } } diff --git a/include/etl/private/chrono/month.h b/include/etl/private/chrono/month.h index 5b1e3678..53849593 100644 --- a/include/etl/private/chrono/month.h +++ b/include/etl/private/chrono/month.h @@ -44,7 +44,7 @@ namespace etl namespace private_chrono { - static ETL_CONSTANT unsigned char days_in_month[13] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + static ETL_CONSTANT unsigned char days_in_month[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; } //*********************************************************************** @@ -385,14 +385,6 @@ namespace etl return m; } - //************************************************************************* - /// Returns the last day of the month - //************************************************************************* - ETL_CONSTEXPR etl::chrono::day day() const ETL_NOEXCEPT - { - return etl::chrono::day(private_chrono::days_in_month[static_cast(m)]); - } - //************************************************************************* /// Is the contained month OK? //************************************************************************* diff --git a/include/etl/private/chrono/year_month_day.h b/include/etl/private/chrono/year_month_day.h index 0cae2211..7b60c907 100644 --- a/include/etl/private/chrono/year_month_day.h +++ b/include/etl/private/chrono/year_month_day.h @@ -94,11 +94,13 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 bool ok() const ETL_NOEXCEPT { + private_chrono::days_in_month[m]; + // Check if the year, month, and day are valid individually return y.ok() && m.ok() && d.ok() && - d <= etl::chrono::month_day_last(m).day(); + d <= max_day_for_month(); } //************************************************************************* @@ -254,6 +256,27 @@ namespace etl private: + //*********************************************************************** + /// Calculates the last day in the year/month. + /// Returns 0 if either the year or month are not OK. + //*********************************************************************** + etl::chrono::day max_day_for_month() const + { + unsigned char count = 0; + + if (y.ok() && m.ok()) + { + count = private_chrono::days_in_month[m]; + + if (y.is_leap() && (m == February)) + { + ++count; + } + } + + return etl::chrono::day(count); + } + etl::chrono::year y; etl::chrono::month m; etl::chrono::day d; @@ -297,7 +320,9 @@ namespace etl //************************************************************************* ETL_CONSTEXPR etl::chrono::day day() const ETL_NOEXCEPT { - return etl::chrono::month_day_last(m).day(); + etl::chrono::day d = etl::chrono::day(etl::chrono::private_chrono::days_in_month[m]); + + return (d == 28) && y.is_leap() ? etl::chrono::day(29) : d; } //************************************************************************* @@ -313,9 +338,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 bool ok() const ETL_NOEXCEPT { - return y.ok() && - m.ok() && - day() == etl::chrono::month_day_last(m).day(); + return y.ok() && m.ok(); } //************************************************************************* diff --git a/test/test_chrono_duration.cpp b/test/test_chrono_duration.cpp index 90bca535..6b8f3043 100644 --- a/test/test_chrono_duration.cpp +++ b/test/test_chrono_duration.cpp @@ -57,6 +57,7 @@ namespace { SUITE(test_chrono_duration) { +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_default_constructor) { @@ -68,6 +69,7 @@ namespace CHECK_TRUE((etl::is_same::value)); CHECK_EQUAL(0, duration.count()); } +#endif //************************************************************************* TEST(test_duration_values_zero_min_max) @@ -79,6 +81,7 @@ namespace CHECK_EQUAL(std::numeric_limits::max(), duration_values_type::max()); } +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_duration_zero_min_max) { @@ -88,6 +91,7 @@ namespace CHECK_EQUAL(duration_type(std::numeric_limits::min()).count(), duration_type::min().count()); CHECK_EQUAL(duration_type(std::numeric_limits::max()).count(), duration_type::max().count()); } +#endif //************************************************************************* TEST(test_predefined_duration_periods) @@ -126,18 +130,21 @@ namespace CHECK_EQUAL(etl::ratio<31556952U>::type::den, Chrono::years::period::den); } +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_duration_common_type) { using duration_type1 = Chrono::duration; using duration_type2 = Chrono::duration; - using duration_type = etl::common_type::type; + using duration_type = etl::common_type_t; - CHECK_TRUE((std::is_same::value)); + CHECK_TRUE((std::is_same::value)); CHECK_TRUE((std::is_same::value)); } +#endif +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_duration_cast_with_same_rep_and_period_for_duration_type1_and_duration_type2) { @@ -151,7 +158,9 @@ namespace CHECK_EQUAL(duration_type1::period::den, duration_type2::period::den); CHECK_EQUAL(dur1.count(), dur2.count()); } +#endif +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_duration_cast_where_ratio_divide_of_periods_num_is_1) { @@ -168,7 +177,9 @@ namespace CHECK_EQUAL(1, ratio_divide_t::num); CHECK_EQUAL(dur1.count(), dur2.count() * microseonds_per_millisecond); } +#endif +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_duration_cast_where_ratio_divide_of_periods_den_is_1) { @@ -185,7 +196,9 @@ namespace CHECK_EQUAL(1, ratio_divide_t::den); CHECK_EQUAL(dur1.count() * microseonds_per_millisecond, dur2.count()); } +#endif +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_duration_cast_when_rep_and_period_are_not_equal_and_ratio_divide_of_periods_num_and_den_are_not_1) { @@ -202,6 +215,7 @@ namespace CHECK_FALSE(1 == ratio_divide_t::den); CHECK_EQUAL(dur1.count(), (dur2.count() * duration_type2::period::num) / duration_type1::period::num); } +#endif //************************************************************************* TEST(test_duration_assignment) @@ -223,6 +237,7 @@ namespace CHECK_EQUAL(Four_Hours, hours2.count()); } +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_duration_comparison_operators) { @@ -276,7 +291,9 @@ namespace CHECK_FALSE(dur1a >= dur2c); CHECK_TRUE(dur2c >= dur1a); } +#endif +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_duration_unary_operators) { @@ -290,7 +307,9 @@ namespace CHECK_EQUAL(245, positive.count()); CHECK_EQUAL(-245, negative.count()); } +#endif +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_duration_hashes_are_unique) { @@ -307,6 +326,7 @@ namespace (void)std::unique(hashes.begin(), hashes.end()); CHECK_EQUAL(256U, hashes.size()); } +#endif //************************************************************************* TEST(test_duration_pre_increment) @@ -779,7 +799,7 @@ namespace auto result = s1 % scalar; - CHECK_EQUAL(1, result.count()); // 10 % 3 = 1 second + CHECK_EQUAL(1, result); // 10 % 3 = 1 second } //************************************************************************* @@ -790,7 +810,7 @@ namespace auto result = s1 % scalar; - CHECK_EQUAL(1, result.count()); // 10 % -3 = 1 second (modulus result is positive) + CHECK_EQUAL(1, result); // 10 % -3 = 1 second (modulus result is positive) } //************************************************************************* @@ -801,7 +821,7 @@ namespace auto result = s1 % scalar; - CHECK_EQUAL(10, result.count()); // 10 % 100 = 10 seconds + CHECK_EQUAL(10, result); // 10 % 100 = 10 seconds } //************************************************************************* @@ -812,7 +832,7 @@ namespace auto result = ms1 % scalar; - CHECK_EQUAL(50, result.count()); // 1050 % 500 = 50 milliseconds + CHECK_EQUAL(50, result); // 1050 % 500 = 50 milliseconds } //************************************************************************* @@ -823,7 +843,7 @@ namespace auto result = s1 % s2; - CHECK_EQUAL(1, result); // 10 % 3 = 1 second + CHECK_EQUAL(1, result.count()); // 10 % 3 = 1 second } //************************************************************************* @@ -835,7 +855,7 @@ namespace auto result = s1 % ms1; // Result should be in the common type (milliseconds) - CHECK_EQUAL(1000, result); // 10 seconds % 3000 milliseconds = 1000 milliseconds + CHECK_EQUAL(1000, result.count()); // 10 seconds % 3000 milliseconds = 1000 milliseconds } //************************************************************************* @@ -846,7 +866,7 @@ namespace auto result = s1 % ms1; - CHECK_EQUAL(0, result); // 1,000,000 seconds % 500,000 milliseconds = 0 + CHECK_EQUAL(0, result.count()); // 1,000,000 seconds % 500,000 milliseconds = 0 } //************************************************************************* @@ -857,7 +877,7 @@ namespace auto result = s1 % s2; - CHECK_EQUAL(1, result); // 7 % 3 = 1 second + CHECK_EQUAL(1, result.count()); // 7 % 3 = 1 second } //************************************************************************* @@ -868,7 +888,7 @@ namespace auto result = s1 % s2; - CHECK_EQUAL(5, result); // 5 % 10 = 5 seconds + CHECK_EQUAL(5, result.count()); // 5 % 10 = 5 seconds } //************************************************************************* @@ -880,7 +900,7 @@ namespace auto result = s1 % ms1; // Result should be in the common type (milliseconds) - CHECK_EQUAL(0, result); // 10 seconds % 2500 milliseconds = 0 milliseconds + CHECK_EQUAL(0, result.count()); // 10 seconds % 2500 milliseconds = 0 milliseconds } //************************************************************************* @@ -1028,6 +1048,7 @@ namespace } #endif +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_duration_compare) { @@ -1038,5 +1059,6 @@ namespace CHECK_EQUAL(-1, ms1.compare(s1)); CHECK_EQUAL(1, s1.compare(ms1)); } +#endif }; } diff --git a/test/test_chrono_month_day_last.cpp b/test/test_chrono_month_day_last.cpp index f47792c7..ec9b6ae4 100644 --- a/test/test_chrono_month_day_last.cpp +++ b/test/test_chrono_month_day_last.cpp @@ -84,19 +84,6 @@ namespace CHECK_TRUE(month_day_last_october.ok()); CHECK_TRUE(month_day_last_november.ok()); CHECK_TRUE(month_day_last_december.ok()); - - CHECK_EQUAL(31, month_day_last_january.day()); - CHECK_EQUAL(29, month_day_last_february.day()); - CHECK_EQUAL(31, month_day_last_march.day()); - CHECK_EQUAL(30, month_day_last_april.day()); - CHECK_EQUAL(31, month_day_last_may.day()); - CHECK_EQUAL(30, month_day_last_june.day()); - CHECK_EQUAL(31, month_day_last_july.day()); - CHECK_EQUAL(31, month_day_last_august.day()); - CHECK_EQUAL(30, month_day_last_september.day()); - CHECK_EQUAL(31, month_day_last_october.day()); - CHECK_EQUAL(30, month_day_last_november.day()); - CHECK_EQUAL(31, month_day_last_december.day()); } //************************************************************************* diff --git a/test/test_chrono_operators.cpp b/test/test_chrono_operators.cpp index f9f55b78..717d653e 100644 --- a/test/test_chrono_operators.cpp +++ b/test/test_chrono_operators.cpp @@ -193,27 +193,22 @@ namespace CHECK_EQUAL(etl::chrono::year(2000), ymdl1.year()); CHECK_EQUAL(etl::chrono::January, ymdl1.month()); - CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::January).day(), ymdl1.day()); CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::January).month(), ymdl1.month_day_last().month()); CHECK_EQUAL(etl::chrono::year(2001), ymdl2.year()); CHECK_EQUAL(etl::chrono::February, ymdl2.month()); - CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::February).day(), ymdl2.day()); CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::February).month(), ymdl2.month_day_last().month()); CHECK_EQUAL(etl::chrono::year(2002), ymdl3.year()); CHECK_EQUAL(etl::chrono::March, ymdl3.month()); - CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::March).day(), ymdl3.day()); CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::March).month(), ymdl3.month_day_last().month()); CHECK_EQUAL(etl::chrono::year(2003), ymdl4.year()); CHECK_EQUAL(etl::chrono::April, ymdl4.month()); - CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::April).day(), ymdl4.day()); CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::April).month(), ymdl4.month_day_last().month()); CHECK_EQUAL(etl::chrono::year(2004), ymdl5.year()); CHECK_EQUAL(etl::chrono::May, ymdl5.month()); - CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::May).day(), ymdl5.day()); CHECK_EQUAL(etl::chrono::month_day_last(etl::chrono::May).month(), ymdl5.month_day_last().month()); } diff --git a/test/test_chrono_weekday_last.cpp b/test/test_chrono_weekday_last.cpp index a3a2a078..4db7e658 100644 --- a/test/test_chrono_weekday_last.cpp +++ b/test/test_chrono_weekday_last.cpp @@ -110,6 +110,7 @@ namespace CHECK_FALSE(weekday_last1 == weekday_last3); } +#if ETL_USING_ETL_CHRONO //************************************************************************* TEST(test_weekday_last_hashes_are_unique) { @@ -129,5 +130,6 @@ namespace std::sort(hashes.begin(), hashes.end()); (void)std::unique(hashes.begin(), hashes.end()); } +#endif }; } From a1ec6136301aca8f7f2a2fad57bd207c7222afdc Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 30 Apr 2025 12:11:23 +0100 Subject: [PATCH 27/33] Fixed parameter shadowing warnings --- include/etl/private/chrono/year_month_day.h | 22 +++++++++---------- .../etl/private/chrono/year_month_weekday.h | 12 +++++----- 2 files changed, 16 insertions(+), 18 deletions(-) diff --git a/include/etl/private/chrono/year_month_day.h b/include/etl/private/chrono/year_month_day.h index 7b60c907..53a14619 100644 --- a/include/etl/private/chrono/year_month_day.h +++ b/include/etl/private/chrono/year_month_day.h @@ -94,8 +94,6 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 bool ok() const ETL_NOEXCEPT { - private_chrono::days_in_month[m]; - // Check if the year, month, and day are valid individually return y.ok() && m.ok() && @@ -292,10 +290,10 @@ namespace etl //************************************************************************* /// //************************************************************************* - ETL_CONSTEXPR year_month_day_last(const etl::chrono::year& y, - const etl::chrono::month_day_last& mdl) ETL_NOEXCEPT - : y(y) - , m(mdl.month()) + ETL_CONSTEXPR year_month_day_last(const etl::chrono::year& y_, + const etl::chrono::month_day_last& mdl_) ETL_NOEXCEPT + : y(y_) + , m(mdl_.month()) { } @@ -460,19 +458,19 @@ namespace etl [[nodiscard]] friend constexpr auto operator <=>(const etl::chrono::year_month_day_last& lhs, const etl::chrono::year_month_day_last& rhs) ETL_NOEXCEPT { - auto cmp = lhs.year() <=> rhs.year(); + auto cmp1 = lhs.year() <=> rhs.year(); - if (cmp != 0) + if (cmp1 != 0) { - return cmp; + return cmp1; } else { - auto cmp = lhs.month() <=> rhs.month(); + auto cmp2 = lhs.month() <=> rhs.month(); - if (cmp != 0) + if (cmp2 != 0) { - return cmp; + return cmp2; } else { diff --git a/include/etl/private/chrono/year_month_weekday.h b/include/etl/private/chrono/year_month_weekday.h index 03242c6e..b12be805 100644 --- a/include/etl/private/chrono/year_month_weekday.h +++ b/include/etl/private/chrono/year_month_weekday.h @@ -403,19 +403,19 @@ namespace etl [[nodiscard]] friend constexpr auto operator <=>(const etl::chrono::year_month_weekday_last& lhs, const etl::chrono::year_month_weekday_last& rhs) ETL_NOEXCEPT { - auto cmp = lhs.year() <=> rhs.year(); + auto cmp1 = lhs.year() <=> rhs.year(); - if (cmp != 0) + if (cmp1 != 0) { - return cmp; + return cmp1; } else { - auto cmp = lhs.month() <=> rhs.month(); + auto cmp2 = lhs.month() <=> rhs.month(); - if (cmp != 0) + if (cmp2 != 0) { - return cmp; + return cmp2; } else { From 12328670ddd851d6bc9c0b89492157971e9d2e20 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sun, 11 May 2025 14:11:22 +0100 Subject: [PATCH 28/33] Work in progress --- include/etl/chrono.h | 9 +- .../etl/generators/type_traits_generator.h | 15 + include/etl/platform.h | 10 +- include/etl/private/chrono/clocks.h | 187 +++++++++ include/etl/private/chrono/day.h | 48 +-- include/etl/private/chrono/duration.h | 178 ++++++--- include/etl/private/chrono/hh_mm_ss.h | 54 ++- include/etl/private/chrono/last_spec.h | 6 +- include/etl/private/chrono/month.h | 56 +-- include/etl/private/chrono/month_day.h | 24 +- include/etl/private/chrono/month_weekday.h | 32 +- include/etl/private/chrono/system_clock.h | 51 --- include/etl/private/chrono/time_point.h | 105 +++-- include/etl/private/chrono/weekday.h | 76 ++-- include/etl/private/chrono/year.h | 50 +-- include/etl/private/chrono/year_month.h | 12 +- include/etl/private/chrono/year_month_day.h | 77 ++-- .../etl/private/chrono/year_month_weekday.h | 46 +-- include/etl/type_traits.h | 18 +- test/CMakeLists.txt | 31 +- test/etl_profile.h | 6 + test/test_chrono_clocks.cpp | 170 ++++++++ test/test_chrono_duration.cpp | 82 +++- test/test_chrono_time_point.cpp | 362 ++++++++++++++++++ test/test_chrono_year_month_day.cpp | 9 + test/test_ratio.cpp | 12 +- test/test_type_traits.cpp | 23 ++ test/vs2022/etl.vcxproj | 4 +- test/vs2022/etl.vcxproj.filters | 12 +- 29 files changed, 1354 insertions(+), 411 deletions(-) create mode 100644 include/etl/private/chrono/clocks.h delete mode 100644 include/etl/private/chrono/system_clock.h create mode 100644 test/test_chrono_clocks.cpp create mode 100644 test/test_chrono_time_point.cpp diff --git a/include/etl/chrono.h b/include/etl/chrono.h index fbc0b47d..62bbac18 100644 --- a/include/etl/chrono.h +++ b/include/etl/chrono.h @@ -44,6 +44,7 @@ SOFTWARE. #include "hash.h" #include +#include namespace etl { @@ -59,12 +60,15 @@ namespace etl constexpr bool treat_as_floating_point_v = treat_as_floating_point::value; #endif } + + // Use the same type as defined in time.h. + using time_t = ::time_t; } -#include "private/chrono/time_point.h" #include "private/chrono/last_spec.h" #include "private/chrono/duration.h" -#include "private/chrono/system_clock.h" +#include "private/chrono/time_point.h" +#include "private/chrono/clocks.h" #include "private/chrono/day.h" #include "private/chrono/weekday.h" #include "private/chrono/month.h" @@ -77,6 +81,7 @@ namespace etl #include "private/chrono/hh_mm_ss.h" #include "private/chrono/operators.h" #include "private/chrono/time_zone.h" + #endif #undef ETL_IN_CHRONO_H diff --git a/include/etl/generators/type_traits_generator.h b/include/etl/generators/type_traits_generator.h index ac421eb9..fd1fb891 100644 --- a/include/etl/generators/type_traits_generator.h +++ b/include/etl/generators/type_traits_generator.h @@ -2394,6 +2394,21 @@ typedef integral_constant true_type; template inline constexpr size_t count_of_v = etl::count_of::value; #endif + +#if ETL_USING_CPP11 + //********************************************* + /// is_specialization + template class Template> + struct is_specialization : etl::false_type {}; + + template