diff --git a/.gitignore b/.gitignore index 8f313ddb..2eeec517 100644 --- a/.gitignore +++ b/.gitignore @@ -388,3 +388,7 @@ support/time remaining test.xlsx test/vs2022/Debug MSVC C++20 - Force C++03 test/vs2022/Release MSVC C++20 - No STL - Optimised -O2 - Sanitiser test/test_file_list.txt +examples/QueuedMessageRouter/vs2022/.vs/QueuedMessageRouter/CopilotIndices +examples/QueuedMessageRouter/vs2022/.vs/QueuedMessageRouter/FileContentIndex +examples/QueuedMessageRouter/vs2022/.vs/QueuedMessageRouter/v17 +test/etl_error_handler/assert_function/build-make diff --git a/include/etl/platform.h b/include/etl/platform.h index d6975bc1..89d05d1b 100644 --- a/include/etl/platform.h +++ b/include/etl/platform.h @@ -457,15 +457,19 @@ SOFTWARE. //************************************* // Determine if the ETL should use __attribute__((packed). #if defined(ETL_COMPILER_CLANG) || defined(ETL_COMPILER_GCC) || defined(ETL_COMPILER_INTEL) || defined(ETL_COMPILER_ARM6) - #define ETL_PACKED __attribute__((packed)) + #define ETL_PACKED_CLASS(class_type) class __attribute__((packed)) class_type + #define ETL_PACKED_STRUCT(struct_type) struct __attribute__((packed)) struct_type #define ETL_END_PACKED #define ETL_HAS_PACKED 1 #elif defined(ETL_COMPILER_MICROSOFT) - #define ETL_PACKED __pragma(pack(push, 1)) + #define ETL_PACKED_CLASS(class_type) __pragma(pack(push, 1)) class class_type + #define ETL_PACKED_STRUCT(struct_type) __pragma(pack(push, 1)) struct struct_type + #define ETL_PACKED #define ETL_END_PACKED __pragma(pack(pop)) #define ETL_HAS_PACKED 1 #else - #define ETL_PACKED + #define ETL_PACKED_CLASS(class_type) class class_type + #define ETL_PACKED_STRUCT(struct_type) struct struct_type #define ETL_END_PACKED #define ETL_HAS_PACKED 0 #endif diff --git a/include/etl/unaligned_type.h b/include/etl/unaligned_type.h index 1c406ba3..7de83aa3 100644 --- a/include/etl/unaligned_type.h +++ b/include/etl/unaligned_type.h @@ -41,19 +41,48 @@ SOFTWARE. #include "iterator.h" #include "algorithm.h" #include "bit.h" +#include "array.h" +#include "exception.h" +#include "file_error_numbers.h" + +#include #include namespace etl { + struct unaligned_type_exception : public etl::exception + { + public: + + unaligned_type_exception(string_type reason_, string_type file_name_, numeric_type line_number_) + : exception(reason_, file_name_, line_number_) + { + } + }; + + //*************************************************************************** + /// Buffer size exception. + //*************************************************************************** + class unaligned_type_buffer_size : public unaligned_type_exception + { + public: + + unaligned_type_buffer_size(string_type file_name_, numeric_type line_number_) + : unaligned_type_exception(ETL_ERROR_TEXT("unaligned_type:buffer size", ETL_UNALIGNED_TYPE_FILE_ID"A"), file_name_, line_number_) + { + } + }; + namespace private_unaligned_type { //************************************************************************* /// unaligned_type_common /// Contains all functionality that doesn't require the type. + /// ETL_PACKED ensures that GCC does not complain when used in a packed object. //************************************************************************* template - class ETL_PACKED unaligned_type_common + ETL_PACKED_CLASS(unaligned_type_common) { public: @@ -227,7 +256,7 @@ namespace etl ///\tparam Endian The endianness of the arithmetic type. //************************************************************************* template - class ETL_PACKED unaligned_type : public private_unaligned_type::unaligned_type_common + ETL_PACKED_CLASS(unaligned_type) : public private_unaligned_type::unaligned_type_common { public: @@ -243,8 +272,8 @@ namespace etl typedef typename private_unaligned_type::unaligned_type_common::reverse_iterator reverse_iterator; typedef typename private_unaligned_type::unaligned_type_common::const_reverse_iterator const_reverse_iterator; - static ETL_CONSTANT int Endian = Endian_; - static ETL_CONSTANT size_t Size = private_unaligned_type::unaligned_type_common::Size; + static ETL_CONSTANT int Endian = Endian_; + static ETL_CONSTANT size_t Size = private_unaligned_type::unaligned_type_common::Size; //************************************************************************* /// Default constructor @@ -261,6 +290,24 @@ namespace etl unaligned_copy::copy(value, this->storage); } + //************************************************************************* + /// Construct from an address. + //************************************************************************* + ETL_CONSTEXPR14 unaligned_type(const void* address) + { + etl::copy_n(reinterpret_cast(address), sizeof(T), this->storage); + } + + //************************************************************************* + /// Construct from an address and size. + //************************************************************************* + ETL_CONSTEXPR14 unaligned_type(const void* address, size_t buffer_size) + { + ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::unaligned_type_buffer_size)); + + etl::copy_n(reinterpret_cast(address), sizeof(T), this->storage); + } + //************************************************************************* /// Copy constructor //************************************************************************* @@ -315,6 +362,56 @@ namespace etl return value; } + // For run time pointer + static unaligned_type& at_address(void* address) + { + //auto p = (::new(address) unaligned_type()); + + //return *p; + + return *reinterpret_cast*>(address); + } + + // For const run time pointer + static const unaligned_type& at_address(const void* address) + { + return *reinterpret_cast*>(address); + } + + // For run time pointer and size + static unaligned_type& at_address(void* address, size_t buffer_size) + { + ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::unaligned_type_buffer_size)); + + return *reinterpret_cast*>(address); + } + + // For const run time pointer and size + static const unaligned_type& at_address(const void* address, size_t buffer_size) + { + ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::unaligned_type_buffer_size)); + + return *reinterpret_cast*>(address); + } + + // For run time pointer and compile time size + template + static unaligned_type& at_address(void* address) + { + ETL_STATIC_ASSERT(sizeof(T) <= Size, "Buffer size to small for type"); + + return *reinterpret_cast*>(address); + } + + // For const run time pointer and compile time size + template + static unaligned_type& at_address(const void* address) + { + ETL_STATIC_ASSERT(sizeof(T) <= Size, "Buffer size to small for type"); + + return *reinterpret_cast*>(address); + } + //************************************************************************* /// Unaligned copy //************************************************************************* diff --git a/test/test_utility.cpp b/test/test_utility.cpp index 5b3ce658..3c35fcd3 100644 --- a/test/test_utility.cpp +++ b/test/test_utility.cpp @@ -678,7 +678,7 @@ namespace uint32_t c = 0x87654321; }; - struct ETL_PACKED Packed + ETL_PACKED_STRUCT(Packed) { uint32_t a = 0x12345678; uint8_t b = 0x9A;