From 9d24c789f8813b0abd4a7d1f7e5da6cdc4566cb9 Mon Sep 17 00:00:00 2001 From: benedekkupper Date: Mon, 3 Oct 2022 17:43:23 +0200 Subject: [PATCH] unaligned types: use unsigned storage type (#614) This saves one static_cast when copying from storage to value, and prevents unintended sign-extension when extracting raw data. --- include/etl/unaligned_type.h | 168 ++++++++++++++++------------------- 1 file changed, 76 insertions(+), 92 deletions(-) diff --git a/include/etl/unaligned_type.h b/include/etl/unaligned_type.h index d884c4e4..0db9543a 100644 --- a/include/etl/unaligned_type.h +++ b/include/etl/unaligned_type.h @@ -58,11 +58,10 @@ namespace etl 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 unsigned char* pointer; + typedef const unsigned char* const_pointer; + typedef unsigned char* iterator; + typedef const unsigned char* const_iterator; typedef etl::reverse_iterator reverse_iterator; typedef etl::reverse_iterator const_reverse_iterator; @@ -197,7 +196,7 @@ namespace etl //************************************************************************* /// Index operator. //************************************************************************* - storage_type& operator[](int i) + unsigned char& operator[](int i) { return storage[i]; } @@ -205,7 +204,7 @@ namespace etl //************************************************************************* /// Const index operator. //************************************************************************* - ETL_CONSTEXPR const storage_type& operator[](int i) const + ETL_CONSTEXPR const unsigned char& operator[](int i) const { return storage[i]; } @@ -218,9 +217,6 @@ namespace etl //************************************************************************* /// 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 private_unaligned_type::unaligned_type_common @@ -231,14 +227,6 @@ namespace etl typedef T value_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; - static ETL_CONSTANT int Endian = Endian_; static ETL_CONSTANT size_t Size = private_unaligned_type::unaligned_type_common::Size; @@ -368,34 +356,32 @@ namespace etl struct unaligned_copy; //******************************************* - /// Unaligned copy - /// Size == 1 + // Size == 1 //******************************************* template struct unaligned_copy { //******************************* - static ETL_CONSTEXPR14 void copy(T value, pointer store) + static ETL_CONSTEXPR14 void copy(T value, unsigned char* 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 unsigned char* store, T& value) { value = static_cast(store[0]); } //******************************* - static ETL_CONSTEXPR14 void copy(const_pointer src, int /*endian_src*/, unsigned char* dst) + static ETL_CONSTEXPR14 void copy(const unsigned char* src, int /*endian_src*/, unsigned char* dst) { dst[0] = src[0]; } }; //******************************************* - /// Unaligned copy - /// Size == 2 + // Size == 2 //******************************************* template struct unaligned_copy @@ -405,33 +391,33 @@ 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 unsigned char* store, T& value) { if (Endian == etl::endianness::value()) { - value = static_cast(static_cast(store[0])); - value |= static_cast(static_cast(store[1])) << (1U * CHAR_BIT); + value = static_cast(store[0]); + value |= static_cast(store[1]) << (1U * CHAR_BIT); } else { - value = static_cast(static_cast(store[1])); - value |= static_cast(static_cast(store[0])) << (1U * CHAR_BIT); + value = static_cast(store[1]); + value |= static_cast(store[0]) << (1U * CHAR_BIT); } } //******************************* - static ETL_CONSTEXPR14 void copy(const_pointer src, int endian_src, unsigned char* dst) + static ETL_CONSTEXPR14 void copy(const unsigned char* src, int endian_src, unsigned char* dst) { if (Endian == endian_src) { @@ -447,8 +433,7 @@ namespace etl }; //******************************************* - /// Unaligned copy - /// Size == 4 + // Size == 4 //******************************************* template struct unaligned_copy @@ -457,41 +442,41 @@ 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 char* store, T& value) { if (Endian == etl::endianness::value()) { - 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); + value = static_cast(store[0]); + value |= static_cast(store[1]) << (1U * CHAR_BIT); + value |= static_cast(store[2]) << (2U * CHAR_BIT); + value |= static_cast(store[3]) << (3U * CHAR_BIT); } else { - 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); + value = static_cast(store[3]); + value |= static_cast(store[2]) << (1U * CHAR_BIT); + value |= static_cast(store[1]) << (2U * CHAR_BIT); + value |= static_cast(store[0]) << (3U * CHAR_BIT); } } //******************************* - static ETL_CONSTEXPR14 void copy(const_pointer src, int endian_src, unsigned char* dst) + static ETL_CONSTEXPR14 void copy(const unsigned char* src, int endian_src, unsigned char* dst) { if (Endian == endian_src) { @@ -511,8 +496,7 @@ namespace etl }; //******************************************* - /// Unaligned copy - /// Size == 8 + // Size == 8 //******************************************* template struct unaligned_copy @@ -521,57 +505,57 @@ 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 unsigned char* store, T& value) { if (Endian == etl::endianness::value()) { - 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); - value |= static_cast(static_cast(store[4])) << (4U * CHAR_BIT); - value |= static_cast(static_cast(store[5])) << (5U * CHAR_BIT); - value |= static_cast(static_cast(store[6])) << (6U * CHAR_BIT); - value |= static_cast(static_cast(store[7])) << (7U * CHAR_BIT); + value = static_cast(store[0]); + value |= static_cast(store[1]) << (1U * CHAR_BIT); + value |= static_cast(store[2]) << (2U * CHAR_BIT); + value |= static_cast(store[3]) << (3U * CHAR_BIT); + value |= static_cast(store[4]) << (4U * CHAR_BIT); + value |= static_cast(store[5]) << (5U * CHAR_BIT); + value |= static_cast(store[6]) << (6U * CHAR_BIT); + value |= static_cast(store[7]) << (7U * CHAR_BIT); } else { - value = static_cast(static_cast(store[7])); - value |= static_cast(static_cast(store[6])) << (1U * CHAR_BIT); - value |= static_cast(static_cast(store[5])) << (2U * CHAR_BIT); - value |= static_cast(static_cast(store[4])) << (3U * CHAR_BIT); - value |= static_cast(static_cast(store[3])) << (4U * CHAR_BIT); - value |= static_cast(static_cast(store[2])) << (5U * CHAR_BIT); - value |= static_cast(static_cast(store[1])) << (6U * CHAR_BIT); - value |= static_cast(static_cast(store[0])) << (7U * CHAR_BIT); + value = static_cast(store[7]); + value |= static_cast(store[6]) << (1U * CHAR_BIT); + value |= static_cast(store[5]) << (2U * CHAR_BIT); + value |= static_cast(store[4]) << (3U * CHAR_BIT); + value |= static_cast(store[3]) << (4U * CHAR_BIT); + value |= static_cast(store[2]) << (5U * CHAR_BIT); + value |= static_cast(store[1]) << (6U * CHAR_BIT); + value |= static_cast(store[0]) << (7U * CHAR_BIT); } } //******************************* - static ETL_CONSTEXPR14 void copy(const_pointer src, int endian_src, unsigned char* dst) + static ETL_CONSTEXPR14 void copy(const unsigned char* src, int endian_src, unsigned char* dst) { if (Endian == endian_src) {