From d4373773107eba5885fbc1578d39bb75bf6b2735 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 24 May 2021 11:53:09 +0100 Subject: [PATCH 01/20] Updated QueuedMessageRouter example. --- examples/QueuedMessageRouter/QueuedMessageRouter.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/examples/QueuedMessageRouter/QueuedMessageRouter.cpp b/examples/QueuedMessageRouter/QueuedMessageRouter.cpp index a392db95..cee5dd79 100644 --- a/examples/QueuedMessageRouter/QueuedMessageRouter.cpp +++ b/examples/QueuedMessageRouter/QueuedMessageRouter.cpp @@ -92,32 +92,32 @@ public: // Call the base class's receive function. // This will route it to the correct on_receive handler. - Base_t::receive(sender, msg); + Base_t::receive(msg); queue.pop(); } } //*************************************************************************** - void on_receive(etl::imessage_router& sender, const Message1& msg) + void on_receive(const Message1& msg) { std::cout << " Received message " << int(msg.get_message_id()) << " : '" << msg.i << "'" << std::endl; } //*************************************************************************** - void on_receive(etl::imessage_router& sender, const Message2& msg) + void on_receive(const Message2& msg) { std::cout << " Received message " << int(msg.get_message_id()) << " : '" << msg.d << "'" << std::endl; } //*************************************************************************** - void on_receive(etl::imessage_router& sender, const Message3& msg) + void on_receive(const Message3& msg) { std::cout << " Received message " << int(msg.get_message_id()) << " : '" << msg.s << "'" << std::endl; } //*************************************************************************** - void on_receive_unknown(etl::imessage_router& sender, const etl::imessage& msg) + void on_receive_unknown(const etl::imessage& msg) { std::cout << " Received unknown message " << int(msg.get_message_id()) << std::endl; } From 71e83c1b5e60a8d257d49c2e340705907e2eff25 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 24 May 2021 19:30:14 +0100 Subject: [PATCH 02/20] Updated QueuedMessageRouter example. --- .../QueuedMessageRouter.cpp | 26 ++++--------------- 1 file changed, 5 insertions(+), 21 deletions(-) diff --git a/examples/QueuedMessageRouter/QueuedMessageRouter.cpp b/examples/QueuedMessageRouter/QueuedMessageRouter.cpp index cee5dd79..d4f78f77 100644 --- a/examples/QueuedMessageRouter/QueuedMessageRouter.cpp +++ b/examples/QueuedMessageRouter/QueuedMessageRouter.cpp @@ -62,15 +62,12 @@ public: //*************************************************************************** // Override the base class's receive function. - void receive(etl::imessage_router& sender_, const etl::imessage& msg_) + void receive(const etl::imessage& msg_) { if (accepts(msg_)) { // Place in queue. - - Item item(&sender_, msg_); - - queue.emplace(&sender_, msg_); + queue.emplace(msg_); std::cout << "Queueing message " << int(msg_.get_message_id()) << std::endl; } @@ -85,9 +82,8 @@ public: { while (!queue.empty()) { - Item& item = queue.front(); - etl::imessage& msg = item.packet.get(); - etl::imessage_router& sender = *item.sender; + message_packet& packet = queue.front(); + etl::imessage& msg = packet.get(); std::cout << "Processing message " << int(msg.get_message_id()) << std::endl; // Call the base class's receive function. @@ -124,19 +120,7 @@ public: private: - struct Item - { - Item(etl::imessage_router* sender_, const etl::imessage& msg_) - : sender(sender_), - packet(msg_) - { - } - - etl::imessage_router* sender; - message_packet packet; - }; - - etl::queue queue; + etl::queue queue; }; //***************************************************************************** From 830d0d00f192116ce519a8388f55da491b348f19 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 24 May 2021 20:08:56 +0100 Subject: [PATCH 03/20] Updated QueuedMessageRouter and QueuedFSM examples to use current message frameworks. --- examples/QueuedFSM/QueuedFSM.cpp | 66 ++++++++----------- .../{vs2017 => vs2019}/QueuedFSM.sln | 0 .../{vs2017 => vs2019}/QueuedFSM.vcxproj | 10 +-- .../QueuedFSM.vcxproj.filters | 0 include/etl/version.h | 2 +- library.json | 2 +- library.properties | 2 +- meson.build | 2 +- support/Release notes.txt | 4 ++ 9 files changed, 39 insertions(+), 49 deletions(-) rename examples/QueuedFSM/{vs2017 => vs2019}/QueuedFSM.sln (100%) rename examples/QueuedFSM/{vs2017 => vs2019}/QueuedFSM.vcxproj (96%) rename examples/QueuedFSM/{vs2017 => vs2019}/QueuedFSM.vcxproj.filters (100%) diff --git a/examples/QueuedFSM/QueuedFSM.cpp b/examples/QueuedFSM/QueuedFSM.cpp index 9d99142e..a0cbd029 100644 --- a/examples/QueuedFSM/QueuedFSM.cpp +++ b/examples/QueuedFSM/QueuedFSM.cpp @@ -99,18 +99,18 @@ public: //*************************************************************************** // The overridden virtual receive function. //*************************************************************************** - void receive(etl::imessage_router& sender_, const etl::imessage& msg_) override + void receive(const etl::imessage& msg_) override { if (accepts(msg_)) { // Place in queue. - queue.emplace(&sender_, msg_); + queue.emplace(msg_); - std::cout << "Queueing message " << int(msg_.message_id) << std::endl; + std::cout << "Queueing message " << int(msg_.get_message_id()) << std::endl; } else { - std::cout << "Ignoring message " << int(msg_.message_id) << std::endl; + std::cout << "Ignoring message " << int(msg_.get_message_id()) << std::endl; } } @@ -121,14 +121,13 @@ public: { while (!queue.empty()) { - Item& item = queue.front(); - etl::imessage& msg = item.packet.get(); - etl::imessage_router& sender = *item.sender; - std::cout << "Processing message " << int(msg.message_id) << std::endl; + message_packet& packet = queue.front(); + etl::imessage& msg = packet.get(); + std::cout << "Processing message " << int(msg.get_message_id()) << std::endl; // Call the base class's receive function. // This will route it to the correct 'on_event' handler. - etl::fsm::receive(sender, msg); + etl::fsm::receive(msg); queue.pop(); } @@ -136,23 +135,10 @@ public: private: - //*************************************************************************** - // The item to queue. - //*************************************************************************** - struct Item - { - Item(etl::imessage_router* sender_, const etl::imessage& msg_) - : sender(sender_), - packet(msg_) - { - } - - etl::imessage_router* sender; - etl::message_packet< Message1, Message2, Message3, Message4> packet; // Defines a packet suitable for all possible messages. - }; + typedef etl::message_packet< Message1, Message2, Message3, Message4> message_packet; // The queue of message items. - etl::queue queue; + etl::queue queue; }; //***************************************************************************** @@ -178,33 +164,33 @@ public: } //*************************************************************************** - etl::fsm_state_id_t on_event(etl::imessage_router& sender, const Message1& msg) + etl::fsm_state_id_t on_event(const Message1& msg) { - std::cout << " S1 : Received message " << int(msg.message_id) << " : '" << msg.i << "'" << std::endl; + std::cout << " S1 : Received message " << int(msg.get_message_id()) << " : '" << msg.i << "'" << std::endl; std::cout.flush(); return STATE1; } //*************************************************************************** - etl::fsm_state_id_t on_event(etl::imessage_router& sender, const Message2& msg) + etl::fsm_state_id_t on_event(const Message2& msg) { - std::cout << " S1 : Received message " << int(msg.message_id) << " : '" << msg.d << "'" << std::endl; + std::cout << " S1 : Received message " << int(msg.get_message_id()) << " : '" << msg.d << "'" << std::endl; std::cout.flush(); return STATE1; } //*************************************************************************** - etl::fsm_state_id_t on_event(etl::imessage_router& sender, const Message3& msg) + etl::fsm_state_id_t on_event(const Message3& msg) { - std::cout << " S1 : Received message " << int(msg.message_id) << " : '" << msg.s << "'" << std::endl; + std::cout << " S1 : Received message " << int(msg.get_message_id()) << " : '" << msg.s << "'" << std::endl; std::cout.flush(); return STATE1; } //*************************************************************************** - etl::fsm_state_id_t on_event_unknown(etl::imessage_router& sender, const etl::imessage& msg) + etl::fsm_state_id_t on_event_unknown(const etl::imessage& msg) { - std::cout << " S1 : Received unknown message " << int(msg.message_id) << std::endl; + std::cout << " S1 : Received unknown message " << int(msg.get_message_id()) << std::endl; std::cout.flush(); return STATE2; } @@ -233,30 +219,30 @@ public: } //*************************************************************************** - etl::fsm_state_id_t on_event(etl::imessage_router& sender, const Message1& msg) + etl::fsm_state_id_t on_event(const Message1& msg) { - std::cout << " S2 : Received message " << int(msg.message_id) << " : '" << msg.i << "'" << std::endl; + std::cout << " S2 : Received message " << int(msg.get_message_id()) << " : '" << msg.i << "'" << std::endl; return STATE2; } //*************************************************************************** - etl::fsm_state_id_t on_event(etl::imessage_router& sender, const Message2& msg) + etl::fsm_state_id_t on_event(const Message2& msg) { - std::cout << " S2 : Received message " << int(msg.message_id) << " : '" << msg.d << "'" << std::endl; + std::cout << " S2 : Received message " << int(msg.get_message_id()) << " : '" << msg.d << "'" << std::endl; return STATE2; } //*************************************************************************** - etl::fsm_state_id_t on_event(etl::imessage_router& sender, const Message3& msg) + etl::fsm_state_id_t on_event(const Message3& msg) { - std::cout << " S2 : Received message " << int(msg.message_id) << " : '" << msg.s << "'" << std::endl; + std::cout << " S2 : Received message " << int(msg.get_message_id()) << " : '" << msg.s << "'" << std::endl; return STATE2; } //*************************************************************************** - etl::fsm_state_id_t on_event_unknown(etl::imessage_router& sender, const etl::imessage& msg) + etl::fsm_state_id_t on_event_unknown(const etl::imessage& msg) { - std::cout << " S2 : Received unknown message " << int(msg.message_id) << std::endl; + std::cout << " S2 : Received unknown message " << int(msg.get_message_id()) << std::endl; return STATE1; } }; diff --git a/examples/QueuedFSM/vs2017/QueuedFSM.sln b/examples/QueuedFSM/vs2019/QueuedFSM.sln similarity index 100% rename from examples/QueuedFSM/vs2017/QueuedFSM.sln rename to examples/QueuedFSM/vs2019/QueuedFSM.sln diff --git a/examples/QueuedFSM/vs2017/QueuedFSM.vcxproj b/examples/QueuedFSM/vs2019/QueuedFSM.vcxproj similarity index 96% rename from examples/QueuedFSM/vs2017/QueuedFSM.vcxproj rename to examples/QueuedFSM/vs2019/QueuedFSM.vcxproj index 6e9c8762..5e461eab 100644 --- a/examples/QueuedFSM/vs2017/QueuedFSM.vcxproj +++ b/examples/QueuedFSM/vs2019/QueuedFSM.vcxproj @@ -23,32 +23,32 @@ {2BB47D48-5EFC-4C38-B2BE-002172F00E3B} Win32Proj QueuedFSM - 10.0.18362.0 + 10.0 Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode Application true - v141 + v142 Unicode Application false - v141 + v142 true Unicode diff --git a/examples/QueuedFSM/vs2017/QueuedFSM.vcxproj.filters b/examples/QueuedFSM/vs2019/QueuedFSM.vcxproj.filters similarity index 100% rename from examples/QueuedFSM/vs2017/QueuedFSM.vcxproj.filters rename to examples/QueuedFSM/vs2019/QueuedFSM.vcxproj.filters diff --git a/include/etl/version.h b/include/etl/version.h index cce3d1f9..720df68d 100644 --- a/include/etl/version.h +++ b/include/etl/version.h @@ -39,7 +39,7 @@ SOFTWARE. #define ETL_VERSION_MAJOR 20 #define ETL_VERSION_MINOR 10 -#define ETL_VERSION_PATCH 5 +#define ETL_VERSION_PATCH 6 #define ETL_VERSION ETL_STRINGIFY(ETL_VERSION_MAJOR) "." ETL_STRINGIFY(ETL_VERSION_MINOR) "." ETL_STRINGIFY(ETL_VERSION_PATCH) #define ETL_VERSION_W ETL_STRINGIFY(ETL_VERSION_MAJOR) L"." ETL_STRINGIFY(ETL_VERSION_MINOR) L"." ETL_STRINGIFY(ETL_VERSION_PATCH) #define ETL_VERSION_U16 ETL_STRINGIFY(ETL_VERSION_MAJOR) u"." ETL_STRINGIFY(ETL_VERSION_MINOR) u"." ETL_STRINGIFY(ETL_VERSION_PATCH) diff --git a/library.json b/library.json index b72d881c..9db55ab8 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "ETL Embedded Template Library", - "version": "20.10.5", + "version": "20.10.6", "author s": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/library.properties b/library.properties index 7fdf7a9e..a5459cd4 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library ETL -version=20.10.5 +version=20.10.6 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/meson.build b/meson.build index 77d55aa3..5b87b504 100644 --- a/meson.build +++ b/meson.build @@ -8,7 +8,7 @@ project('PROJECT_NAME', 'cpp_std=c++17', 'build.cpp_std=c++17', ], meson_version: '>=0.54.0', - version: '20.10.5' + version: '20.10.6' ) ###################### diff --git a/support/Release notes.txt b/support/Release notes.txt index 6f5ef35c..95dfd39d 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,7 @@ +=============================================================================== +20.10.6 +Updated QueuedMessageRouter and QueuedFSM examples to use current message frameworks. + =============================================================================== 20.10.5 Added container_type to etl::stack, etl::queue and etl::priority_queue. From e21d3edd6ad599fee8a640885e89dca5b50985c0 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 31 May 2021 15:55:13 +0100 Subject: [PATCH 04/20] Initial commit --- include/etl/file_error_numbers.h | 1 + include/etl/mem_cast.h | 343 +++++++++++++++++++++++++ test/CMakeLists.txt | 2 + test/sanity-check/c++03/CMakeLists.txt | 1 + test/sanity-check/c++11/CMakeLists.txt | 1 + test/sanity-check/c++14/CMakeLists.txt | 1 + test/sanity-check/c++17/CMakeLists.txt | 1 + test/sanity-check/mem_cast.h.t.cpp | 29 +++ test/test_mem_cast.cpp | 209 +++++++++++++++ test/test_mem_cast_ptr.cpp | 188 ++++++++++++++ test/vs2019/etl.vcxproj | 19 ++ test/vs2019/etl.vcxproj.filters | 12 + 12 files changed, 807 insertions(+) create mode 100644 include/etl/mem_cast.h create mode 100644 test/sanity-check/mem_cast.h.t.cpp create mode 100644 test/test_mem_cast.cpp create mode 100644 test/test_mem_cast_ptr.cpp diff --git a/include/etl/file_error_numbers.h b/include/etl/file_error_numbers.h index a72f34de..86a31fbb 100644 --- a/include/etl/file_error_numbers.h +++ b/include/etl/file_error_numbers.h @@ -92,5 +92,6 @@ SOFTWARE. #define ETL_QUEUE_SPSC_LOCKABLE_FILE_ID "59" #define ETL_MESSAGE_ROUTER_REGISTRY_FILE_ID "60" #define ETL_ARRAY_WRAPPER_FILE_ID "61" +#define ETL_MEM_CAST_FILE_ID "62" #endif diff --git a/include/etl/mem_cast.h b/include/etl/mem_cast.h new file mode 100644 index 00000000..b43b7af9 --- /dev/null +++ b/include/etl/mem_cast.h @@ -0,0 +1,343 @@ +///\file + +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2021 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#ifndef ETL_MEM_CAST_INCLUDED +#define ETL_MEM_CAST_INCLUDED + +#include +#include + +#include "platform.h" +#include "memory.h" +#include "static_assert.h" +#include "largest.h" +#include "utility.h" +#include "placement_new.h" +#include "exception.h" +#include "error_handler.h" +#include "file_error_numbers.h" + +namespace etl +{ + //*************************************************************************** + /// The base class for array_wrapper exceptions. + //*************************************************************************** + class mem_cast_exception : public etl::exception + { + public: + + mem_cast_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + : exception(reason_, file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// The exception thrown when the buffer pointer alignment is not compatible. + //*************************************************************************** + class mem_cast_alignment_exception : public etl::mem_cast_exception + { + public: + + mem_cast_alignment_exception(string_type file_name_, numeric_type line_number_) + : mem_cast_exception(ETL_ERROR_TEXT("mem_cast:alignment", ETL_MEM_CAST_FILE_ID"A"), file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// The exception thrown when the pointer is null. + //*************************************************************************** + class mem_cast_nullptr_exception : public etl::mem_cast_exception + { + public: + + mem_cast_nullptr_exception(string_type file_name_, numeric_type line_number_) + : mem_cast_exception(ETL_ERROR_TEXT("mem_cast:null pointer", ETL_MEM_CAST_FILE_ID"B"), file_name_, line_number_) + { + } + }; + + //***************************************************************************** + /// mem_cast + //***************************************************************************** + template + class mem_cast + { + public: + + static ETL_CONSTANT size_t Size = Size_; + static ETL_CONSTANT size_t Alignment = Alignment_; + + //*********************************** + /// Default constructor + //*********************************** + mem_cast() + : buffer() + { + } + + //*********************************** + /// Copy constructor + //*********************************** + template + mem_cast(const mem_cast& other) + { + ETL_STATIC_ASSERT(Size >= Other_Size, "Other size is too large"); + ETL_STATIC_ASSERT(Alignment >= Other_Alignment, "Other alignment incompatible"); + + memcpy(buffer, other.buffer, Size_); + } + +#if ETL_CPP11_SUPPORTED + //*********************************** + /// Emplace from parameters + //*********************************** + template + void emplace(TArgs... args) + { + ::new (static_cast(buffer)) T(etl::forward(args)...); + } +#endif + + //*********************************** + /// Get a reference to T + //*********************************** + template + T& ref() + { + ETL_STATIC_ASSERT(sizeof(T) <= Size, "Size of T is too large"); + ETL_STATIC_ASSERT(Alignment >= etl::alignment_of::value, "Alignment of T is incompatible"); + + return *static_cast(buffer); + } + + //*********************************** + /// Get a const reference to T + //*********************************** + template + const T& ref() const + { + ETL_STATIC_ASSERT(sizeof(T) <= Size, "Size of T is too large"); + ETL_STATIC_ASSERT(Alignment >= etl::alignment_of::value, "Alignment of T is incompatible"); + + return *static_cast(buffer); + } + + //*********************************** + /// Assignment operator + //*********************************** + template + mem_cast& operator =(const mem_cast& rhs) + { + ETL_STATIC_ASSERT(Size >= Other_Size, "RHS size is too large"); + ETL_STATIC_ASSERT(Alignment >= Other_Alignment, "RHS alignment incompatible"); + + memcpy(buffer, rhs.buffer, Size_); + + return *this; + } + + //*********************************** + /// Get the size of the buffer + //*********************************** + ETL_CONSTEXPR size_t size() const + { + return Size; + } + + //*********************************** + /// Get the alignment of the buffer + //*********************************** + ETL_CONSTEXPR size_t alignment() const + { + return Alignment; + } + + //*********************************** + /// Get a pointer to the internal buffer + //*********************************** + char* data() + { + return buffer; + } + + //*********************************** + /// Get a const pointer to the internal buffer + //*********************************** + const char* data() const + { + return buffer; + } + + private: + + /// The internal buffer + etl::uninitialized_buffer buffer; + }; + + //***************************************************************************** + /// mem_cast_ptr + //***************************************************************************** + template + class mem_cast_ptr + { + public: + + static ETL_CONSTANT size_t Size = Size_; + + //*********************************** + /// Default constructor + //*********************************** + mem_cast_ptr() + : pbuffer(ETL_NULLPTR) + { + } + + //*********************************** + /// Construct with pointer to buffer + //*********************************** + mem_cast_ptr(char* pbuffer_) + : pbuffer(pbuffer_) + { + } + + //*********************************** + /// Copy construct with pointer to buffer + //*********************************** + template + mem_cast_ptr(const mem_cast_ptr& other, char* pbuffer_) + : pbuffer(pbuffer_) + { + ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); + ETL_STATIC_ASSERT(Size >= Other_Size, "Other size is too large"); + + memcpy(pbuffer, other.pbuffer, Size_); + } + +#if ETL_CPP11_SUPPORTED + //*********************************** + /// Emplace from parameters + //*********************************** + template + void emplace(TArgs... args) + { + ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); + ETL_ASSERT((uintptr_t(pbuffer) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + + ::new (pbuffer) T(etl::forward(args)...); + } +#endif + + //*********************************** + /// Get a reference to T + //*********************************** + template + T& ref() + { + ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); + ETL_ASSERT((uintptr_t(pbuffer) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + + return *reinterpret_cast(pbuffer); + } + + //*********************************** + /// Get a const reference to T + //*********************************** + template + const T& ref() const + { + ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); + ETL_ASSERT((uintptr_t(pbuffer) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + + return *reinterpret_cast(pbuffer); + } + + //*********************************** + template + mem_cast_ptr& operator =(const mem_cast_ptr& rhs) + { + ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); + ETL_STATIC_ASSERT(Size >= Other_Size, "RHS size is too large"); + + memcpy(pbuffer, rhs.pbuffer, Size_); + + return *this; + } + + //*********************************** + /// Assignment operator + //*********************************** + ETL_CONSTEXPR size_t size() const + { + return Size; + } + + //*********************************** + /// Set the pointer to the external buffer + //*********************************** + void data(char* pbuffer_) + { + pbuffer = pbuffer_; + } + + //*********************************** + /// Get a pointer to the external buffer + //*********************************** + char* data() + { + return pbuffer; + } + + //*********************************** + /// Get const a pointer to the external buffer + //*********************************** + const char* data() const + { + return pbuffer; + } + + private: + + /// Pointer to the buffer + char* pbuffer; + }; + +#if ETL_CPP11_SUPPORTED + //***************************************************************************** + /// mem_cast_var + /// mem_cast from a variadic list of types + //***************************************************************************** + template + using mem_cast_types = etl::mem_cast::size, etl::largest::alignment>; +#endif +} + +#endif diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index e91d9b3c..8664063e 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -145,6 +145,8 @@ set(TEST_SOURCE_FILES test_map.cpp test_maths.cpp test_mean.cpp + test_mem_cast.cpp + test_mem_cast_ptr.cpp test_memory.cpp test_message_bus.cpp test_message_packet.cpp diff --git a/test/sanity-check/c++03/CMakeLists.txt b/test/sanity-check/c++03/CMakeLists.txt index 9c029fda..dea14a49 100644 --- a/test/sanity-check/c++03/CMakeLists.txt +++ b/test/sanity-check/c++03/CMakeLists.txt @@ -151,6 +151,7 @@ target_sources(t98 PRIVATE etl_profile.h ../map.h.t.cpp ../math_constants.h.t.cpp ../mean.h.t.cpp + ../mem_cast.h.t.cpp ../memory.h.t.cpp ../memory_model.h.t.cpp ../message.h.t.cpp diff --git a/test/sanity-check/c++11/CMakeLists.txt b/test/sanity-check/c++11/CMakeLists.txt index c34ccaea..09193372 100644 --- a/test/sanity-check/c++11/CMakeLists.txt +++ b/test/sanity-check/c++11/CMakeLists.txt @@ -151,6 +151,7 @@ target_sources(t11 PRIVATE etl_profile.h ../map.h.t.cpp ../math_constants.h.t.cpp ../mean.h.t.cpp + ../mem_cast.h.t.cpp ../memory.h.t.cpp ../memory_model.h.t.cpp ../message.h.t.cpp diff --git a/test/sanity-check/c++14/CMakeLists.txt b/test/sanity-check/c++14/CMakeLists.txt index 02fc1823..e514d386 100644 --- a/test/sanity-check/c++14/CMakeLists.txt +++ b/test/sanity-check/c++14/CMakeLists.txt @@ -151,6 +151,7 @@ target_sources(t14 PRIVATE etl_profile.h ../map.h.t.cpp ../math_constants.h.t.cpp ../mean.h.t.cpp + ../mem_cast.h.t.cpp ../memory.h.t.cpp ../memory_model.h.t.cpp ../message.h.t.cpp diff --git a/test/sanity-check/c++17/CMakeLists.txt b/test/sanity-check/c++17/CMakeLists.txt index 91193e63..dd6b754a 100644 --- a/test/sanity-check/c++17/CMakeLists.txt +++ b/test/sanity-check/c++17/CMakeLists.txt @@ -151,6 +151,7 @@ target_sources(t17 PRIVATE etl_profile.h ../map.h.t.cpp ../math_constants.h.t.cpp ../mean.h.t.cpp + ../mem_cast.h.t.cpp ../memory.h.t.cpp ../memory_model.h.t.cpp ../message.h.t.cpp diff --git a/test/sanity-check/mem_cast.h.t.cpp b/test/sanity-check/mem_cast.h.t.cpp new file mode 100644 index 00000000..d62b8b27 --- /dev/null +++ b/test/sanity-check/mem_cast.h.t.cpp @@ -0,0 +1,29 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2021 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 diff --git a/test/test_mem_cast.cpp b/test/test_mem_cast.cpp new file mode 100644 index 00000000..cb9105ee --- /dev/null +++ b/test/test_mem_cast.cpp @@ -0,0 +1,209 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2021 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/mem_cast.h" +#include "etl/largest.h" + +#include +#include +#include +#include + +namespace +{ + struct Data + { + Data() + : c(0) + , d(0) + , a() + { + } + + Data(char c_, double d_, std::array a_) + : c(c_) + , d(d_) + , a(a_) + { + } + + char c; + double d; + std::array a; + }; + + constexpr size_t Size = etl::largest::size; + constexpr size_t Alignment = etl::largest::alignment; + + // Test variant types. + using MemCast = etl::mem_cast; + using MemCastTypes = etl::mem_cast_types; + + char c; + double d; + Data data; + + SUITE(test_mem_cast) + { + //************************************************************************* + TEST(test_size) + { + MemCast memCast; + MemCastTypes memCastTypes; + + CHECK(sizeof(char) <= MemCast::Size); + CHECK(sizeof(short) <= MemCast::Size); + CHECK(sizeof(Data) <= MemCast::Size); + + CHECK(sizeof(char) <= memCast.Size); + CHECK(sizeof(short) <= memCast.Size); + CHECK(sizeof(Data) <= memCast.Size); + + CHECK(sizeof(char) <= memCast.size()); + CHECK(sizeof(short) <= memCast.size()); + CHECK(sizeof(Data) <= memCast.size()); + + CHECK(sizeof(char) <= MemCastTypes::Size); + CHECK(sizeof(short) <= MemCastTypes::Size); + CHECK(sizeof(Data) <= MemCastTypes::Size); + + CHECK(sizeof(char) <= memCastTypes.Size); + CHECK(sizeof(short) <= memCastTypes.Size); + CHECK(sizeof(Data) <= memCastTypes.Size); + + CHECK(sizeof(char) <= memCastTypes.size()); + CHECK(sizeof(short) <= memCastTypes.size()); + CHECK(sizeof(Data) <= memCastTypes.size()); + } + + //************************************************************************* + TEST(test_alignment) + { + MemCast memCast; + MemCastTypes memCastTypes; + + CHECK(alignof(char) <= MemCast::Alignment); + CHECK(alignof(short) <= MemCast::Alignment); + CHECK(alignof(Data) <= MemCast::Alignment); + + CHECK(alignof(char) <= memCast.Alignment); + CHECK(alignof(short) <= memCast.Alignment); + CHECK(alignof(Data) <= memCast.Alignment); + + CHECK(alignof(char) <= memCast.alignment()); + CHECK(alignof(short) <= memCast.alignment()); + CHECK(alignof(Data) <= memCast.alignment()); + + CHECK(alignof(char) <= MemCastTypes::Alignment); + CHECK(alignof(short) <= MemCastTypes::Alignment); + CHECK(alignof(Data) <= MemCastTypes::Alignment); + + CHECK(alignof(char) <= memCastTypes.Alignment); + CHECK(alignof(short) <= memCastTypes.Alignment); + CHECK(alignof(Data) <= memCastTypes.Alignment); + + CHECK(alignof(char) <= memCastTypes.alignment()); + CHECK(alignof(short) <= memCastTypes.alignment()); + CHECK(alignof(Data) <= memCastTypes.alignment()); + } + + //************************************************************************* + TEST(test_mem_cast_emplace_type) + { + MemCast memCast; + + memCast.emplace(123); + CHECK_EQUAL(123, memCast.ref()); + + memCast.emplace(1.23); + CHECK_EQUAL(1.23, memCast.ref()); + + memCast.emplace(123, 1.23, std::array{ 1, 2, 3 }); + CHECK(123 == memCast.ref().c); + CHECK(1.23 == memCast.ref().d); + CHECK((std::array { 1, 2, 3 }) == memCast.ref().a); + } + + //************************************************************************* + TEST(test_mem_cast_to_type) + { + MemCast memCast; + + char* pbuffer = memCast.data(); + *pbuffer = 123; + CHECK_EQUAL(123, memCast.ref()); + + *reinterpret_cast(pbuffer) = 1.23; + CHECK_EQUAL(1.23, memCast.ref()); + + *reinterpret_cast(pbuffer) = { 123, 1.23, { 1, 2, 3 } }; + CHECK(123 == memCast.ref().c); + CHECK(1.23 == memCast.ref().d); + CHECK((std::array { 1, 2, 3 }) == memCast.ref().a); + } + + //************************************************************************* + TEST(test_const_mem_cast_to_type) + { + MemCast memCast; + const MemCast& memCastRef = memCast; + + char* pbuffer = memCast.data(); + *pbuffer = 123; + CHECK_EQUAL(123, memCastRef.ref()); + + *reinterpret_cast(pbuffer) = 1.23; + CHECK_EQUAL(1.23, memCastRef.ref()); + + *reinterpret_cast(pbuffer) = { 123, 1.23, { 1, 2, 3 } }; + CHECK(123 == memCastRef.ref().c); + CHECK(1.23 == memCastRef.ref().d); + CHECK((std::array { 1, 2, 3 }) == memCastRef.ref().a); + } + + //************************************************************************* + TEST(test_mem_cast_types_to_type) + { + MemCastTypes memCastTypes; + + char* pbuffer = memCastTypes.data(); + *pbuffer = 123; + CHECK_EQUAL(123, memCastTypes.ref()); + + *reinterpret_cast(pbuffer) = 1.23; + CHECK_EQUAL(1.23, memCastTypes.ref()); + + *reinterpret_cast(pbuffer) = { 123, 1.23, { 1, 2, 3 } }; + CHECK(123 == memCastTypes.ref().c); + CHECK(1.23 == memCastTypes.ref().d); + CHECK((std::array { 1, 2, 3 }) == memCastTypes.ref().a); + } + }; +} diff --git a/test/test_mem_cast_ptr.cpp b/test/test_mem_cast_ptr.cpp new file mode 100644 index 00000000..90bfae39 --- /dev/null +++ b/test/test_mem_cast_ptr.cpp @@ -0,0 +1,188 @@ +/****************************************************************************** +The MIT License(MIT) + +Embedded Template Library. +https://github.com/ETLCPP/etl +https://www.etlcpp.com + +Copyright(c) 2021 jwellbelove + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files(the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and / or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions : + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. +******************************************************************************/ + +#include "unit_test_framework.h" + +#include "etl/mem_cast.h" +#include "etl/largest.h" + +#include +#include +#include +#include + +namespace +{ + struct Data + { + Data() + : c(0) + , d(0) + , a() + { + } + + Data(char c_, double d_, std::array a_) + : c(c_) + , d(d_) + , a(a_) + { + } + + char c; + double d; + std::array a; + }; + + constexpr size_t Size = etl::largest::size; + constexpr size_t Alignment = etl::largest::alignment; + + // Test variant types. + using MemCast = etl::mem_cast_ptr; + + char c; + double d; + Data data; + + std::aligned_storage_t buffer; + + SUITE(test_mem_cast) + { + //************************************************************************* + TEST(test_size) + { + MemCast memCast; + + CHECK(sizeof(char) <= MemCast::Size); + CHECK(sizeof(short) <= MemCast::Size); + CHECK(sizeof(Data) <= MemCast::Size); + + CHECK(sizeof(char) <= memCast.Size); + CHECK(sizeof(short) <= memCast.Size); + CHECK(sizeof(Data) <= memCast.Size); + + CHECK(sizeof(char) <= memCast.size()); + CHECK(sizeof(short) <= memCast.size()); + CHECK(sizeof(Data) <= memCast.size()); + } + + //************************************************************************* + TEST(test_mem_cast_emplace_type) + { + char* pbuffer = reinterpret_cast(&buffer); + + MemCast memCast(pbuffer); + + memCast.emplace(123); + CHECK_EQUAL(123, memCast.ref()); + + memCast.emplace(1.23); + CHECK_EQUAL(1.23, memCast.ref()); + + memCast.emplace(123, 1.23, std::array{ 1, 2, 3 }); + CHECK(123 == memCast.ref().c); + CHECK(1.23 == memCast.ref().d); + CHECK((std::array { 1, 2, 3 }) == memCast.ref().a); + } + + //************************************************************************* + TEST(test_mem_cast_to_type) + { + char* pbuffer = reinterpret_cast(&buffer); + + MemCast memCast(pbuffer); + + pbuffer = memCast.data(); + *pbuffer = 123; + CHECK_EQUAL(123, memCast.ref()); + + *reinterpret_cast(pbuffer) = 1.23; + CHECK_EQUAL(1.23, memCast.ref()); + + *reinterpret_cast(pbuffer) = { 123, 1.23, { 1, 2, 3 } }; + CHECK(123 == memCast.ref().c); + CHECK(1.23 == memCast.ref().d); + CHECK((std::array { 1, 2, 3 }) == memCast.ref().a); + } + + //************************************************************************* + TEST(test_const_mem_cast_to_type) + { + char* pbuffer = reinterpret_cast(&buffer); + + const MemCast memCast(pbuffer); + + *pbuffer = 123; + CHECK_EQUAL(123, memCast.ref()); + + *reinterpret_cast(pbuffer) = 1.23; + CHECK_EQUAL(1.23, memCast.ref()); + + *reinterpret_cast(pbuffer) = { 123, 1.23, { 1, 2, 3 } }; + CHECK(123 == memCast.ref().c); + CHECK(1.23 == memCast.ref().d); + CHECK((std::array { 1, 2, 3 }) == memCast.ref().a); + } + + //************************************************************************* + TEST(test_mem_cast_to_type_no_buffer) + { + MemCast memCast; + + CHECK_THROW(memCast.ref(), etl::mem_cast_nullptr_exception); + } + + //************************************************************************* + TEST(test_const_mem_cast_to_type_no_buffer) + { + const MemCast memCast; + + CHECK_THROW(memCast.ref(), etl::mem_cast_nullptr_exception); + } + + //************************************************************************* + TEST(test_mem_cast_to_type_misaligned_buffer) + { + double d; + char* pbuffer = reinterpret_cast(&d); + MemCast memCast(pbuffer + 1); + + CHECK_THROW(memCast.ref(), etl::mem_cast_alignment_exception); + } + + //************************************************************************* + TEST(test_const_mem_cast_to_type_misaligned_buffer) + { + double d; + char* pbuffer = reinterpret_cast(&d); + const MemCast memCast(pbuffer + 1); + + CHECK_THROW(memCast.ref(), etl::mem_cast_alignment_exception); + } + }; +} diff --git a/test/vs2019/etl.vcxproj b/test/vs2019/etl.vcxproj index 80c7a26d..102055ea 100644 --- a/test/vs2019/etl.vcxproj +++ b/test/vs2019/etl.vcxproj @@ -1339,6 +1339,7 @@ + @@ -3228,6 +3229,22 @@ true true + + true + true + true + true + true + true + true + true + true + true + true + true + true + true + true true @@ -4492,6 +4509,8 @@ + + diff --git a/test/vs2019/etl.vcxproj.filters b/test/vs2019/etl.vcxproj.filters index 8b11f5cf..46c2f34d 100644 --- a/test/vs2019/etl.vcxproj.filters +++ b/test/vs2019/etl.vcxproj.filters @@ -1101,6 +1101,9 @@ ETL\Frameworks + + ETL\Utilities + @@ -2519,6 +2522,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files\Sanity Checks + From 177c4d1e79f8bd74f6d699ca6b0435e872c92386 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 2 Jun 2021 21:33:08 +0100 Subject: [PATCH 05/20] Added 'at_offset' functions. Changed size for mem_cast_ptr from template parameter fo member variable. --- include/etl/mem_cast.h | 339 +++++++++++++++++++++++++++++++++---- test/test_mem_cast.cpp | 74 ++++++++ test/test_mem_cast_ptr.cpp | 207 ++++++++++++++++++++-- 3 files changed, 570 insertions(+), 50 deletions(-) diff --git a/include/etl/mem_cast.h b/include/etl/mem_cast.h index b43b7af9..8aee094e 100644 --- a/include/etl/mem_cast.h +++ b/include/etl/mem_cast.h @@ -43,6 +43,7 @@ SOFTWARE. #include "exception.h" #include "error_handler.h" #include "file_error_numbers.h" +#include "binary.h" namespace etl { @@ -72,6 +73,19 @@ namespace etl } }; + //*************************************************************************** + /// The exception thrown when the type size is too large. + //*************************************************************************** + class mem_cast_size_exception : public etl::mem_cast_exception + { + public: + + mem_cast_size_exception(string_type file_name_, numeric_type line_number_) + : mem_cast_exception(ETL_ERROR_TEXT("mem_cast:size", ETL_MEM_CAST_FILE_ID"B"), file_name_, line_number_) + { + } + }; + //*************************************************************************** /// The exception thrown when the pointer is null. //*************************************************************************** @@ -80,7 +94,7 @@ namespace etl public: mem_cast_nullptr_exception(string_type file_name_, numeric_type line_number_) - : mem_cast_exception(ETL_ERROR_TEXT("mem_cast:null pointer", ETL_MEM_CAST_FILE_ID"B"), file_name_, line_number_) + : mem_cast_exception(ETL_ERROR_TEXT("mem_cast:null pointer", ETL_MEM_CAST_FILE_ID"C"), file_name_, line_number_) { } }; @@ -116,6 +130,43 @@ namespace etl memcpy(buffer, other.buffer, Size_); } + //*********************************** + /// Assign from parameters + //*********************************** + template + void assign(const T& value) + { + ETL_STATIC_ASSERT(Size >= sizeof(T), "Type size is too large"); + + ::new (static_cast(buffer)) T(value); + } + + //*********************************** + /// Assign from parameters at offset + //*********************************** + template + void assign_at_offset(size_t offset, const T& value) + { + char* p = static_cast(buffer) + offset; + ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception)); + + ::new (p) T(value); + } + + //*********************************** + /// Assign from parameters at offset + //*********************************** + template + void assign_at_offset(const T& value) + { + char* p = static_cast(buffer) + Offset; + ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Type size is too large"); + + ::new (p) T(value); + } + #if ETL_CPP11_SUPPORTED //*********************************** /// Emplace from parameters @@ -123,15 +174,43 @@ namespace etl template void emplace(TArgs... args) { + ETL_STATIC_ASSERT(Size >= sizeof(T), "Type size is too large"); + ::new (static_cast(buffer)) T(etl::forward(args)...); } + + //*********************************** + /// Emplace from parameters at offset + //*********************************** + template + void emplace_at_offset(size_t offset, TArgs... args) + { + char* p = static_cast(buffer) + offset; + ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception)); + + ::new (p) T(etl::forward(args)...); + } + + //*********************************** + /// Emplace from parameters at offset + //*********************************** + template + void emplace_at_offset(TArgs... args) + { + char* p = static_cast(buffer) + Offset; + ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Type size is too large"); + + ::new (p) T(etl::forward(args)...); + } #endif //*********************************** /// Get a reference to T //*********************************** template - T& ref() + ETL_NODISCARD T& ref() { ETL_STATIC_ASSERT(sizeof(T) <= Size, "Size of T is too large"); ETL_STATIC_ASSERT(Alignment >= etl::alignment_of::value, "Alignment of T is incompatible"); @@ -143,7 +222,7 @@ namespace etl /// Get a const reference to T //*********************************** template - const T& ref() const + ETL_NODISCARD const T& ref() const { ETL_STATIC_ASSERT(sizeof(T) <= Size, "Size of T is too large"); ETL_STATIC_ASSERT(Alignment >= etl::alignment_of::value, "Alignment of T is incompatible"); @@ -151,6 +230,62 @@ namespace etl return *static_cast(buffer); } + //*********************************** + /// Get a reference to T at offset (dynamic) + //*********************************** + template + ETL_NODISCARD T& ref_at_offset(size_t offset) + { + ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception)); + + char* p = buffer + offset; + ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + + return *static_cast(p); + } + + //*********************************** + /// Get a const reference to T at offset (dynamic) + //*********************************** + template + ETL_NODISCARD const T& ref_at_offset(size_t offset) const + { + ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception)); + + char* p = buffer + offset; + ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + + return *static_cast(p); + } + + //*********************************** + /// Get a reference to T at offset (static) + //*********************************** + template + ETL_NODISCARD T& ref_at_offset() + { + ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Size of T is too large"); + + char* p = buffer + Offset; + ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + + return *static_cast(p); + } + + //*********************************** + /// Get a const reference to T at offset (static) + //*********************************** + template + ETL_NODISCARD const T& ref_at_offset() const + { + ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Size of T is too large"); + + char* p = buffer + Offset; + ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + + return *static_cast(p); + } + //*********************************** /// Assignment operator //*********************************** @@ -168,7 +303,7 @@ namespace etl //*********************************** /// Get the size of the buffer //*********************************** - ETL_CONSTEXPR size_t size() const + ETL_NODISCARD static ETL_CONSTEXPR size_t size() { return Size; } @@ -176,7 +311,7 @@ namespace etl //*********************************** /// Get the alignment of the buffer //*********************************** - ETL_CONSTEXPR size_t alignment() const + ETL_NODISCARD static ETL_CONSTEXPR size_t alignment() { return Alignment; } @@ -184,7 +319,7 @@ namespace etl //*********************************** /// Get a pointer to the internal buffer //*********************************** - char* data() + ETL_NODISCARD char* data() { return buffer; } @@ -192,7 +327,7 @@ namespace etl //*********************************** /// Get a const pointer to the internal buffer //*********************************** - const char* data() const + ETL_NODISCARD const char* data() const { return buffer; } @@ -206,40 +341,78 @@ namespace etl //***************************************************************************** /// mem_cast_ptr //***************************************************************************** - template class mem_cast_ptr { public: - static ETL_CONSTANT size_t Size = Size_; + static ETL_CONSTANT size_t Undefined_Size = etl::integral_limits::max; //*********************************** /// Default constructor //*********************************** mem_cast_ptr() : pbuffer(ETL_NULLPTR) + , buffer_size(Undefined_Size) { } //*********************************** - /// Construct with pointer to buffer + /// Construct with pointer to buffer and optional size //*********************************** - mem_cast_ptr(char* pbuffer_) + mem_cast_ptr(char* pbuffer_, size_t buffer_size_ = Undefined_Size) : pbuffer(pbuffer_) + , buffer_size(buffer_size_) { } //*********************************** - /// Copy construct with pointer to buffer + /// Copy construct //*********************************** - template - mem_cast_ptr(const mem_cast_ptr& other, char* pbuffer_) - : pbuffer(pbuffer_) + mem_cast_ptr(const mem_cast_ptr& other) + : pbuffer(other.pbuffer) + , buffer_size(other.buffer_size) + { + } + + //*********************************** + /// Assign from parameters + //*********************************** + template + void assign(const T& value) { ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); - ETL_STATIC_ASSERT(Size >= Other_Size, "Other size is too large"); + ETL_ASSERT((reinterpret_cast(pbuffer) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception)); - memcpy(pbuffer, other.pbuffer, Size_); + ::new (pbuffer) T(value); + } + + //*********************************** + /// Assign from parameters at offset + //*********************************** + template + void assign_at_offset(size_t offset, const T& value) + { + ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); + char* p = pbuffer + offset; + ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_ASSERT(sizeof(T) <= (buffer_size - offset), ETL_ERROR(etl::mem_cast_size_exception)); + + ::new (p) T(value); + } + + //*********************************** + /// Assign from parameters at offset + //*********************************** + template + void assign_at_offset(const T& value) + { + ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); + char* p = pbuffer + Offset; + ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception)); + + ::new (p) T(value); } #if ETL_CPP11_SUPPORTED @@ -250,20 +423,50 @@ namespace etl void emplace(TArgs... args) { ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); - ETL_ASSERT((uintptr_t(pbuffer) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_ASSERT((reinterpret_cast(pbuffer) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception)); ::new (pbuffer) T(etl::forward(args)...); } + + //*********************************** + /// Emplace from parameters at offset + //*********************************** + template + void emplace_at_offset(size_t offset, TArgs... args) + { + ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); + char* p = pbuffer + offset; + ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_ASSERT(sizeof(T) <= (buffer_size - offset), ETL_ERROR(etl::mem_cast_size_exception)); + + ::new (p) T(etl::forward(args)...); + } + + //*********************************** + /// Emplace from parameters at offset + //*********************************** + template + void emplace_at_offset(TArgs... args) + { + ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); + char* p = pbuffer + Offset; + ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception)); + + ::new (p) T(etl::forward(args)...); + } #endif //*********************************** /// Get a reference to T //*********************************** template - T& ref() + ETL_NODISCARD T& ref() { ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); - ETL_ASSERT((uintptr_t(pbuffer) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_ASSERT((reinterpret_cast(pbuffer) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception)); return *reinterpret_cast(pbuffer); } @@ -272,46 +475,113 @@ namespace etl /// Get a const reference to T //*********************************** template - const T& ref() const + ETL_NODISCARD const T& ref() const { ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); - ETL_ASSERT((uintptr_t(pbuffer) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_ASSERT((reinterpret_cast(pbuffer) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception)); return *reinterpret_cast(pbuffer); } //*********************************** - template - mem_cast_ptr& operator =(const mem_cast_ptr& rhs) + /// Get a reference to T at offset (dynamic) + //*********************************** + template + ETL_NODISCARD T& ref_at_offset(size_t offset) { ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); - ETL_STATIC_ASSERT(Size >= Other_Size, "RHS size is too large"); + char* p = pbuffer + offset; + ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_ASSERT(sizeof(T) <= (buffer_size - offset), ETL_ERROR(etl::mem_cast_size_exception)); - memcpy(pbuffer, rhs.pbuffer, Size_); + return *reinterpret_cast(p); + } - return *this; + //*********************************** + /// Get a const reference to T at offset (dynamic) + //*********************************** + template + ETL_NODISCARD const T& ref_at_offset(size_t offset) const + { + ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); + char* p = pbuffer + offset; + ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_ASSERT(sizeof(T) <= (buffer_size - offset), ETL_ERROR(etl::mem_cast_size_exception)); + + return *reinterpret_cast(p); + } + + //*********************************** + /// Get a reference to T at offset (static) + //*********************************** + template + ETL_NODISCARD T& ref_at_offset() + { + ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); + char* p = pbuffer + Offset; + ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception)); + + return *reinterpret_cast(p); + } + + //*********************************** + /// Get a const reference to T at offset (static) + //*********************************** + template + ETL_NODISCARD const T& ref_at_offset() const + { + ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); + char* p = pbuffer + Offset; + ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); + ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception)); + + return *reinterpret_cast(p); } //*********************************** /// Assignment operator //*********************************** - ETL_CONSTEXPR size_t size() const + mem_cast_ptr& operator =(const mem_cast_ptr& rhs) { - return Size; + pbuffer = rhs.pbuffer; + buffer_size = rhs.buffer_size; + + return *this; + } + + //*********************************** + /// Get the size of the buffer + //*********************************** + ETL_NODISCARD size_t size() const + { + return buffer_size; + } + + //*********************************** + /// Get the alignment of the buffer + //*********************************** + ETL_NODISCARD size_t alignment() const + { + const uintptr_t p = reinterpret_cast(pbuffer); + + return 1U << etl::count_trailing_zeros(p); } //*********************************** /// Set the pointer to the external buffer //*********************************** - void data(char* pbuffer_) + void data(char* pbuffer_, size_t buffer_size_ = Undefined_Size) { - pbuffer = pbuffer_; + pbuffer = pbuffer_; + buffer_size = buffer_size_; } //*********************************** /// Get a pointer to the external buffer //*********************************** - char* data() + ETL_NODISCARD char* data() { return pbuffer; } @@ -319,7 +589,7 @@ namespace etl //*********************************** /// Get const a pointer to the external buffer //*********************************** - const char* data() const + ETL_NODISCARD const char* data() const { return pbuffer; } @@ -327,7 +597,8 @@ namespace etl private: /// Pointer to the buffer - char* pbuffer; + char* pbuffer; + size_t buffer_size; }; #if ETL_CPP11_SUPPORTED diff --git a/test/test_mem_cast.cpp b/test/test_mem_cast.cpp index cb9105ee..65e33da0 100644 --- a/test/test_mem_cast.cpp +++ b/test/test_mem_cast.cpp @@ -134,6 +134,52 @@ namespace CHECK(alignof(Data) <= memCastTypes.alignment()); } + //************************************************************************* + TEST(test_mem_cast_assign_type) + { + MemCast memCast; + + memCast.assign(123); + CHECK_EQUAL(123, memCast.ref()); + + memCast.assign(1.23); + CHECK_EQUAL(1.23, memCast.ref()); + + Data data(123, 1.23, std::array{ 1, 2, 3 }); + memCast.assign(data); + CHECK(123 == memCast.ref().c); + CHECK(1.23 == memCast.ref().d); + CHECK((std::array { 1, 2, 3 }) == memCast.ref().a); + } + + //************************************************************************* + TEST(test_mem_cast_assign_type_at_dynamic_offset) + { + MemCast memCast; + + using Array = std::array; + Array a{ 1, 2, 3 }; + + size_t offset = offsetof(Data, a); + + memCast.assign_at_offset(offset, a); + CHECK(a == memCast.ref().a); + } + + //************************************************************************* + TEST(test_mem_cast_assign_type_at_static_offset) + { + MemCast memCast; + + using Array = std::array; + Array a{ 1, 2, 3 }; + + constexpr size_t Offset = offsetof(Data, a); + + memCast.assign_at_offset(a); + CHECK(a == memCast.ref().a); + } + //************************************************************************* TEST(test_mem_cast_emplace_type) { @@ -151,6 +197,34 @@ namespace CHECK((std::array { 1, 2, 3 }) == memCast.ref().a); } + //************************************************************************* + TEST(test_mem_cast_emplace_type_at_dynamic_offset) + { + MemCast memCast; + + using Array = std::array; + Array a{ 1, 2, 3 }; + + size_t offset = offsetof(Data, a); + + memCast.emplace_at_offset(offset, a); + CHECK(a == memCast.ref().a); + } + + //************************************************************************* + TEST(test_mem_cast_emplace_type_at_static_offset) + { + MemCast memCast; + + using Array = std::array; + Array a{ 1, 2, 3 }; + + constexpr size_t Offset = offsetof(Data, a); + + memCast.emplace_at_offset(a); + CHECK(a == memCast.ref().a); + } + //************************************************************************* TEST(test_mem_cast_to_type) { diff --git a/test/test_mem_cast_ptr.cpp b/test/test_mem_cast_ptr.cpp index 90bfae39..aaf29033 100644 --- a/test/test_mem_cast_ptr.cpp +++ b/test/test_mem_cast_ptr.cpp @@ -63,32 +63,175 @@ namespace constexpr size_t Alignment = etl::largest::alignment; // Test variant types. - using MemCast = etl::mem_cast_ptr; + using MemCast = etl::mem_cast_ptr; char c; double d; Data data; + char* Ptr(int i) + { + return reinterpret_cast(i); + } + std::aligned_storage_t buffer; - SUITE(test_mem_cast) + SUITE(test_mem_cast_ptr) { //************************************************************************* - TEST(test_size) + TEST(test_alignment) { MemCast memCast; - CHECK(sizeof(char) <= MemCast::Size); - CHECK(sizeof(short) <= MemCast::Size); - CHECK(sizeof(Data) <= MemCast::Size); + char* p = nullptr; - CHECK(sizeof(char) <= memCast.Size); - CHECK(sizeof(short) <= memCast.Size); - CHECK(sizeof(Data) <= memCast.Size); + memCast.data(Ptr(1)); + CHECK_EQUAL(1U , memCast.alignment()); - CHECK(sizeof(char) <= memCast.size()); - CHECK(sizeof(short) <= memCast.size()); - CHECK(sizeof(Data) <= memCast.size()); + memCast.data(Ptr(2)); + CHECK_EQUAL(2U , memCast.alignment()); + + memCast.data(Ptr(3)); + CHECK_EQUAL(1U , memCast.alignment()); + + memCast.data(Ptr(4)); + CHECK_EQUAL(4U , memCast.alignment()); + + memCast.data(Ptr(5)); + CHECK_EQUAL(1U , memCast.alignment()); + + memCast.data(Ptr(6)); + CHECK_EQUAL(2U , memCast.alignment()); + + memCast.data(Ptr(7)); + CHECK_EQUAL(1U , memCast.alignment()); + + memCast.data(Ptr(8)); + CHECK_EQUAL(8U , memCast.alignment()); + + memCast.data(Ptr(9)); + CHECK_EQUAL(1U , memCast.alignment()); + + memCast.data(Ptr(10)); + CHECK_EQUAL(2U , memCast.alignment()); + + memCast.data(Ptr(11)); + CHECK_EQUAL(1U , memCast.alignment()); + + memCast.data(Ptr(12)); + CHECK_EQUAL(4U , memCast.alignment()); + + memCast.data(Ptr(13)); + CHECK_EQUAL(1U , memCast.alignment()); + + memCast.data(Ptr(14)); + CHECK_EQUAL(2U , memCast.alignment()); + + memCast.data(Ptr(15)); + CHECK_EQUAL(1U , memCast.alignment()); + + memCast.data(Ptr(16)); + CHECK_EQUAL(16U , memCast.alignment()); + + memCast.data(Ptr(17)); + CHECK_EQUAL(1U , memCast.alignment()); + + memCast.data(Ptr(18)); + CHECK_EQUAL(2U , memCast.alignment()); + + memCast.data(Ptr(19)); + CHECK_EQUAL(1U , memCast.alignment()); + + memCast.data(Ptr(20)); + CHECK_EQUAL(4U , memCast.alignment()); + + memCast.data(Ptr(21)); + CHECK_EQUAL(1U , memCast.alignment()); + + memCast.data(Ptr(22)); + CHECK_EQUAL(2U , memCast.alignment()); + + memCast.data(Ptr(23)); + CHECK_EQUAL(1U , memCast.alignment()); + + memCast.data(Ptr(24)); + CHECK_EQUAL(8U , memCast.alignment()); + + memCast.data(Ptr(25)); + CHECK_EQUAL(1U , memCast.alignment()); + + memCast.data(Ptr(26)); + CHECK_EQUAL(2U , memCast.alignment()); + + memCast.data(Ptr(27)); + CHECK_EQUAL(1U , memCast.alignment()); + + memCast.data(Ptr(28)); + CHECK_EQUAL(4U , memCast.alignment()); + + memCast.data(Ptr(29)); + CHECK_EQUAL(1U , memCast.alignment()); + + memCast.data(Ptr(30)); + CHECK_EQUAL(2U , memCast.alignment()); + + memCast.data(Ptr(31)); + CHECK_EQUAL(1U , memCast.alignment()); + + memCast.data(Ptr(32)); + CHECK_EQUAL(32U , memCast.alignment()); + } + + //************************************************************************* + TEST(test_mem_cast_assign_type) + { + char* pbuffer = reinterpret_cast(&buffer); + + MemCast memCast(pbuffer); + + memCast.assign(123); + CHECK_EQUAL(123, memCast.ref()); + + memCast.assign(1.23); + CHECK_EQUAL(1.23, memCast.ref()); + + Data data(123, 1.23, std::array{ 1, 2, 3 }); + memCast.assign(data); + CHECK(123 == memCast.ref().c); + CHECK(1.23 == memCast.ref().d); + CHECK((std::array { 1, 2, 3 }) == memCast.ref().a); + } + + //************************************************************************* + TEST(test_mem_cast_assign_type_at_dynamic_offset) + { + char* pbuffer = reinterpret_cast(&buffer); + + MemCast memCast(pbuffer); + + using Array = std::array; + Array a{ 1, 2, 3 }; + + size_t offset = offsetof(Data, a); + + memCast.assign_at_offset(offset, a); + CHECK(a == memCast.ref().a); + } + + //************************************************************************* + TEST(test_mem_cast_assign_type_at_static_offset) + { + char* pbuffer = reinterpret_cast(&buffer); + + MemCast memCast(pbuffer); + + using Array = std::array; + Array a{ 1, 2, 3 }; + + constexpr size_t Offset = offsetof(Data, a); + + memCast.assign_at_offset(a); + CHECK(a == memCast.ref().a); } //************************************************************************* @@ -110,6 +253,38 @@ namespace CHECK((std::array { 1, 2, 3 }) == memCast.ref().a); } + //************************************************************************* + TEST(test_mem_cast_emplace_type_at_dynamic_offset) + { + char* pbuffer = reinterpret_cast(&buffer); + + MemCast memCast(pbuffer); + + using Array = std::array; + Array a{ 1, 2, 3 }; + + size_t offset = offsetof(Data, a); + + memCast.emplace_at_offset(offset, a); + CHECK(a == memCast.ref().a); + } + + //************************************************************************* + TEST(test_mem_cast_emplace_type_at_static_offset) + { + char* pbuffer = reinterpret_cast(&buffer); + + MemCast memCast(pbuffer); + + using Array = std::array; + Array a{ 1, 2, 3 }; + + constexpr size_t Offset = offsetof(Data, a); + + memCast.emplace_at_offset(a); + CHECK(a == memCast.ref().a); + } + //************************************************************************* TEST(test_mem_cast_to_type) { @@ -154,7 +329,7 @@ namespace { MemCast memCast; - CHECK_THROW(memCast.ref(), etl::mem_cast_nullptr_exception); + CHECK_THROW(char c = memCast.ref(), etl::mem_cast_nullptr_exception); } //************************************************************************* @@ -162,7 +337,7 @@ namespace { const MemCast memCast; - CHECK_THROW(memCast.ref(), etl::mem_cast_nullptr_exception); + CHECK_THROW(char c = memCast.ref(), etl::mem_cast_nullptr_exception); } //************************************************************************* @@ -172,7 +347,7 @@ namespace char* pbuffer = reinterpret_cast(&d); MemCast memCast(pbuffer + 1); - CHECK_THROW(memCast.ref(), etl::mem_cast_alignment_exception); + CHECK_THROW(double d = memCast.ref(), etl::mem_cast_alignment_exception); } //************************************************************************* @@ -182,7 +357,7 @@ namespace char* pbuffer = reinterpret_cast(&d); const MemCast memCast(pbuffer + 1); - CHECK_THROW(memCast.ref(), etl::mem_cast_alignment_exception); + CHECK_THROW(double d = memCast.ref(), etl::mem_cast_alignment_exception); } }; } From e2eb6e865027a0a47c3cbb48aacbebbe8449c650 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Wed, 2 Jun 2021 21:34:48 +0100 Subject: [PATCH 06/20] Added ETL_ASSERT_AND_RETURN and ETL_ASSERT_AND_RETURN_VALUE error macros --- include/etl/error_handler.h | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/include/etl/error_handler.h b/include/etl/error_handler.h index 065f2480..fe62da42 100644 --- a/include/etl/error_handler.h +++ b/include/etl/error_handler.h @@ -269,26 +269,50 @@ namespace etl //*************************************************************************** #if defined(ETL_NO_CHECKS) #define ETL_ASSERT(b, e) // Does nothing. + #define ETL_ASSERT_AND_RETURN(b, e) // Does nothing. + #define ETL_ASSERT_AND_RETURN_VALUE(b, e, v) // Does nothing. #define ETL_ALWAYS_ASSERT(e) // Does nothing. + #define ETL_ALWAYS_ASSERT_AND_RETURN(e) // Does nothing. + #define ETL_ALWAYS_ASSERT_AND_RETURN_VALUE(e, v) // Does nothing. #elif defined(ETL_THROW_EXCEPTIONS) #if defined(ETL_LOG_ERRORS) - #define ETL_ASSERT(b, e) {if (!(b)) {etl::error_handler::error((e)); throw((e));}} // If the condition fails, calls the error handler then throws an exception. - #define ETL_ALWAYS_ASSERT(e) {etl::error_handler::error((e)); throw((e));} // Calls the error handler then throws an exception. + #define ETL_ASSERT(b, e) {if (!(b)) {etl::error_handler::error((e)); throw((e));}} // If the condition fails, calls the error handler then throws an exception. + #define ETL_ASSERT_AND_RETURN(b, e) {if (!(b)) {etl::error_handler::error((e)); throw((e));}} // If the condition fails, calls the error handler then throws an exception. + #define ETL_ASSERT_AND_RETURN_VALUE(b, e, v) {if (!(b)) {etl::error_handler::error((e)); throw((e));}} // If the condition fails, calls the error handler then throws an exception. + #define ETL_ALWAYS_ASSERT(e) {etl::error_handler::error((e)); throw((e));} // Calls the error handler then throws an exception. + #define ETL_ALWAYS_ASSERT_AND_RETURN(e) {etl::error_handler::error((e)); throw((e));} // Calls the error handler then throws an exception. + #define ETL_ALWAYS_ASSERT_AND_RETURN_VALUE(e) {etl::error_handler::error((e)); throw((e));} // Calls the error handler then throws an exception. #else #define ETL_ASSERT(b, e) {if (!(b)) {throw((e));}} // If the condition fails, throws an exception. + #define ETL_ASSERT_AND_RETURN(b, e) {if (!(b)) {throw((e));}} // If the condition fails, throws an exception. + #define ETL_ASSERT_AND_RETURN_VALUE(b, e, v) {if (!(b)) {throw((e));}} // If the condition fails, throws an exception. #define ETL_ALWAYS_ASSERT(e) {throw((e));} // Throws an exception. + #define ETL_ALWAYS_ASSERT_AND_RETURN(e) {throw((e));} // Throws an exception. + #define ETL_ALWAYS_ASSERT_AND_RETURN_VALUE(e, v) {throw((e));} // Throws an exception. #endif #else #if defined(ETL_LOG_ERRORS) - #define ETL_ASSERT(b, e) {if(!(b)) {etl::error_handler::error((e));}} // If the condition fails, calls the error handler - #define ETL_ALWAYS_ASSERT(e) {etl::error_handler::error((e));} // Calls the error handler + #define ETL_ASSERT(b, e) {if(!(b)) {etl::error_handler::error((e));}} // If the condition fails, calls the error handler + #define ETL_ASSERT_AND_RETURN(b, e) {if(!(b)) {etl::error_handler::error((e)); return;}} // If the condition fails, calls the error handler and return + #define ETL_ASSERT_AND_RETURN_VALUE(b, e, v) {if(!(b)) {etl::error_handler::error((e)); return (v);}} // If the condition fails, calls the error handler and return a value + #define ETL_ALWAYS_ASSERT(e) {etl::error_handler::error((e));} // Calls the error handler + #define ETL_ALWAYS_ASSERT_AND_RETURN(e) {etl::error_handler::error((e)); return;} // Calls the error handler and return + #define ETL_ALWAYS_ASSERT_AND_RETURN_VALUE(e, v) {etl::error_handler::error((e)); return (v);} // Calls the error handler and return a value #else #if defined(ETL_DEBUG) #define ETL_ASSERT(b, e) assert((b)) // If the condition fails, asserts. + #define ETL_ASSERT_AND_RETURN(b, e) assert((b)) // If the condition fails, asserts. + #define ETL_ASSERT_AND_RETURN_VALUE(b, e, v) assert((b)) // If the condition fails, asserts. #define ETL_ALWAYS_ASSERT(e) assert(false) // Asserts. + #define ETL_ALWAYS_ASSERT_AND_RETURN(e) assert(false) // Asserts. + #define ETL_ALWAYS_ASSERT_AND_RETURN_VALUE(e, v) assert(false) // Asserts. #else #define ETL_ASSERT(b, e) // Does nothing. + #define ETL_ASSERT_AND_RETURN(b, e) {if (!(b)) return;} // Returns. + #define ETL_ASSERT_AND_RETURN_VALUE(b, e, v) {if (!(b)) return(v);} // Returns a value. #define ETL_ALWAYS_ASSERT(e) // Does nothing. + #define ETL_ALWAYS_ASSERT_AND_RETURN(e) {return;} // Returns. + #define ETL_ALWAYS_ASSERT_AND_RETURN_VALUE(e, v) {return(v);} // Returns a value. #endif #endif #endif From 208d0c4a267d3b7a849fc4c74b8c06fce20a9060 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 3 Jun 2021 10:56:08 +0100 Subject: [PATCH 07/20] Added/adjusted 'force C++03' unit test macros --- include/etl/crc16.h | 2 +- include/etl/crc16_a.h | 2 +- include/etl/crc16_arc.h | 2 +- include/etl/crc16_aug_ccitt.h | 2 +- include/etl/crc16_buypass.h | 2 +- include/etl/crc16_ccitt.h | 2 +- include/etl/crc16_cdma2000.h | 2 +- include/etl/crc16_dds110.h | 2 +- include/etl/crc16_dectr.h | 2 +- include/etl/crc16_dectx.h | 2 +- include/etl/crc16_dnp.h | 2 +- include/etl/crc16_en13757.h | 2 +- include/etl/crc16_genibus.h | 2 +- include/etl/crc16_kermit.h | 2 +- include/etl/crc16_maxim.h | 2 +- include/etl/crc16_mcrf4xx.h | 2 +- include/etl/crc16_modbus.h | 2 +- include/etl/crc16_profibus.h | 2 +- include/etl/crc16_riello.h | 2 +- include/etl/crc16_t10dif.h | 2 +- include/etl/crc16_teledisk.h | 2 +- include/etl/crc16_tms37157.h | 2 +- include/etl/crc16_usb.h | 2 +- include/etl/crc16_x25.h | 2 +- include/etl/crc8_ccitt.h | 2 +- include/etl/crc8_cdma2000.h | 2 +- include/etl/crc8_darc.h | 2 +- include/etl/crc8_dvbs2.h | 2 +- include/etl/crc8_ebu.h | 2 +- include/etl/crc8_icode.h | 2 +- include/etl/crc8_itu.h | 2 +- include/etl/crc8_maxim.h | 2 +- include/etl/crc8_rohc.h | 2 +- include/etl/crc8_wcdma.h | 2 +- include/etl/mem_cast.h | 11 ++++++++++- test/etl_profile.h | 31 +++++++++++++++++-------------- 36 files changed, 61 insertions(+), 49 deletions(-) diff --git a/include/etl/crc16.h b/include/etl/crc16.h index f9c8cb2e..bbb5b5b4 100644 --- a/include/etl/crc16.h +++ b/include/etl/crc16.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_t = etl::crc_type; #else diff --git a/include/etl/crc16_a.h b/include/etl/crc16_a.h index 2430c9f4..be98d3ef 100644 --- a/include/etl/crc16_a.h +++ b/include/etl/crc16_a.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_a_t = etl::crc_type; #else diff --git a/include/etl/crc16_arc.h b/include/etl/crc16_arc.h index b60b667c..80799617 100644 --- a/include/etl/crc16_arc.h +++ b/include/etl/crc16_arc.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_arc_t = etl::crc_type; #else diff --git a/include/etl/crc16_aug_ccitt.h b/include/etl/crc16_aug_ccitt.h index 4cd66e10..807d432f 100644 --- a/include/etl/crc16_aug_ccitt.h +++ b/include/etl/crc16_aug_ccitt.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_aug_ccitt_t = etl::crc_type; #else diff --git a/include/etl/crc16_buypass.h b/include/etl/crc16_buypass.h index a8315e21..462a17ce 100644 --- a/include/etl/crc16_buypass.h +++ b/include/etl/crc16_buypass.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_buypass_t = etl::crc_type; #else diff --git a/include/etl/crc16_ccitt.h b/include/etl/crc16_ccitt.h index eefd8255..9a444345 100644 --- a/include/etl/crc16_ccitt.h +++ b/include/etl/crc16_ccitt.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_ccitt_t = etl::crc_type; #else diff --git a/include/etl/crc16_cdma2000.h b/include/etl/crc16_cdma2000.h index 3a5b2b77..7784c9ae 100644 --- a/include/etl/crc16_cdma2000.h +++ b/include/etl/crc16_cdma2000.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_cdma2000_t = etl::crc_type; #else diff --git a/include/etl/crc16_dds110.h b/include/etl/crc16_dds110.h index e3dbbf8e..7a998e66 100644 --- a/include/etl/crc16_dds110.h +++ b/include/etl/crc16_dds110.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_dds110_t = etl::crc_type; #else diff --git a/include/etl/crc16_dectr.h b/include/etl/crc16_dectr.h index 172ebbbb..327dfc51 100644 --- a/include/etl/crc16_dectr.h +++ b/include/etl/crc16_dectr.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_dect_r_t = etl::crc_type; #else diff --git a/include/etl/crc16_dectx.h b/include/etl/crc16_dectx.h index d018d6cf..a8497d8d 100644 --- a/include/etl/crc16_dectx.h +++ b/include/etl/crc16_dectx.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_dect_x_t = etl::crc_type; #else diff --git a/include/etl/crc16_dnp.h b/include/etl/crc16_dnp.h index a347ccd3..02c67c4f 100644 --- a/include/etl/crc16_dnp.h +++ b/include/etl/crc16_dnp.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_dnp_t = etl::crc_type; #else diff --git a/include/etl/crc16_en13757.h b/include/etl/crc16_en13757.h index 1cb217fc..d5ec5fed 100644 --- a/include/etl/crc16_en13757.h +++ b/include/etl/crc16_en13757.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_en13757_t = etl::crc_type; #else diff --git a/include/etl/crc16_genibus.h b/include/etl/crc16_genibus.h index 378eebc1..a7cbb382 100644 --- a/include/etl/crc16_genibus.h +++ b/include/etl/crc16_genibus.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_genibus_t = etl::crc_type; #else diff --git a/include/etl/crc16_kermit.h b/include/etl/crc16_kermit.h index fa7db6b1..66dedb5b 100644 --- a/include/etl/crc16_kermit.h +++ b/include/etl/crc16_kermit.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_kermit_t = etl::crc_type; #else diff --git a/include/etl/crc16_maxim.h b/include/etl/crc16_maxim.h index ef3a2bca..896ab11d 100644 --- a/include/etl/crc16_maxim.h +++ b/include/etl/crc16_maxim.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_maxim_t = etl::crc_type; #else diff --git a/include/etl/crc16_mcrf4xx.h b/include/etl/crc16_mcrf4xx.h index 24012377..06a3f890 100644 --- a/include/etl/crc16_mcrf4xx.h +++ b/include/etl/crc16_mcrf4xx.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_mcrf4xx_t = etl::crc_type; #else diff --git a/include/etl/crc16_modbus.h b/include/etl/crc16_modbus.h index aa536027..5743ef41 100644 --- a/include/etl/crc16_modbus.h +++ b/include/etl/crc16_modbus.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_modbus_t = etl::crc_type; #else diff --git a/include/etl/crc16_profibus.h b/include/etl/crc16_profibus.h index 275f5bb6..9b6951c1 100644 --- a/include/etl/crc16_profibus.h +++ b/include/etl/crc16_profibus.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_profibus_t = etl::crc_type; #else diff --git a/include/etl/crc16_riello.h b/include/etl/crc16_riello.h index 65f99583..ed1332e5 100644 --- a/include/etl/crc16_riello.h +++ b/include/etl/crc16_riello.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_riello_t = etl::crc_type; #else diff --git a/include/etl/crc16_t10dif.h b/include/etl/crc16_t10dif.h index 1087c8cd..44e767a8 100644 --- a/include/etl/crc16_t10dif.h +++ b/include/etl/crc16_t10dif.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_t10dif_t = etl::crc_type; #else diff --git a/include/etl/crc16_teledisk.h b/include/etl/crc16_teledisk.h index 29e78eca..f90d8964 100644 --- a/include/etl/crc16_teledisk.h +++ b/include/etl/crc16_teledisk.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_teledisk_t = etl::crc_type; #else diff --git a/include/etl/crc16_tms37157.h b/include/etl/crc16_tms37157.h index 4af39380..31de01c5 100644 --- a/include/etl/crc16_tms37157.h +++ b/include/etl/crc16_tms37157.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_tms37157_t = etl::crc_type; #else diff --git a/include/etl/crc16_usb.h b/include/etl/crc16_usb.h index 2a2528f6..bb67e42c 100644 --- a/include/etl/crc16_usb.h +++ b/include/etl/crc16_usb.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_usb_t = etl::crc_type; #else diff --git a/include/etl/crc16_x25.h b/include/etl/crc16_x25.h index afb705c0..9120a7c2 100644 --- a/include/etl/crc16_x25.h +++ b/include/etl/crc16_x25.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc16_x25_t = etl::crc_type; #else diff --git a/include/etl/crc8_ccitt.h b/include/etl/crc8_ccitt.h index 80c7ec8e..d95b85c2 100644 --- a/include/etl/crc8_ccitt.h +++ b/include/etl/crc8_ccitt.h @@ -36,7 +36,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc8_ccitt_t = etl::crc_type; #else diff --git a/include/etl/crc8_cdma2000.h b/include/etl/crc8_cdma2000.h index d7a83108..f1607e56 100644 --- a/include/etl/crc8_cdma2000.h +++ b/include/etl/crc8_cdma2000.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc8_cdma2000_t = etl::crc_type; #else diff --git a/include/etl/crc8_darc.h b/include/etl/crc8_darc.h index 29a6a167..f419a706 100644 --- a/include/etl/crc8_darc.h +++ b/include/etl/crc8_darc.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc8_darc_t = etl::crc_type; #else diff --git a/include/etl/crc8_dvbs2.h b/include/etl/crc8_dvbs2.h index 02fe9f03..bd55a255 100644 --- a/include/etl/crc8_dvbs2.h +++ b/include/etl/crc8_dvbs2.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc8_dvbs2_t = etl::crc_type; #else diff --git a/include/etl/crc8_ebu.h b/include/etl/crc8_ebu.h index 3c4c7f2e..47b4613b 100644 --- a/include/etl/crc8_ebu.h +++ b/include/etl/crc8_ebu.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc8_ebu_t = etl::crc_type; #else diff --git a/include/etl/crc8_icode.h b/include/etl/crc8_icode.h index e421cc46..e51c6dfb 100644 --- a/include/etl/crc8_icode.h +++ b/include/etl/crc8_icode.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc8_icode_t = etl::crc_type; #else diff --git a/include/etl/crc8_itu.h b/include/etl/crc8_itu.h index a4a7fc0c..f84aa025 100644 --- a/include/etl/crc8_itu.h +++ b/include/etl/crc8_itu.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc8_itu_t = etl::crc_type; #else diff --git a/include/etl/crc8_maxim.h b/include/etl/crc8_maxim.h index bf39cd32..a138657f 100644 --- a/include/etl/crc8_maxim.h +++ b/include/etl/crc8_maxim.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc8_maxim_t = etl::crc_type; #else diff --git a/include/etl/crc8_rohc.h b/include/etl/crc8_rohc.h index dcade461..34e61dbe 100644 --- a/include/etl/crc8_rohc.h +++ b/include/etl/crc8_rohc.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc8_rohc_t = etl::crc_type; #else diff --git a/include/etl/crc8_wcdma.h b/include/etl/crc8_wcdma.h index a947e09a..f30d3529 100644 --- a/include/etl/crc8_wcdma.h +++ b/include/etl/crc8_wcdma.h @@ -39,7 +39,7 @@ SOFTWARE. namespace etl { -#if ETL_CPP11_SUPPORTED && !ETL_CRC_FORCE_CPP03 +#if ETL_CPP11_SUPPORTED && !defined(ETL_CRC_FORCE_CPP03) template using crc8_wcdma_t = etl::crc_type; #else diff --git a/include/etl/mem_cast.h b/include/etl/mem_cast.h index 8aee094e..2f156268 100644 --- a/include/etl/mem_cast.h +++ b/include/etl/mem_cast.h @@ -601,13 +601,22 @@ namespace etl size_t buffer_size; }; -#if ETL_CPP11_SUPPORTED //***************************************************************************** /// mem_cast_var /// mem_cast from a variadic list of types //***************************************************************************** +#if ETL_CPP11_SUPPORTED && !defined(ETL_MEM_CAST_FORCE_CPP03) template using mem_cast_types = etl::mem_cast::size, etl::largest::alignment>; +#else + template + struct mem_cast_types : public etl::mem_cast::size, + etl::largest::alignment> + { + }; #endif } diff --git a/test/etl_profile.h b/test/etl_profile.h index 1c24412d..c1652ae3 100644 --- a/test/etl_profile.h +++ b/test/etl_profile.h @@ -80,20 +80,23 @@ SOFTWARE. //#define ETL_NO_STL -//#define ETL_FUNCTION_FORCE_CPP03 -//#define ETL_PRIORITY_QUEUE_FORCE_CPP03 -//#define ETL_QUEUE_ATOMIC_FORCE_CPP03 -//#define ETL_VARIANT_FORCE_CPP03 -//#define ETL_VECTOR_FORCE_CPP03 -//#define ETL_QUEUE_FORCE_CPP03 -//#define ETL_QUEUE_MPMC_MUTEX_FORCE_CPP03 -//#define ETL_QUEUE_ISR_FORCE_CPP03 -//#define ETL_QUEUE_LOCKED_FORCE_CPP03 -//#define ETL_OPTIONAL_FORCE_CPP03 -//#define ETL_LARGEST_TYPE_FORCE_CPP03 -//#define ETL_TYPE_SELECT_FORCE_CPP03 -//#define ETL_UNINITIALIZED_BUFFER_FORCE_CPP03 -//#define ETL_CRC_FORCE_CPP03 +#if defined(ETL_FORCE_TEST_CPP03) + #define ETL_FUNCTION_FORCE_CPP03 + #define ETL_PRIORITY_QUEUE_FORCE_CPP03 + #define ETL_QUEUE_ATOMIC_FORCE_CPP03 + #define ETL_VARIANT_FORCE_CPP03 + #define ETL_VECTOR_FORCE_CPP03 + #define ETL_QUEUE_FORCE_CPP03 + #define ETL_QUEUE_MPMC_MUTEX_FORCE_CPP03 + #define ETL_QUEUE_ISR_FORCE_CPP03 + #define ETL_QUEUE_LOCKED_FORCE_CPP03 + #define ETL_OPTIONAL_FORCE_CPP03 + #define ETL_LARGEST_TYPE_FORCE_CPP03 + #define ETL_TYPE_SELECT_FORCE_CPP03 + #define ETL_UNINITIALIZED_BUFFER_FORCE_CPP03 + #define ETL_CRC_FORCE_CPP03 + #define ETL_MEM_CAST_FORCE_CPP03 +#endif #if defined(ETL_NO_STL) #define ETL_TIMER_SEMAPHORE_TYPE uint32_t From a2aa6b26c310071f62f929d55698f3031f430f9a Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 3 Jun 2021 11:44:38 +0100 Subject: [PATCH 08/20] Changed comments --- include/etl/mem_cast.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/etl/mem_cast.h b/include/etl/mem_cast.h index 2f156268..4d05b9a6 100644 --- a/include/etl/mem_cast.h +++ b/include/etl/mem_cast.h @@ -131,7 +131,7 @@ namespace etl } //*********************************** - /// Assign from parameters + /// Assign from value //*********************************** template void assign(const T& value) @@ -142,7 +142,7 @@ namespace etl } //*********************************** - /// Assign from parameters at offset + /// Assign from value at offset //*********************************** template void assign_at_offset(size_t offset, const T& value) @@ -155,7 +155,7 @@ namespace etl } //*********************************** - /// Assign from parameters at offset + /// Assign from value at offset //*********************************** template void assign_at_offset(const T& value) @@ -375,7 +375,7 @@ namespace etl } //*********************************** - /// Assign from parameters + /// Assign from value //*********************************** template void assign(const T& value) @@ -388,7 +388,7 @@ namespace etl } //*********************************** - /// Assign from parameters at offset + /// Assign from value at offset //*********************************** template void assign_at_offset(size_t offset, const T& value) @@ -402,7 +402,7 @@ namespace etl } //*********************************** - /// Assign from parameters at offset + /// Assign from value at offset //*********************************** template void assign_at_offset(const T& value) From 2b2a542aa1b73ec1b56fb9cfac5e586dd3aaf23b Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Thu, 3 Jun 2021 20:45:36 +0100 Subject: [PATCH 09/20] Added more static asserts for alignment --- include/etl/mem_cast.h | 56 ++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/include/etl/mem_cast.h b/include/etl/mem_cast.h index 4d05b9a6..1cc5ee0f 100644 --- a/include/etl/mem_cast.h +++ b/include/etl/mem_cast.h @@ -110,6 +110,8 @@ namespace etl static ETL_CONSTANT size_t Size = Size_; static ETL_CONSTANT size_t Alignment = Alignment_; + ETL_STATIC_ASSERT(etl::is_power_of_2::value, "Alignment must be a power of 2"); + //*********************************** /// Default constructor //*********************************** @@ -125,10 +127,26 @@ namespace etl mem_cast(const mem_cast& other) { ETL_STATIC_ASSERT(Size >= Other_Size, "Other size is too large"); - ETL_STATIC_ASSERT(Alignment >= Other_Alignment, "Other alignment incompatible"); + ETL_STATIC_ASSERT(Alignment >= Other_Alignment, "Other alignment is incompatible"); + ETL_STATIC_ASSERT(etl::is_power_of_2::value, "Other alignment must be a power of 2"); memcpy(buffer, other.buffer, Size_); } + + //*********************************** + /// Assignment operator + //*********************************** + template + mem_cast& operator =(const mem_cast& rhs) + { + ETL_STATIC_ASSERT(Size >= Other_Size, "RHS size is too large"); + ETL_STATIC_ASSERT(Alignment >= Other_Alignment, "RHS alignment is incompatible"); + ETL_STATIC_ASSERT(etl::is_power_of_2::value, "Other alignment must be a power of 2"); + + memcpy(buffer, rhs.buffer, Size_); + + return *this; + } //*********************************** /// Assign from value @@ -286,20 +304,6 @@ namespace etl return *static_cast(p); } - //*********************************** - /// Assignment operator - //*********************************** - template - mem_cast& operator =(const mem_cast& rhs) - { - ETL_STATIC_ASSERT(Size >= Other_Size, "RHS size is too large"); - ETL_STATIC_ASSERT(Alignment >= Other_Alignment, "RHS alignment incompatible"); - - memcpy(buffer, rhs.buffer, Size_); - - return *this; - } - //*********************************** /// Get the size of the buffer //*********************************** @@ -374,6 +378,17 @@ namespace etl { } + //*********************************** + /// Assignment operator + //*********************************** + mem_cast_ptr& operator =(const mem_cast_ptr& rhs) + { + pbuffer = rhs.pbuffer; + buffer_size = rhs.buffer_size; + + return *this; + } + //*********************************** /// Assign from value //*********************************** @@ -540,17 +555,6 @@ namespace etl return *reinterpret_cast(p); } - //*********************************** - /// Assignment operator - //*********************************** - mem_cast_ptr& operator =(const mem_cast_ptr& rhs) - { - pbuffer = rhs.pbuffer; - buffer_size = rhs.buffer_size; - - return *this; - } - //*********************************** /// Get the size of the buffer //*********************************** From f5c7897ea20bc9ecfe78bb35f58897d162f81550 Mon Sep 17 00:00:00 2001 From: Jonathan <2489823+jtlenzz@users.noreply.github.com> Date: Thu, 10 Jun 2021 04:50:55 -0400 Subject: [PATCH 10/20] Change debounce state tables to be defined as constant. (#386) Currently these state tables are being defined in the data section of RAM. As these tables are unchanged, this change allows them to be placed in the text section instead. As they are function local objects, they also get lazy initialized causing references to the dynamic shared object which are unnecessary. --- include/etl/debounce.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/etl/debounce.h b/include/etl/debounce.h index 21981236..b3787ce5 100644 --- a/include/etl/debounce.h +++ b/include/etl/debounce.h @@ -132,7 +132,7 @@ namespace etl //************************************************************************* /// Gets the next state based on the inputs. //************************************************************************* - void get_next(bool sample, bool condition_set, bool condition_clear, uint_least8_t state_table[][2]) + void get_next(bool sample, bool condition_set, bool condition_clear, const uint_least8_t state_table[][2]) { int index1 = ((flags & STATE) * 2) + (sample ? 1 : 0); int index2 = (sample ? (condition_set ? 0 : 1) : (condition_clear ? 0 : 1)); @@ -182,7 +182,7 @@ namespace etl //************************************************************************* void set_state(bool sample, bool condition_set, bool condition_clear) { - static uint_least8_t state_table[4][2] = + static ETL_CONSTANT uint_least8_t state_table[4][2] = { /* OFF 0 */{ debounce_base::OFF, debounce_base::OFF }, /* OFF 1 */{ debounce_base::ON, debounce_base::OFF }, @@ -260,7 +260,7 @@ namespace etl //************************************************************************* void set_state(bool sample, bool condition_set, bool condition_clear) { - static uint_least8_t state_table[6][2] = + static ETL_CONSTANT uint_least8_t state_table[6][2] = { /* OFF 0 */{ debounce_base::OFF, debounce_base::OFF }, /* OFF 1 */{ debounce_base::ON, debounce_base::OFF }, @@ -347,7 +347,7 @@ namespace etl //************************************************************************* void set_state(bool sample, bool condition_set, bool condition_clear) { - static uint_least8_t state_table[8][2] = + static ETL_CONSTANT uint_least8_t state_table[8][2] = { /* OFF 0 */{ debounce_base::OFF, debounce_base::OFF }, /* OFF 1 */{ debounce_base::ON, debounce_base::OFF }, From 72128564243242351db7443405e91801e8ba9ebe Mon Sep 17 00:00:00 2001 From: Jonathan <2489823+jtlenzz@users.noreply.github.com> Date: Thu, 10 Jun 2021 04:50:55 -0400 Subject: [PATCH 11/20] Change debounce state tables to be defined as constant. (#386) Currently these state tables are being defined in the data section of RAM. As these tables are unchanged, this change allows them to be placed in the text section instead. As they are function local objects, they also get lazy initialized causing references to the dynamic shared object which are unnecessary. --- include/etl/debounce.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/etl/debounce.h b/include/etl/debounce.h index 21981236..b3787ce5 100644 --- a/include/etl/debounce.h +++ b/include/etl/debounce.h @@ -132,7 +132,7 @@ namespace etl //************************************************************************* /// Gets the next state based on the inputs. //************************************************************************* - void get_next(bool sample, bool condition_set, bool condition_clear, uint_least8_t state_table[][2]) + void get_next(bool sample, bool condition_set, bool condition_clear, const uint_least8_t state_table[][2]) { int index1 = ((flags & STATE) * 2) + (sample ? 1 : 0); int index2 = (sample ? (condition_set ? 0 : 1) : (condition_clear ? 0 : 1)); @@ -182,7 +182,7 @@ namespace etl //************************************************************************* void set_state(bool sample, bool condition_set, bool condition_clear) { - static uint_least8_t state_table[4][2] = + static ETL_CONSTANT uint_least8_t state_table[4][2] = { /* OFF 0 */{ debounce_base::OFF, debounce_base::OFF }, /* OFF 1 */{ debounce_base::ON, debounce_base::OFF }, @@ -260,7 +260,7 @@ namespace etl //************************************************************************* void set_state(bool sample, bool condition_set, bool condition_clear) { - static uint_least8_t state_table[6][2] = + static ETL_CONSTANT uint_least8_t state_table[6][2] = { /* OFF 0 */{ debounce_base::OFF, debounce_base::OFF }, /* OFF 1 */{ debounce_base::ON, debounce_base::OFF }, @@ -347,7 +347,7 @@ namespace etl //************************************************************************* void set_state(bool sample, bool condition_set, bool condition_clear) { - static uint_least8_t state_table[8][2] = + static ETL_CONSTANT uint_least8_t state_table[8][2] = { /* OFF 0 */{ debounce_base::OFF, debounce_base::OFF }, /* OFF 1 */{ debounce_base::ON, debounce_base::OFF }, From fb54f23e5d1b4b1569eca09aaaa92de5fce6c81f Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 12 Jun 2021 11:43:32 +0100 Subject: [PATCH 12/20] Latest updates --- include/etl/mem_cast.h | 45 +++----------------------------------- test/test_mem_cast.cpp | 2 ++ test/test_mem_cast_ptr.cpp | 20 ----------------- 3 files changed, 5 insertions(+), 62 deletions(-) diff --git a/include/etl/mem_cast.h b/include/etl/mem_cast.h index 1cc5ee0f..a10905da 100644 --- a/include/etl/mem_cast.h +++ b/include/etl/mem_cast.h @@ -60,19 +60,6 @@ namespace etl } }; - //*************************************************************************** - /// The exception thrown when the buffer pointer alignment is not compatible. - //*************************************************************************** - class mem_cast_alignment_exception : public etl::mem_cast_exception - { - public: - - mem_cast_alignment_exception(string_type file_name_, numeric_type line_number_) - : mem_cast_exception(ETL_ERROR_TEXT("mem_cast:alignment", ETL_MEM_CAST_FILE_ID"A"), file_name_, line_number_) - { - } - }; - //*************************************************************************** /// The exception thrown when the type size is too large. //*************************************************************************** @@ -81,7 +68,7 @@ namespace etl public: mem_cast_size_exception(string_type file_name_, numeric_type line_number_) - : mem_cast_exception(ETL_ERROR_TEXT("mem_cast:size", ETL_MEM_CAST_FILE_ID"B"), file_name_, line_number_) + : mem_cast_exception(ETL_ERROR_TEXT("mem_cast:size", ETL_MEM_CAST_FILE_ID"A"), file_name_, line_number_) { } }; @@ -94,7 +81,7 @@ namespace etl public: mem_cast_nullptr_exception(string_type file_name_, numeric_type line_number_) - : mem_cast_exception(ETL_ERROR_TEXT("mem_cast:null pointer", ETL_MEM_CAST_FILE_ID"C"), file_name_, line_number_) + : mem_cast_exception(ETL_ERROR_TEXT("mem_cast:null pointer", ETL_MEM_CAST_FILE_ID"B"), file_name_, line_number_) { } }; @@ -110,7 +97,7 @@ namespace etl static ETL_CONSTANT size_t Size = Size_; static ETL_CONSTANT size_t Alignment = Alignment_; - ETL_STATIC_ASSERT(etl::is_power_of_2::value, "Alignment must be a power of 2"); + ETL_STATIC_ASSERT((Alignment == 1) || etl::is_power_of_2::value, "Alignment must be a power of 2"); //*********************************** /// Default constructor @@ -127,8 +114,6 @@ namespace etl mem_cast(const mem_cast& other) { ETL_STATIC_ASSERT(Size >= Other_Size, "Other size is too large"); - ETL_STATIC_ASSERT(Alignment >= Other_Alignment, "Other alignment is incompatible"); - ETL_STATIC_ASSERT(etl::is_power_of_2::value, "Other alignment must be a power of 2"); memcpy(buffer, other.buffer, Size_); } @@ -140,8 +125,6 @@ namespace etl mem_cast& operator =(const mem_cast& rhs) { ETL_STATIC_ASSERT(Size >= Other_Size, "RHS size is too large"); - ETL_STATIC_ASSERT(Alignment >= Other_Alignment, "RHS alignment is incompatible"); - ETL_STATIC_ASSERT(etl::is_power_of_2::value, "Other alignment must be a power of 2"); memcpy(buffer, rhs.buffer, Size_); @@ -166,7 +149,6 @@ namespace etl void assign_at_offset(size_t offset, const T& value) { char* p = static_cast(buffer) + offset; - ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception)); ::new (p) T(value); @@ -179,7 +161,6 @@ namespace etl void assign_at_offset(const T& value) { char* p = static_cast(buffer) + Offset; - ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Type size is too large"); ::new (p) T(value); @@ -204,7 +185,6 @@ namespace etl void emplace_at_offset(size_t offset, TArgs... args) { char* p = static_cast(buffer) + offset; - ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception)); ::new (p) T(etl::forward(args)...); @@ -217,7 +197,6 @@ namespace etl void emplace_at_offset(TArgs... args) { char* p = static_cast(buffer) + Offset; - ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Type size is too large"); ::new (p) T(etl::forward(args)...); @@ -231,7 +210,6 @@ namespace etl ETL_NODISCARD T& ref() { ETL_STATIC_ASSERT(sizeof(T) <= Size, "Size of T is too large"); - ETL_STATIC_ASSERT(Alignment >= etl::alignment_of::value, "Alignment of T is incompatible"); return *static_cast(buffer); } @@ -243,7 +221,6 @@ namespace etl ETL_NODISCARD const T& ref() const { ETL_STATIC_ASSERT(sizeof(T) <= Size, "Size of T is too large"); - ETL_STATIC_ASSERT(Alignment >= etl::alignment_of::value, "Alignment of T is incompatible"); return *static_cast(buffer); } @@ -257,7 +234,6 @@ namespace etl ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception)); char* p = buffer + offset; - ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); return *static_cast(p); } @@ -271,7 +247,6 @@ namespace etl ETL_ASSERT(sizeof(T) <= (Size - offset), ETL_ERROR(etl::mem_cast_size_exception)); char* p = buffer + offset; - ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); return *static_cast(p); } @@ -285,7 +260,6 @@ namespace etl ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Size of T is too large"); char* p = buffer + Offset; - ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); return *static_cast(p); } @@ -299,7 +273,6 @@ namespace etl ETL_STATIC_ASSERT(sizeof(T) <= (Size - Offset), "Size of T is too large"); char* p = buffer + Offset; - ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); return *static_cast(p); } @@ -396,7 +369,6 @@ namespace etl void assign(const T& value) { ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); - ETL_ASSERT((reinterpret_cast(pbuffer) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception)); ::new (pbuffer) T(value); @@ -410,7 +382,6 @@ namespace etl { ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); char* p = pbuffer + offset; - ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); ETL_ASSERT(sizeof(T) <= (buffer_size - offset), ETL_ERROR(etl::mem_cast_size_exception)); ::new (p) T(value); @@ -424,7 +395,6 @@ namespace etl { ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); char* p = pbuffer + Offset; - ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception)); ::new (p) T(value); @@ -438,7 +408,6 @@ namespace etl void emplace(TArgs... args) { ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); - ETL_ASSERT((reinterpret_cast(pbuffer) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception)); ::new (pbuffer) T(etl::forward(args)...); @@ -452,7 +421,6 @@ namespace etl { ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); char* p = pbuffer + offset; - ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); ETL_ASSERT(sizeof(T) <= (buffer_size - offset), ETL_ERROR(etl::mem_cast_size_exception)); ::new (p) T(etl::forward(args)...); @@ -466,7 +434,6 @@ namespace etl { ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); char* p = pbuffer + Offset; - ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception)); ::new (p) T(etl::forward(args)...); @@ -480,7 +447,6 @@ namespace etl ETL_NODISCARD T& ref() { ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); - ETL_ASSERT((reinterpret_cast(pbuffer) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception)); return *reinterpret_cast(pbuffer); @@ -493,7 +459,6 @@ namespace etl ETL_NODISCARD const T& ref() const { ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); - ETL_ASSERT((reinterpret_cast(pbuffer) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::mem_cast_size_exception)); return *reinterpret_cast(pbuffer); @@ -507,7 +472,6 @@ namespace etl { ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); char* p = pbuffer + offset; - ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); ETL_ASSERT(sizeof(T) <= (buffer_size - offset), ETL_ERROR(etl::mem_cast_size_exception)); return *reinterpret_cast(p); @@ -521,7 +485,6 @@ namespace etl { ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); char* p = pbuffer + offset; - ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); ETL_ASSERT(sizeof(T) <= (buffer_size - offset), ETL_ERROR(etl::mem_cast_size_exception)); return *reinterpret_cast(p); @@ -535,7 +498,6 @@ namespace etl { ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); char* p = pbuffer + Offset; - ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception)); return *reinterpret_cast(p); @@ -549,7 +511,6 @@ namespace etl { ETL_ASSERT((pbuffer != ETL_NULLPTR), ETL_ERROR(etl::mem_cast_nullptr_exception)); char* p = pbuffer + Offset; - ETL_ASSERT((reinterpret_cast(p) % etl::alignment_of::value) == 0, ETL_ERROR(etl::mem_cast_alignment_exception)); ETL_ASSERT(sizeof(T) <= (buffer_size - Offset), ETL_ERROR(etl::mem_cast_size_exception)); return *reinterpret_cast(p); diff --git a/test/test_mem_cast.cpp b/test/test_mem_cast.cpp index 65e33da0..304be224 100644 --- a/test/test_mem_cast.cpp +++ b/test/test_mem_cast.cpp @@ -38,6 +38,7 @@ SOFTWARE. namespace { + #pragma pack(push,1) struct Data { Data() @@ -58,6 +59,7 @@ namespace double d; std::array a; }; + #pragma pack(pop) constexpr size_t Size = etl::largest::size; constexpr size_t Alignment = etl::largest::alignment; diff --git a/test/test_mem_cast_ptr.cpp b/test/test_mem_cast_ptr.cpp index aaf29033..582d9c7a 100644 --- a/test/test_mem_cast_ptr.cpp +++ b/test/test_mem_cast_ptr.cpp @@ -339,25 +339,5 @@ namespace CHECK_THROW(char c = memCast.ref(), etl::mem_cast_nullptr_exception); } - - //************************************************************************* - TEST(test_mem_cast_to_type_misaligned_buffer) - { - double d; - char* pbuffer = reinterpret_cast(&d); - MemCast memCast(pbuffer + 1); - - CHECK_THROW(double d = memCast.ref(), etl::mem_cast_alignment_exception); - } - - //************************************************************************* - TEST(test_const_mem_cast_to_type_misaligned_buffer) - { - double d; - char* pbuffer = reinterpret_cast(&d); - const MemCast memCast(pbuffer + 1); - - CHECK_THROW(double d = memCast.ref(), etl::mem_cast_alignment_exception); - } }; } From 0a7a131a4343f350d09f5b76de8d7097bd156a31 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Sat, 12 Jun 2021 11:48:27 +0100 Subject: [PATCH 13/20] Updated version numbers --- include/etl/version.h | 4 ++-- library.json | 2 +- library.properties | 2 +- meson.build | 2 +- support/Release notes.txt | 5 +++++ 5 files changed, 10 insertions(+), 5 deletions(-) diff --git a/include/etl/version.h b/include/etl/version.h index 720df68d..c8a2722a 100644 --- a/include/etl/version.h +++ b/include/etl/version.h @@ -38,8 +38,8 @@ SOFTWARE. ///\ingroup utilities #define ETL_VERSION_MAJOR 20 -#define ETL_VERSION_MINOR 10 -#define ETL_VERSION_PATCH 6 +#define ETL_VERSION_MINOR 11 +#define ETL_VERSION_PATCH 0 #define ETL_VERSION ETL_STRINGIFY(ETL_VERSION_MAJOR) "." ETL_STRINGIFY(ETL_VERSION_MINOR) "." ETL_STRINGIFY(ETL_VERSION_PATCH) #define ETL_VERSION_W ETL_STRINGIFY(ETL_VERSION_MAJOR) L"." ETL_STRINGIFY(ETL_VERSION_MINOR) L"." ETL_STRINGIFY(ETL_VERSION_PATCH) #define ETL_VERSION_U16 ETL_STRINGIFY(ETL_VERSION_MAJOR) u"." ETL_STRINGIFY(ETL_VERSION_MINOR) u"." ETL_STRINGIFY(ETL_VERSION_PATCH) diff --git a/library.json b/library.json index 9db55ab8..70f17042 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "ETL Embedded Template Library", - "version": "20.10.6", + "version": "20.11.0", "author s": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/library.properties b/library.properties index a5459cd4..4d2d0258 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library ETL -version=20.10.6 +version=20.11.0 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/meson.build b/meson.build index 5b87b504..450c0b79 100644 --- a/meson.build +++ b/meson.build @@ -8,7 +8,7 @@ project('PROJECT_NAME', 'cpp_std=c++17', 'build.cpp_std=c++17', ], meson_version: '>=0.54.0', - version: '20.10.6' + version: '20.11.0' ) ###################### diff --git a/support/Release notes.txt b/support/Release notes.txt index 95dfd39d..f44a0cb9 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,8 @@ +=============================================================================== +20.11.0 +Added etl::mem_cast, etl::mem_cast_ptr & etl::mem_cast_types for reinterpretion of memory blocks. +State tables in etl::debounce are now constexpr in C++11 or above. + =============================================================================== 20.10.6 Updated QueuedMessageRouter and QueuedFSM examples to use current message frameworks. From e4e61cfe69675a5eded4302095648bfccd4391da Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 14 Jun 2021 13:11:03 +0100 Subject: [PATCH 14/20] Fixed ambiguous function call for clang --- .github/workflows/clang.yml | 2 +- include/etl/mem_cast.h | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/clang.yml b/.github/workflows/clang.yml index 35b012c1..381a76d2 100644 --- a/.github/workflows/clang.yml +++ b/.github/workflows/clang.yml @@ -1,7 +1,7 @@ name: clang on: push: - branches: [ master ] + branches: [ master, feature/mem_cast ] pull_request: branches: [ master ] diff --git a/include/etl/mem_cast.h b/include/etl/mem_cast.h index a10905da..1dc30041 100644 --- a/include/etl/mem_cast.h +++ b/include/etl/mem_cast.h @@ -529,7 +529,9 @@ namespace etl //*********************************** ETL_NODISCARD size_t alignment() const { - const uintptr_t p = reinterpret_cast(pbuffer); + typedef typename etl::smallest_uint_for_bits::type type; + + const uintptr_t p = reinterpret_cast(pbuffer); return 1U << etl::count_trailing_zeros(p); } From f68624f90932d664d5d55579b59ca16faa40c342 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 14 Jun 2021 13:18:17 +0100 Subject: [PATCH 15/20] Fixed ambiguous function call for clang --- .github/workflows/clang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/clang.yml b/.github/workflows/clang.yml index 381a76d2..d9d55e8c 100644 --- a/.github/workflows/clang.yml +++ b/.github/workflows/clang.yml @@ -1,7 +1,7 @@ name: clang on: push: - branches: [ master, feature/mem_cast ] + branches: [ feature/mem_cast ] pull_request: branches: [ master ] From 1781be7702d8af7233772196cea0610331cbe5e1 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 14 Jun 2021 13:23:41 +0100 Subject: [PATCH 16/20] Fixed ambiguous function call for clang --- .github/workflows/clang.yml | 21 +++++++++++++++++++++ include/etl/mem_cast.h | 2 +- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/.github/workflows/clang.yml b/.github/workflows/clang.yml index d9d55e8c..e27e4701 100644 --- a/.github/workflows/clang.yml +++ b/.github/workflows/clang.yml @@ -27,6 +27,27 @@ jobs: - name: Run tests run: ./test/etl_tests + build-clang-10-linux: + name: Clang-10 Linux + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-20.04] + + steps: + - uses: actions/checkout@v2 + + - name: Build + run: | + export CC=clang-10 + export CXX=clang++-10 + cmake -D BUILD_TESTS=ON ./ + clang --version + make + + - name: Run tests + run: ./test/etl_tests + build-clang-9-linux-no-stl: name: Clang-9 Linux - No STL runs-on: ${{ matrix.os }} diff --git a/include/etl/mem_cast.h b/include/etl/mem_cast.h index 1dc30041..3388d4ac 100644 --- a/include/etl/mem_cast.h +++ b/include/etl/mem_cast.h @@ -531,7 +531,7 @@ namespace etl { typedef typename etl::smallest_uint_for_bits::type type; - const uintptr_t p = reinterpret_cast(pbuffer); + const type p = reinterpret_cast(pbuffer); return 1U << etl::count_trailing_zeros(p); } From 2c8f079c6057dc83f8691b49201eb5614ce713b9 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 14 Jun 2021 13:53:15 +0100 Subject: [PATCH 17/20] Fixed ambiguous function call for clang --- .github/workflows/clang.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/clang.yml b/.github/workflows/clang.yml index e27e4701..4ab31035 100644 --- a/.github/workflows/clang.yml +++ b/.github/workflows/clang.yml @@ -18,6 +18,8 @@ jobs: - name: Build run: | + sudo apt-get update + sudo apt-get install -y "clang-9" "lldb-9" "lld-9" "clang-format-9" export CC=clang-9 export CXX=clang++-9 cmake -D BUILD_TESTS=ON ./ From a287877ac985032dce280991f42afeb58cfe966c Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 14 Jun 2021 14:00:53 +0100 Subject: [PATCH 18/20] Fixed ambiguous function call for clang --- .github/workflows/clang.yml | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/.github/workflows/clang.yml b/.github/workflows/clang.yml index 4ab31035..144b506e 100644 --- a/.github/workflows/clang.yml +++ b/.github/workflows/clang.yml @@ -29,27 +29,6 @@ jobs: - name: Run tests run: ./test/etl_tests - build-clang-10-linux: - name: Clang-10 Linux - runs-on: ${{ matrix.os }} - strategy: - matrix: - os: [ubuntu-20.04] - - steps: - - uses: actions/checkout@v2 - - - name: Build - run: | - export CC=clang-10 - export CXX=clang++-10 - cmake -D BUILD_TESTS=ON ./ - clang --version - make - - - name: Run tests - run: ./test/etl_tests - build-clang-9-linux-no-stl: name: Clang-9 Linux - No STL runs-on: ${{ matrix.os }} From 6f0b0a98096ebb8c299dafdd9e5a51807ab6cb15 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 14 Jun 2021 14:31:55 +0100 Subject: [PATCH 19/20] Updated version numbers --- include/etl/version.h | 2 +- library.json | 2 +- library.properties | 2 +- meson.build | 2 +- support/Release notes.txt | 4 ++++ 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/include/etl/version.h b/include/etl/version.h index c8a2722a..61d898fe 100644 --- a/include/etl/version.h +++ b/include/etl/version.h @@ -39,7 +39,7 @@ SOFTWARE. #define ETL_VERSION_MAJOR 20 #define ETL_VERSION_MINOR 11 -#define ETL_VERSION_PATCH 0 +#define ETL_VERSION_PATCH 1 #define ETL_VERSION ETL_STRINGIFY(ETL_VERSION_MAJOR) "." ETL_STRINGIFY(ETL_VERSION_MINOR) "." ETL_STRINGIFY(ETL_VERSION_PATCH) #define ETL_VERSION_W ETL_STRINGIFY(ETL_VERSION_MAJOR) L"." ETL_STRINGIFY(ETL_VERSION_MINOR) L"." ETL_STRINGIFY(ETL_VERSION_PATCH) #define ETL_VERSION_U16 ETL_STRINGIFY(ETL_VERSION_MAJOR) u"." ETL_STRINGIFY(ETL_VERSION_MINOR) u"." ETL_STRINGIFY(ETL_VERSION_PATCH) diff --git a/library.json b/library.json index 70f17042..11db9207 100644 --- a/library.json +++ b/library.json @@ -1,6 +1,6 @@ { "name": "ETL Embedded Template Library", - "version": "20.11.0", + "version": "20.11.1", "author s": { "name": "John Wellbelove", "email": "john.wellbelove@etlcpp.com" diff --git a/library.properties b/library.properties index 4d2d0258..aeaf6fa4 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Embedded Template Library ETL -version=20.11.0 +version=20.11.1 author= John Wellbelove maintainer=John Wellbelove license=MIT diff --git a/meson.build b/meson.build index 450c0b79..f870b9bc 100644 --- a/meson.build +++ b/meson.build @@ -8,7 +8,7 @@ project('PROJECT_NAME', 'cpp_std=c++17', 'build.cpp_std=c++17', ], meson_version: '>=0.54.0', - version: '20.11.0' + version: '20.11.1' ) ###################### diff --git a/support/Release notes.txt b/support/Release notes.txt index f44a0cb9..4e457139 100644 --- a/support/Release notes.txt +++ b/support/Release notes.txt @@ -1,3 +1,7 @@ +=============================================================================== +20.11.1 +Fixed ambiguous function call in etl::mem_cast for clang. + =============================================================================== 20.11.0 Added etl::mem_cast, etl::mem_cast_ptr & etl::mem_cast_types for reinterpretion of memory blocks. From 5bd7222e926673f4f2aa3f52b36935050ec61a53 Mon Sep 17 00:00:00 2001 From: John Wellbelove Date: Mon, 14 Jun 2021 17:31:33 +0100 Subject: [PATCH 20/20] Updated version numbers --- .github/workflows/clang.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/clang.yml b/.github/workflows/clang.yml index 144b506e..ea07e377 100644 --- a/.github/workflows/clang.yml +++ b/.github/workflows/clang.yml @@ -1,7 +1,7 @@ name: clang on: push: - branches: [ feature/mem_cast ] + branches: [ master ] pull_request: branches: [ master ]