diff --git a/.gitignore b/.gitignore index 6ca19e11..2eeec517 100644 --- a/.gitignore +++ b/.gitignore @@ -391,3 +391,4 @@ 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 0583d17a..232fc0b3 100644 --- a/include/etl/platform.h +++ b/include/etl/platform.h @@ -463,15 +463,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 d86a0c9f..2ed98c35 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,7 @@ namespace etl return value; } + //************************************************************************* /// Unaligned copy //************************************************************************* diff --git a/test/test_utility.cpp b/test/test_utility.cpp index 5d7e2809..e049198d 100644 --- a/test/test_utility.cpp +++ b/test/test_utility.cpp @@ -730,7 +730,7 @@ namespace uint32_t c = 0x87654321; }; - struct ETL_PACKED Packed + ETL_PACKED_STRUCT(Packed) { uint32_t a = 0x12345678; uint8_t b = 0x9A;