diff --git a/include/etl/file_error_numbers.h b/include/etl/file_error_numbers.h index a866ce417..e28c8d055 100644 --- a/include/etl/file_error_numbers.h +++ b/include/etl/file_error_numbers.h @@ -103,5 +103,6 @@ SOFTWARE. #define ETL_EXPECTED_FILE_ID "70" #define ETL_ALIGNMENT_FILE_ID "71" #define ETL_BASE64_FILE_ID "72" +#define ETL_UNALIGNED_TYPE_FILE_ID "73" #endif diff --git a/include/etl/unaligned_type.h b/include/etl/unaligned_type.h index 9b4ae6629..be9e69151 100644 --- a/include/etl/unaligned_type.h +++ b/include/etl/unaligned_type.h @@ -37,7 +37,10 @@ SOFTWARE. #include "platform.h" #include "type_traits.h" +#include "nullptr.h" #include "endianness.h" +#include "error_handler.h" +#include "exception.h" #include "iterator.h" #include "algorithm.h" #include "bit.h" @@ -46,24 +49,55 @@ SOFTWARE. namespace etl { + //*************************************************************************** + /// The base class for unaligned_type exceptions. + ///\ingroup pool + //*************************************************************************** + 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_) + { + } + }; + + //*************************************************************************** + /// The base class for unaligned_type buffer overflow. + ///\ingroup pool + //*************************************************************************** + 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. + /// Implements CRTP for StorageContainer //************************************************************************* - template + template class unaligned_type_common { public: static ETL_CONSTANT size_t Size = Size_; - typedef unsigned char storage_type; - typedef storage_type* pointer; - typedef const storage_type* const_pointer; - typedef storage_type* iterator; - typedef const storage_type* const_iterator; + typedef StorageContainer_ storage_container_type; + typedef unsigned char storage_value_type; + typedef storage_value_type* pointer; + typedef const storage_value_type* const_pointer; + typedef storage_value_type* iterator; + typedef const storage_value_type* const_iterator; typedef etl::reverse_iterator reverse_iterator; typedef etl::reverse_iterator const_reverse_iterator; @@ -71,7 +105,6 @@ namespace etl /// Default constructor //************************************************************************* ETL_CONSTEXPR unaligned_type_common() - : storage() { } @@ -88,7 +121,7 @@ namespace etl //************************************************************************* pointer data() { - return storage; + return static_cast(this)->data(); } //************************************************************************* @@ -96,7 +129,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR const_pointer data() const { - return storage; + return static_cast(this)->data(); } //************************************************************************* @@ -104,7 +137,7 @@ namespace etl //************************************************************************* iterator begin() { - return iterator(storage); + return iterator(static_cast(this)->data()); } //************************************************************************* @@ -112,7 +145,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR const_iterator begin() const { - return const_iterator(storage); + return const_iterator(static_cast(this)->data()); } //************************************************************************* @@ -120,7 +153,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR const_iterator cbegin() const { - return const_iterator(storage); + return const_iterator(static_cast(this)->data()); } //************************************************************************* @@ -128,7 +161,7 @@ namespace etl //************************************************************************* reverse_iterator rbegin() { - return reverse_iterator(storage + Size); + return reverse_iterator(static_cast(this)->data() + Size); } //************************************************************************* @@ -136,7 +169,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 const_reverse_iterator rbegin() const { - return const_reverse_iterator(storage + Size); + return const_reverse_iterator(static_cast(this)->data() + Size); } //************************************************************************* @@ -144,7 +177,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 const_reverse_iterator crbegin() const { - return const_reverse_iterator(storage + Size); + return const_reverse_iterator(static_cast(this)->data() + Size); } //************************************************************************* @@ -152,7 +185,7 @@ namespace etl //************************************************************************* iterator end() { - return iterator(storage + Size); + return iterator(static_cast(this)->data() + Size); } //************************************************************************* @@ -160,7 +193,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR const_iterator end() const { - return const_iterator(storage + Size); + return const_iterator(static_cast(this)->data() + Size); } //************************************************************************* @@ -168,7 +201,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR const_iterator cend() const { - return const_iterator(storage + Size); + return const_iterator(static_cast(this)->data() + Size); } //************************************************************************* @@ -176,7 +209,7 @@ namespace etl //************************************************************************* reverse_iterator rend() { - return reverse_iterator(storage); + return reverse_iterator(static_cast(this)->data()); } //************************************************************************* @@ -184,7 +217,7 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 const_reverse_iterator rend() const { - return const_reverse_iterator(storage); + return const_reverse_iterator(static_cast(this)->data()); } //************************************************************************* @@ -192,90 +225,74 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 const_reverse_iterator crend() const { - return const_reverse_iterator(storage); + return const_reverse_iterator(static_cast(this)->data()); } //************************************************************************* /// Index operator. //************************************************************************* - storage_type& operator[](int i) + storage_value_type& operator[](int i) { - return storage[i]; + return static_cast(this)[i]; } //************************************************************************* /// Const index operator. //************************************************************************* - ETL_CONSTEXPR const storage_type& operator[](int i) const + ETL_CONSTEXPR const storage_value_type& operator[](int i) const { - return storage[i]; + return static_cast(this)[i]; } - - protected: - - unsigned char storage[Size]; }; - template - ETL_CONSTANT size_t unaligned_type_common::Size; + template + ETL_CONSTANT size_t unaligned_type_common::Size; } //************************************************************************* - /// unaligned_type + /// unaligned_type_base ///\brief Allows an arithmetic type to be stored at an unaligned address. ///\tparam T The arithmetic type. ///\tparam Endian The endianness of the arithmetic type. + ///\tparam StorageContainer Specialization for internal or external storage via CRTP //************************************************************************* - template - class unaligned_type : public private_unaligned_type::unaligned_type_common + template + class unaligned_type_base + : public private_unaligned_type::unaligned_type_common { public: ETL_STATIC_ASSERT(etl::is_integral::value || etl::is_floating_point::value, "Unaligned type must be integral or floating point"); - typedef T value_type; + typedef T value_type; + typedef typename etl::remove_cv::type base_value_type; + typedef private_unaligned_type::unaligned_type_common base_type; + typedef StorageContainer storage_container_type; - typedef typename private_unaligned_type::unaligned_type_common::storage_type storage_type; - typedef typename private_unaligned_type::unaligned_type_common::pointer pointer; - typedef typename private_unaligned_type::unaligned_type_common::const_pointer const_pointer; - typedef typename private_unaligned_type::unaligned_type_common::iterator iterator; - typedef typename private_unaligned_type::unaligned_type_common::const_iterator const_iterator; - 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; + typedef typename base_type::storage_value_type storage_value_type; + typedef typename base_type::pointer pointer; + typedef typename base_type::const_pointer const_pointer; + typedef typename base_type::iterator iterator; + typedef typename base_type::const_iterator const_iterator; + typedef typename base_type::reverse_iterator reverse_iterator; + typedef typename base_type::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; - - //************************************************************************* - /// Default constructor - //************************************************************************* - ETL_CONSTEXPR unaligned_type() - { - } + static ETL_CONSTANT size_t Size = private_unaligned_type::unaligned_type_common::Size; //************************************************************************* - /// Construct from a value. - //************************************************************************* - ETL_CONSTEXPR14 unaligned_type(T value) - { - unaligned_copy::copy(value, this->storage); - } - + /// Default constructor. //************************************************************************* - /// Copy constructor - //************************************************************************* - template - ETL_CONSTEXPR14 unaligned_type(const unaligned_type& other) + ETL_CONSTEXPR unaligned_type_base() { - unaligned_copy::copy(other.data(), Endian_Other, this->storage); } //************************************************************************* /// Assignment operator //************************************************************************* - ETL_CONSTEXPR14 unaligned_type& operator =(T value) + ETL_CONSTEXPR14 unaligned_type_base& operator =(T value) { - unaligned_copy::copy(value, this->storage); + unaligned_copy::copy(value, static_cast(this)->data()); return *this; } @@ -283,10 +300,10 @@ namespace etl //************************************************************************* /// Assignment operator from other endianness. //************************************************************************* - template - ETL_CONSTEXPR14 unaligned_type& operator =(const unaligned_type& other) + template + ETL_CONSTEXPR14 unaligned_type_base& operator =(const unaligned_type_base& other) { - unaligned_copy::copy(other.data(), Endian_Other, this->storage); + unaligned_copy::copy(other.data(), Endian_Other, static_cast(this)->data()); return *this; } @@ -296,9 +313,9 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 operator T() const { - T value = T(); + base_value_type value = base_value_type(); - unaligned_copy::copy(this->storage, value); + unaligned_copy::copy(static_cast(this)->data(), value); return value; } @@ -308,9 +325,9 @@ namespace etl //************************************************************************* ETL_CONSTEXPR14 T value() const { - T value = T(); + base_value_type value = base_value_type(); - unaligned_copy::copy(this->storage, value); + unaligned_copy::copy(static_cast(this)->data(), value); return value; } @@ -331,11 +348,11 @@ namespace etl //******************************* static ETL_CONSTEXPR14 void copy(T value, pointer store) { - store[0] = static_cast(value); + store[0] = static_cast(value); } //******************************* - static ETL_CONSTEXPR14 void copy(const_pointer store, T& value) + static ETL_CONSTEXPR14 void copy(const_pointer store, base_value_type& value) { value = static_cast(store[0]); } @@ -359,18 +376,18 @@ namespace etl { if (Endian == etl::endianness::value()) { - store[0] = static_cast(value); - store[1] = static_cast(value >> (1U * CHAR_BIT)); + store[0] = static_cast(value); + store[1] = static_cast(value >> (1U * CHAR_BIT)); } else { - store[1] = static_cast(value); - store[0] = static_cast(value >> (1U * CHAR_BIT)); + store[1] = static_cast(value); + store[0] = static_cast(value >> (1U * CHAR_BIT)); } } //******************************* - static ETL_CONSTEXPR14 void copy(const_pointer store, T& value) + static ETL_CONSTEXPR14 void copy(const_pointer store, base_value_type& value) { if (Endian == etl::endianness::value()) { @@ -412,33 +429,33 @@ namespace etl { if (Endian == etl::endianness::value()) { - store[0] = static_cast(value); - store[1] = static_cast(value >> (1U * CHAR_BIT)); - store[2] = static_cast(value >> (2U * CHAR_BIT)); - store[3] = static_cast(value >> (3U * CHAR_BIT)); + store[0] = static_cast(value); + store[1] = static_cast(value >> (1U * CHAR_BIT)); + store[2] = static_cast(value >> (2U * CHAR_BIT)); + store[3] = static_cast(value >> (3U * CHAR_BIT)); } else { - store[3] = static_cast(value); - store[2] = static_cast(value >> (1U * CHAR_BIT)); - store[1] = static_cast(value >> (2U * CHAR_BIT)); - store[0] = static_cast(value >> (3U * CHAR_BIT)); + store[3] = static_cast(value); + store[2] = static_cast(value >> (1U * CHAR_BIT)); + store[1] = static_cast(value >> (2U * CHAR_BIT)); + store[0] = static_cast(value >> (3U * CHAR_BIT)); } } //******************************* - static ETL_CONSTEXPR14 void copy(const_pointer store, T& value) + static ETL_CONSTEXPR14 void copy(const_pointer store, base_value_type& value) { if (Endian == etl::endianness::value()) { - value = static_cast(static_cast(store[0])); + value = static_cast(static_cast(store[0])); value |= static_cast(static_cast(store[1])) << (1U * CHAR_BIT); value |= static_cast(static_cast(store[2])) << (2U * CHAR_BIT); value |= static_cast(static_cast(store[3])) << (3U * CHAR_BIT); } else { - value = static_cast(static_cast(store[3])); + value = static_cast(static_cast(store[3])); value |= static_cast(static_cast(store[2])) << (1U * CHAR_BIT); value |= static_cast(static_cast(store[1])) << (2U * CHAR_BIT); value |= static_cast(static_cast(store[0])) << (3U * CHAR_BIT); @@ -484,7 +501,7 @@ namespace etl } //******************************* - static void copy(const_pointer store, T& value) + static void copy(const_pointer store, base_value_type& value) { unsigned char temp[4U]; memcpy(temp, store, 4U); @@ -521,30 +538,30 @@ namespace etl { if (Endian == etl::endianness::value()) { - store[0] = static_cast(value); - store[1] = static_cast(value >> (1U * CHAR_BIT)); - store[2] = static_cast(value >> (2U * CHAR_BIT)); - store[3] = static_cast(value >> (3U * CHAR_BIT)); - store[4] = static_cast(value >> (4U * CHAR_BIT)); - store[5] = static_cast(value >> (5U * CHAR_BIT)); - store[6] = static_cast(value >> (6U * CHAR_BIT)); - store[7] = static_cast(value >> (7U * CHAR_BIT)); + store[0] = static_cast(value); + store[1] = static_cast(value >> (1U * CHAR_BIT)); + store[2] = static_cast(value >> (2U * CHAR_BIT)); + store[3] = static_cast(value >> (3U * CHAR_BIT)); + store[4] = static_cast(value >> (4U * CHAR_BIT)); + store[5] = static_cast(value >> (5U * CHAR_BIT)); + store[6] = static_cast(value >> (6U * CHAR_BIT)); + store[7] = static_cast(value >> (7U * CHAR_BIT)); } else { - store[7] = static_cast(value); - store[6] = static_cast(value >> (1U * CHAR_BIT)); - store[5] = static_cast(value >> (2U * CHAR_BIT)); - store[4] = static_cast(value >> (3U * CHAR_BIT)); - store[3] = static_cast(value >> (4U * CHAR_BIT)); - store[2] = static_cast(value >> (5U * CHAR_BIT)); - store[1] = static_cast(value >> (6U * CHAR_BIT)); - store[0] = static_cast(value >> (7U * CHAR_BIT)); + store[7] = static_cast(value); + store[6] = static_cast(value >> (1U * CHAR_BIT)); + store[5] = static_cast(value >> (2U * CHAR_BIT)); + store[4] = static_cast(value >> (3U * CHAR_BIT)); + store[3] = static_cast(value >> (4U * CHAR_BIT)); + store[2] = static_cast(value >> (5U * CHAR_BIT)); + store[1] = static_cast(value >> (6U * CHAR_BIT)); + store[0] = static_cast(value >> (7U * CHAR_BIT)); } } //******************************* - static ETL_CONSTEXPR14 void copy(const_pointer store, T& value) + static ETL_CONSTEXPR14 void copy(const_pointer store, base_value_type& value) { if (Endian == etl::endianness::value()) { @@ -617,7 +634,7 @@ namespace etl } //******************************* - static void copy(const_pointer store, T& value) + static void copy(const_pointer store, base_value_type& value) { unsigned char temp[8U]; memcpy(temp, store, 8U); @@ -661,7 +678,7 @@ namespace etl } //******************************* - static void copy(const_pointer store, T& value) + static void copy(const_pointer store, base_value_type& value) { unsigned char temp[12U]; memcpy(temp, store, 12U); @@ -705,7 +722,7 @@ namespace etl } //******************************* - static void copy(const_pointer store, T& value) + static void copy(const_pointer store, base_value_type& value) { unsigned char temp[16U]; memcpy(temp, store, 16U); @@ -731,12 +748,276 @@ namespace etl }; }; - template - ETL_CONSTANT int unaligned_type::Endian; + template + ETL_CONSTANT int unaligned_type_base::Endian; + template + ETL_CONSTANT size_t unaligned_type_base::Size; + + //************************************************************************* + /// unaligned_type + ///\brief Allows an arithmetic type to be stored at an unaligned address. + ///\tparam T The arithmetic type. + ///\tparam Endian The endianness of the arithmetic type. + //************************************************************************* + template + class unaligned_type + : public unaligned_type_base > + { + public: + + typedef unaligned_type_base > base_type; + typedef unsigned char storage_value_type; + + static ETL_CONSTANT size_t Size = sizeof(T); + + //************************************************************************* + /// Default constructor. + //************************************************************************* + ETL_CONSTEXPR unaligned_type() + : storage() + { + } + + //************************************************************************* + /// Construct from a value. + //************************************************************************* + ETL_CONSTEXPR14 unaligned_type(T value) + : storage() + { + base_type::template unaligned_copy::copy(value, storage); + } + + //************************************************************************* + /// Copy constructor. + //************************************************************************* + template + ETL_CONSTEXPR14 unaligned_type(const unaligned_type_base& other) + : storage() + { + base_type::template unaligned_copy::copy(other.data(), Endian_Other, storage); + } + + //************************************************************************* + /// Assignment from value. + //************************************************************************* + ETL_CONSTEXPR14 unaligned_type& operator =(T value) + { + base_type::template unaligned_copy::copy(value, storage); + + return *this; + } + + //************************************************************************* + /// Copy assignment. + //************************************************************************* + template + ETL_CONSTEXPR14 unaligned_type& operator =(const unaligned_type& other) + { + base_type::template unaligned_copy::copy(other.data(), Endian_Other, storage); + + return *this; + } + + //************************************************************************* + /// Const storage access. + //************************************************************************* + ETL_CONSTEXPR14 const storage_value_type* data() const + { + return storage; + } + + //************************************************************************* + /// Storage access. + //************************************************************************* + ETL_CONSTEXPR14 storage_value_type* data() + { + return storage; + } + + //************************************************************************* + /// Const index operator. + //************************************************************************* + ETL_CONSTEXPR const storage_value_type& operator[](int i) const + { + return storage[i]; + } + + //************************************************************************* + /// Index operator. + //************************************************************************* + storage_value_type& operator[](int i) + { + return storage[i]; + } + + private: + + storage_value_type storage[sizeof(T)]; + }; + template ETL_CONSTANT size_t unaligned_type::Size; + //************************************************************************* + /// Automatic const or non-const choice to support const and non-const storage + //************************************************************************* + template + struct storage_type + { + typedef typename etl::conditional::value, const unsigned char, unsigned char>::type type; + }; + + //************************************************************************* + /// unaligned_type + ///\brief Allows an arithmetic type to be stored at an unaligned external address. + ///\note No initialization of pointed-to data is being done. + /// This needs to be done by application code. + ///\tparam T The arithmetic type. + ///\tparam Endian The endianness of the arithmetic type. + //************************************************************************* + template + class unaligned_type_ext + : public unaligned_type_base > + { + public: + + typedef unaligned_type_base > base_type; + typedef typename storage_type::type storage_value_type; + + static ETL_CONSTANT size_t Size = sizeof(T); + + //************************************************************************* + /// Default constructor. + //************************************************************************* + ETL_CONSTEXPR unaligned_type_ext() + : storage(ETL_NULLPTR) + { + } + + //************************************************************************* + /// Constructor from const pointer. + //************************************************************************* + ETL_CONSTEXPR14 explicit unaligned_type_ext(const void* address, size_t buffer_size = sizeof(T)) + : storage(static_cast(address)) + { + ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::unaligned_type_buffer_size)); + } + + //************************************************************************* + /// Constructor from pointer. + //************************************************************************* + ETL_CONSTEXPR14 explicit unaligned_type_ext(void* address, size_t buffer_size = sizeof(T)) + : storage(static_cast(address)) + { + ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::unaligned_type_buffer_size)); + } + + //************************************************************************* + /// Assignment from value. + //************************************************************************* + ETL_CONSTEXPR14 unaligned_type_ext& operator =(T value) + { + base_type::template unaligned_copy::copy(value, storage); + + return *this; + } + + //************************************************************************* + /// Set external storage to new location with optional size limit of buffer. + ///\param address New external buffer address + ///\param buffer_size Maximum external buffer size. Guarded by static assert. + //************************************************************************* + void set_storage(void* address, size_t buffer_size = sizeof(T)) + { + ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::unaligned_type_buffer_size)); + + storage = static_cast(address); + } + + //************************************************************************* + /// Set external storage to new location with compile time size limit of buffer. + ///\tparam BufferSize Maximum external buffer size. Guarded by static assert. + ///\param address New external buffer address + //************************************************************************* + template + void set_storage(void* address) + { + ETL_STATIC_ASSERT(sizeof(T) <= BufferSize, "Buffer size to small for type"); + + storage = static_cast(address); + } + + //************************************************************************* + /// Set external storage to new location with optional size limit of buffer. + /// Overload for const buffer. + ///\param address New external buffer address + ///\param buffer_size Maximum external buffer size. Guarded by static assert. + //************************************************************************* + void set_storage(const void* address, size_t buffer_size = sizeof(T)) + { + ETL_ASSERT(sizeof(T) <= buffer_size, ETL_ERROR(etl::unaligned_type_buffer_size)); + + storage = static_cast(address); + } + + //************************************************************************* + /// Set external storage to new location with compile time size limit of buffer. + /// Overload for const buffer. + ///\tparam BufferSize Maximum external buffer size. Guarded by static assert. + ///\param address New external buffer address + //************************************************************************* + template + void set_storage(const void* address) + { + ETL_STATIC_ASSERT(sizeof(T) <= BufferSize, "Buffer size to small for type"); + + storage = static_cast(address); + } + + //************************************************************************* + /// Const storage access. + //************************************************************************* + ETL_CONSTEXPR14 const storage_value_type* data() const + { + return storage; + } + + //************************************************************************* + /// Storage access. + //************************************************************************* + ETL_CONSTEXPR14 storage_value_type* data() + { + return storage; + } + + //************************************************************************* + /// Const index operator. + //************************************************************************* + ETL_CONSTEXPR const storage_value_type& operator[](int i) const + { + return storage[i]; + } + + //************************************************************************* + /// Index operator. + //************************************************************************* + storage_value_type& operator[](int i) + { + return storage[i]; + } + + private: + + storage_value_type* storage; + }; + + template + ETL_CONSTANT size_t unaligned_type_ext::Size; + + //************************************************************************* + /// Convenience types with internal storage + //************************************************************************* #if ETL_HAS_CONSTEXPR_ENDIANNESS // Host order typedef unaligned_type host_char_t; @@ -860,6 +1141,250 @@ namespace etl template constexpr size_t unaligned_type_v = etl::unaligned_type::Size; #endif + + //************************************************************************* + /// Convenience types with external storage + //************************************************************************* +#if ETL_HAS_CONSTEXPR_ENDIANNESS + // Host order + typedef unaligned_type_ext host_char_t_ext; + typedef unaligned_type_ext host_schar_t_ext; + typedef unaligned_type_ext host_uchar_t_ext; + typedef unaligned_type_ext host_short_t_ext; + typedef unaligned_type_ext host_ushort_t_ext; + typedef unaligned_type_ext host_int_t_ext; + typedef unaligned_type_ext host_uint_t_ext; + typedef unaligned_type_ext host_long_t_ext; + typedef unaligned_type_ext host_ulong_t_ext; + typedef unaligned_type_ext host_long_long_t_ext; + typedef unaligned_type_ext host_ulong_long_t_ext; +#if ETL_USING_8BIT_TYPES + typedef unaligned_type_ext host_int8_t_ext; + typedef unaligned_type_ext host_uint8_t_ext; +#endif + typedef unaligned_type_ext host_int16_t_ext; + typedef unaligned_type_ext host_uint16_t_ext; + typedef unaligned_type_ext host_int32_t_ext; + typedef unaligned_type_ext host_uint32_t_ext; +#if ETL_USING_64BIT_TYPES + typedef unaligned_type_ext host_int64_t_ext; + typedef unaligned_type_ext host_uint64_t_ext; +#endif + typedef unaligned_type_ext host_float_t_ext; + typedef unaligned_type_ext host_double_t_ext; + typedef unaligned_type_ext host_long_double_t_ext; +#endif + + // Little Endian + typedef unaligned_type_ext le_char_t_ext; + typedef unaligned_type_ext le_schar_t_ext; + typedef unaligned_type_ext le_uchar_t_ext; + typedef unaligned_type_ext le_short_t_ext; + typedef unaligned_type_ext le_ushort_t_ext; + typedef unaligned_type_ext le_int_t_ext; + typedef unaligned_type_ext le_uint_t_ext; + typedef unaligned_type_ext le_long_t_ext; + typedef unaligned_type_ext le_ulong_t_ext; + typedef unaligned_type_ext le_long_long_t_ext; + typedef unaligned_type_ext le_ulong_long_t_ext; +#if ETL_USING_8BIT_TYPES + typedef unaligned_type_ext le_int8_t_ext; + typedef unaligned_type_ext le_uint8_t_ext; +#endif + typedef unaligned_type_ext le_int16_t_ext; + typedef unaligned_type_ext le_uint16_t_ext; + typedef unaligned_type_ext le_int32_t_ext; + typedef unaligned_type_ext le_uint32_t_ext; +#if ETL_USING_64BIT_TYPES + typedef unaligned_type_ext le_int64_t_ext; + typedef unaligned_type_ext le_uint64_t_ext; +#endif + typedef unaligned_type_ext le_float_t_ext; + typedef unaligned_type_ext le_double_t_ext; + typedef unaligned_type_ext le_long_double_t_ext; + + // Big Endian + typedef unaligned_type_ext be_char_t_ext; + typedef unaligned_type_ext be_schar_t_ext; + typedef unaligned_type_ext be_uchar_t_ext; + typedef unaligned_type_ext be_short_t_ext; + typedef unaligned_type_ext be_ushort_t_ext; + typedef unaligned_type_ext be_int_t_ext; + typedef unaligned_type_ext be_uint_t_ext; + typedef unaligned_type_ext be_long_t_ext; + typedef unaligned_type_ext be_ulong_t_ext; + typedef unaligned_type_ext be_long_long_t_ext; + typedef unaligned_type_ext be_ulong_long_t_ext; +#if ETL_USING_8BIT_TYPES + typedef unaligned_type_ext be_int8_t_ext; + typedef unaligned_type_ext be_uint8_t_ext; +#endif + typedef unaligned_type_ext be_int16_t_ext; + typedef unaligned_type_ext be_uint16_t_ext; + typedef unaligned_type_ext be_int32_t_ext; + typedef unaligned_type_ext be_uint32_t_ext; +#if ETL_USING_64BIT_TYPES + typedef unaligned_type_ext be_int64_t_ext; + typedef unaligned_type_ext be_uint64_t_ext; +#endif + typedef unaligned_type_ext be_float_t_ext; + typedef unaligned_type_ext be_double_t_ext; + typedef unaligned_type_ext be_long_double_t_ext; + + // Network Order + typedef be_char_t_ext net_char_t_ext; + typedef be_schar_t_ext net_schar_t_ext; + typedef be_uchar_t_ext net_uchar_t_ext; + typedef be_short_t_ext net_short_t_ext; + typedef be_ushort_t_ext net_ushort_t_ext; + typedef be_int_t_ext net_int_t_ext; + typedef be_uint_t_ext net_uint_t_ext; + typedef be_long_t_ext net_long_t_ext; + typedef be_ulong_t_ext net_ulong_t_ext; + typedef be_long_long_t_ext net_long_long_t_ext; + typedef be_ulong_long_t_ext net_ulong_long_t_ext; +#if ETL_USING_8BIT_TYPES + typedef be_int8_t_ext net_int8_t_ext; + typedef be_uint8_t_ext net_uint8_t_ext; +#endif + typedef be_int16_t_ext net_int16_t_ext; + typedef be_uint16_t_ext net_uint16_t_ext; + typedef be_int32_t_ext net_int32_t_ext; + typedef be_uint32_t_ext net_uint32_t_ext; +#if ETL_USING_64BIT_TYPES + typedef be_int64_t_ext net_int64_t_ext; + typedef be_uint64_t_ext net_uint64_t_ext; +#endif + typedef be_float_t_ext net_float_t_ext; + typedef be_double_t_ext net_double_t_ext; + typedef be_long_double_t_ext net_long_double_t_ext; + +#if ETL_USING_CPP11 + template + using unaligned_type_ext_t = typename etl::unaligned_type_ext::type; +#endif + +#if ETL_USING_CPP17 + template + constexpr size_t unaligned_type_ext_v = etl::unaligned_type_ext::Size; +#endif + + //************************************************************************* + /// Convenience const types with external storage + //************************************************************************* +#if ETL_HAS_CONSTEXPR_ENDIANNESS + // Host order + typedef unaligned_type_ext host_const_char_t_ext; + typedef unaligned_type_ext host_const_schar_t_ext; + typedef unaligned_type_ext host_const_uchar_t_ext; + typedef unaligned_type_ext host_const_short_t_ext; + typedef unaligned_type_ext host_const_ushort_t_ext; + typedef unaligned_type_ext host_const_int_t_ext; + typedef unaligned_type_ext host_const_uint_t_ext; + typedef unaligned_type_ext host_const_long_t_ext; + typedef unaligned_type_ext host_const_ulong_t_ext; + typedef unaligned_type_ext host_const_long_long_t_ext; + typedef unaligned_type_ext host_const_ulong_long_t_ext; +#if ETL_USING_8BIT_TYPES + typedef unaligned_type_ext host_const_int8_t_ext; + typedef unaligned_type_ext host_const_uint8_t_ext; +#endif + typedef unaligned_type_ext host_const_int16_t_ext; + typedef unaligned_type_ext host_const_uint16_t_ext; + typedef unaligned_type_ext host_const_int32_t_ext; + typedef unaligned_type_ext host_const_uint32_t_ext; +#if ETL_USING_64BIT_TYPES + typedef unaligned_type_ext host_const_int64_t_ext; + typedef unaligned_type_ext host_const_uint64_t_ext; +#endif + typedef unaligned_type_ext host_const_float_t_ext; + typedef unaligned_type_ext host_const_double_t_ext; + typedef unaligned_type_ext host_const_long_double_t_ext; +#endif + + // Little Endian + typedef unaligned_type_ext le_const_char_t_ext; + typedef unaligned_type_ext le_const_schar_t_ext; + typedef unaligned_type_ext le_const_uchar_t_ext; + typedef unaligned_type_ext le_const_short_t_ext; + typedef unaligned_type_ext le_const_ushort_t_ext; + typedef unaligned_type_ext le_const_int_t_ext; + typedef unaligned_type_ext le_const_uint_t_ext; + typedef unaligned_type_ext le_const_long_t_ext; + typedef unaligned_type_ext le_const_ulong_t_ext; + typedef unaligned_type_ext le_const_long_long_t_ext; + typedef unaligned_type_ext le_const_ulong_long_t_ext; +#if ETL_USING_8BIT_TYPES + typedef unaligned_type_ext le_const_int8_t_ext; + typedef unaligned_type_ext le_const_uint8_t_ext; +#endif + typedef unaligned_type_ext le_const_int16_t_ext; + typedef unaligned_type_ext le_const_uint16_t_ext; + typedef unaligned_type_ext le_const_int32_t_ext; + typedef unaligned_type_ext le_const_uint32_t_ext; +#if ETL_USING_64BIT_TYPES + typedef unaligned_type_ext le_const_int64_t_ext; + typedef unaligned_type_ext le_const_uint64_t_ext; +#endif + typedef unaligned_type_ext le_const_float_t_ext; + typedef unaligned_type_ext le_const_double_t_ext; + typedef unaligned_type_ext le_const_long_double_t_ext; + + // Big Endian + typedef unaligned_type_ext be_const_char_t_ext; + typedef unaligned_type_ext be_const_schar_t_ext; + typedef unaligned_type_ext be_const_uchar_t_ext; + typedef unaligned_type_ext be_const_short_t_ext; + typedef unaligned_type_ext be_const_ushort_t_ext; + typedef unaligned_type_ext be_const_int_t_ext; + typedef unaligned_type_ext be_const_uint_t_ext; + typedef unaligned_type_ext be_const_long_t_ext; + typedef unaligned_type_ext be_const_ulong_t_ext; + typedef unaligned_type_ext be_const_long_long_t_ext; + typedef unaligned_type_ext be_const_ulong_long_t_ext; +#if ETL_USING_8BIT_TYPES + typedef unaligned_type_ext be_const_int8_t_ext; + typedef unaligned_type_ext be_const_uint8_t_ext; +#endif + typedef unaligned_type_ext be_const_int16_t_ext; + typedef unaligned_type_ext be_const_uint16_t_ext; + typedef unaligned_type_ext be_const_int32_t_ext; + typedef unaligned_type_ext be_const_uint32_t_ext; +#if ETL_USING_64BIT_TYPES + typedef unaligned_type_ext be_const_int64_t_ext; + typedef unaligned_type_ext be_const_uint64_t_ext; +#endif + typedef unaligned_type_ext be_const_float_t_ext; + typedef unaligned_type_ext be_const_double_t_ext; + typedef unaligned_type_ext be_const_long_double_t_ext; + + // Network Order + typedef be_const_char_t_ext net_const_char_t_ext; + typedef be_const_schar_t_ext net_const_schar_t_ext; + typedef be_const_uchar_t_ext net_const_uchar_t_ext; + typedef be_const_short_t_ext net_const_short_t_ext; + typedef be_const_ushort_t_ext net_const_ushort_t_ext; + typedef be_const_int_t_ext net_const_int_t_ext; + typedef be_const_uint_t_ext net_const_uint_t_ext; + typedef be_const_long_t_ext net_const_long_t_ext; + typedef be_const_ulong_t_ext net_const_ulong_t_ext; + typedef be_const_long_long_t_ext net_const_long_long_t_ext; + typedef be_const_ulong_long_t_ext net_const_ulong_long_t_ext; +#if ETL_USING_8BIT_TYPES + typedef be_const_int8_t_ext net_const_int8_t_ext; + typedef be_const_uint8_t_ext net_const_uint8_t_ext; +#endif + typedef be_const_int16_t_ext net_const_int16_t_ext; + typedef be_const_uint16_t_ext net_const_uint16_t_ext; + typedef be_const_int32_t_ext net_const_int32_t_ext; + typedef be_const_uint32_t_ext net_const_uint32_t_ext; +#if ETL_USING_64BIT_TYPES + typedef be_const_int64_t_ext net_const_int64_t_ext; + typedef be_const_uint64_t_ext net_const_uint64_t_ext; +#endif + typedef be_const_float_t_ext net_const_float_t_ext; + typedef be_const_double_t_ext net_const_double_t_ext; + typedef be_const_long_double_t_ext net_const_long_double_t_ext; } #endif diff --git a/test/test_unaligned_type.cpp b/test/test_unaligned_type.cpp index 16fb31b22..b0ce1aef7 100644 --- a/test/test_unaligned_type.cpp +++ b/test/test_unaligned_type.cpp @@ -981,6 +981,75 @@ namespace CHECK_EQUAL(0x12, bev0); CHECK_EQUAL(0x34, bev1); } + + //************************************************************************* + TEST(test_unaligned_type_ext) + { + uint8_t data[] = {0x01, 0x02, 0x03, 0x04}; + + CHECK_EQUAL(etl::be_uint32_t_ext(data), 0x01020304); + CHECK_EQUAL(etl::le_uint32_t_ext(data), 0x04030201); + + // with overflow checks: at runtime + CHECK_EQUAL(etl::be_uint32_t_ext(data, sizeof(data)), 0x01020304); + CHECK_EQUAL(etl::le_uint32_t_ext(data, sizeof(data)), 0x04030201); + CHECK_EQUAL(etl::be_uint32_t_ext(data, sizeof(data) + 1), 0x01020304); + CHECK_EQUAL(etl::le_uint32_t_ext(data, sizeof(data) + 1), 0x04030201); + CHECK_THROW(etl::be_uint32_t_ext(data, sizeof(data) - 1), etl::unaligned_type_buffer_size); + CHECK_THROW(etl::le_uint32_t_ext(data, sizeof(data) - 1), etl::unaligned_type_buffer_size); + CHECK_THROW(etl::be_uint32_t_ext(data, 0), etl::unaligned_type_buffer_size); + CHECK_THROW(etl::le_uint32_t_ext(data, 0), etl::unaligned_type_buffer_size); + + etl::be_uint32_t_ext{data} = 0x12345678; + CHECK_EQUAL(etl::le_uint32_t_ext(data), 0x78563412); + } + + TEST(test_unaligned_type_ext_set_storage) + { + uint8_t data1[] = {0x12, 0x34, 0x56, 0x78}; + uint8_t data2[] = {0x78, 0x56, 0x34, 0x12}; + + etl::be_uint32_t_ext be_u32_data; + + be_u32_data.set_storage(data1); + CHECK_EQUAL(be_u32_data, 0x12345678); + + be_u32_data.set_storage(data2); + CHECK_EQUAL(be_u32_data, 0x78563412); + + // static assert: + //be_u32_data.set_storage<0>(data1); + //be_u32_data.set_storage<3>(data1); + be_u32_data.set_storage<4>(data1); + CHECK_EQUAL(be_u32_data, 0x12345678); + be_u32_data.set_storage<5>(data2); + CHECK_EQUAL(be_u32_data, 0x78563412); + + CHECK_THROW(be_u32_data.set_storage(data1, 0), etl::unaligned_type_buffer_size); + CHECK_THROW(be_u32_data.set_storage(data1, 3), etl::unaligned_type_buffer_size); + be_u32_data.set_storage(data1, 4); + CHECK_EQUAL(be_u32_data, 0x12345678); + be_u32_data.set_storage(data2, 5); + CHECK_EQUAL(be_u32_data, 0x78563412); + } + + TEST(test_const_unaligned_type_ext) + { + const uint8_t data[] = {0x01, 0x02, 0x03, 0x04}; + + CHECK_EQUAL(etl::be_const_uint32_t_ext(data), 0x01020304); + CHECK_EQUAL(etl::le_const_uint32_t_ext(data), 0x04030201); + + // with overflow checks: at runtime + CHECK_EQUAL(etl::be_const_uint32_t_ext(data, sizeof(data)), 0x01020304); + CHECK_EQUAL(etl::le_const_uint32_t_ext(data, sizeof(data)), 0x04030201); + CHECK_EQUAL(etl::be_const_uint32_t_ext(data, sizeof(data) + 1), 0x01020304); + CHECK_EQUAL(etl::le_const_uint32_t_ext(data, sizeof(data) + 1), 0x04030201); + CHECK_THROW(etl::be_const_uint32_t_ext(data, sizeof(data) - 1), etl::unaligned_type_buffer_size); + CHECK_THROW(etl::le_const_uint32_t_ext(data, sizeof(data) - 1), etl::unaligned_type_buffer_size); + CHECK_THROW(etl::be_const_uint32_t_ext(data, 0), etl::unaligned_type_buffer_size); + CHECK_THROW(etl::le_const_uint32_t_ext(data, 0), etl::unaligned_type_buffer_size); + } }; }