Embedded Artistry Framework
Embedded Systems C++ Framework
Functions

Functions that can be used to swap the endianness of a value. More...

Collaboration diagram for Endian Swap:

Functions

template<class T >
constexpr std::enable_if< std::is_unsigned< T >::value, T >::type embutil::byteswap (T i, T j=0u, std::size_t n=0u) noexcept
 Recursive constexpr byteswap implementation without C++17 fold expressions. More...
 
template<typename T >
void embutil::SwapEndian (T &val, typename std::enable_if< std::is_arithmetic< T >::value, std::nullptr_t >::type unused=nullptr) noexcept
 Non-constexpr Robust Endian Swap. More...
 
template<typename T >
void embutil::SwapEndian_UB (T &val) noexcept
 Endian swap using undefined behavior. More...
 

Detailed Description

Functions that can be used to swap the endianness of a value.

Function Documentation

◆ byteswap()

template<class T >
constexpr std::enable_if<std::is_unsigned<T>::value, T>::type embutil::byteswap ( T  i,
T  j = 0u,
std::size_t  n = 0u 
)
noexcept

Recursive constexpr byteswap implementation without C++17 fold expressions.

Specialized implementations can be defined for specific types if desired. Example of template specialization for a specific type:

template<>
void SwapEndian<std::uint32_t>(std::uint32_t &value) {
std::uint32_t tmp = ((value << 8) & 0xFF00FF00) | ((value >> 8) & 0xFF00FF);
value = (tmp << 16) | (tmp >> 16);
}
Template Parameters
TThe type of the value being byteswap'd. This is (typically) deduced by the compiler.
Parameters
iThe value to byteswap.
jUsed in the recursive calculation; users should not set this.
nUsed in the recursive calculation; users shoudl not set this.
Returns
Endian swapped value.

References CHAR_BIT, n, and T.

Referenced by embdrv::vl53l1x::readTrim(), and embdrv::vl53l1x::writeReg().

◆ SwapEndian()

template<typename T >
void embutil::SwapEndian ( T val,
typename std::enable_if< std::is_arithmetic< T >::value, std::nullptr_t >::type  unused = nullptr 
)
noexcept

Non-constexpr Robust Endian Swap.

Described here: https://mklimenko.github.io/english/2018/08/22/robust-endian-swap/ This approach avoids bitmasks/shifts and intrinsics, which can be non-portable and error prone

The idea is simple: we define a template function, in which there is a union, containing both the passed value and the std::array of the corresponding size. We create two objects of such union and perform the reverse copying from one to another. All the extra assignments will be optimized out by the compiler, which will make this code fast and efficient.

We use the SFINAE-d version to make sure you won’t pass anything wrong

The good thing about this is that we have a template for all the corner cases and possible types. But the greatest is that the compiler was able to optimize both of these functions into one assembly command bswap. Some instructions sets haven’t got that command and if this will become the bottleneck of your program, you can make a template specialization for the case you need.

Template Parameters
TType of integer to perform the swap on. This value is (typically) deduced by the compiler.
Parameters
valThe value to perform an endian swap on.
unusedAn unused parameter, present for use with std::enable_if.

References T.

◆ SwapEndian_UB()

template<typename T >
void embutil::SwapEndian_UB ( T val)
noexcept

Endian swap using undefined behavior.

Original version of SwapEndian(). The undefined behavior is due to the use of an inactive member of the union. This function is efficient, but the undefined behavior makes it risky.

Template Parameters
TType of integer to perform the swap on. This value is (typically) deduced by the compiler.
Parameters
valThe value to perform an endian swpa on.

References T.