25#ifndef JAU_BYTE_UTIL_HPP_
26#define JAU_BYTE_UTIL_HPP_
64 #if defined __has_builtin
65 #if __has_builtin(__builtin_bswap16)
66 #define __has_builtin_bswap16 1
68 #elif defined(__GNUC__) && __GNUC_PREREQ (4, 8)
69 #define __has_builtin_bswap16 1
71 #if defined __has_builtin
72 #if __has_builtin(__builtin_bswap32)
73 #define __has_builtin_bswap32 1
75 #elif defined(__GNUC__) && __GNUC_PREREQ (4, 8)
76 #define __has_builtin_bswap32 1
78 #if defined __has_builtin
79 #if __has_builtin(__builtin_bswap64)
80 #define __has_builtin_bswap64 1
82 #elif defined(__GNUC__) && __GNUC_PREREQ (4, 8)
83 #define __has_builtin_bswap64 1
88 template <jau::req::
unsigned_
integral T>
89 requires (
sizeof(T) == 2)
90 constexpr T
bswap(T
const & source)
noexcept {
91 #if defined __has_builtin_bswap16
92 return __builtin_bswap16(source);
95 return (T) ( ( ( source >> 8 ) & 0xff ) |
96 ( ( source & 0xff_u16) << 8 ) );
100 template <jau::req::
signed_
integral T>
101 requires (
sizeof(T) == 2)
102 constexpr T
bswap(T
const & source)
noexcept {
103 #if defined __has_builtin_bswap16
108 return (T) ( ( ( usource >> 8 ) & 0xff ) |
109 ( ( usource & 0xff_u16) << 8 ) );
113 template <jau::req::
unsigned_
integral T>
114 requires (
sizeof(T) == 4)
115 constexpr T
bswap(T
const & source)
noexcept {
116 #if defined __has_builtin_bswap32
117 return __builtin_bswap32(source);
120 return ( ( source & 0xff000000_u32 ) >> 24 ) |
121 ( ( source & 0x00ff0000_u32 ) >> 8 ) |
122 ( ( source & 0x0000ff00_u32 ) << 8 ) |
123 ( ( source & 0x000000ff_u32 ) << 24 );
127 template <jau::req::
signed_
integral T>
128 requires (
sizeof(T) == 4)
129 constexpr T
bswap(T
const & source)
noexcept {
130 #if defined __has_builtin_bswap32
136 ( ( usource & 0x00ff0000_u32 ) >> 8 ) |
137 ( ( usource & 0x0000ff00_u32 ) << 8 ) |
138 ( ( usource & 0x000000ff_u32 ) << 24 ) );
142 template <jau::req::
unsigned_
integral T>
143 requires (
sizeof(T) == 8)
144 constexpr T
bswap(T
const & source)
noexcept {
145 #if defined __has_builtin_bswap64
146 return __builtin_bswap64(source);
149 return ( ( source & 0xff00000000000000_u64 ) >> 56 ) |
150 ( ( source & 0x00ff000000000000_u64 ) >> 40 ) |
151 ( ( source & 0x0000ff0000000000_u64 ) >> 24 ) |
152 ( ( source & 0x000000ff00000000_u64 ) >> 8 ) |
153 ( ( source & 0x00000000ff000000_u64 ) << 8 ) |
154 ( ( source & 0x0000000000ff0000_u64 ) << 24 ) |
155 ( ( source & 0x000000000000ff00_u64 ) << 40 ) |
156 ( ( source & 0x00000000000000ff_u64 ) << 56 );
160 template <jau::req::
signed_
integral T>
161 requires (
sizeof(T) == 8)
162 constexpr T
bswap(T
const & source)
noexcept {
163 #if defined __has_builtin_bswap64
169 ( ( usource & 0x00ff000000000000_u64 ) >> 40 ) |
170 ( ( usource & 0x0000ff0000000000_u64 ) >> 24 ) |
171 ( ( usource & 0x000000ff00000000_u64 ) >> 8 ) |
172 ( ( usource & 0x00000000ff000000_u64 ) << 8 ) |
173 ( ( usource & 0x0000000000ff0000_u64 ) << 24 ) |
174 ( ( usource & 0x000000000000ff00_u64 ) << 40 ) |
175 ( ( usource & 0x00000000000000ff_u64 ) << 56 ) );
179 constexpr void bswap(uint8_t * sink, uint8_t
const * source,
nsize_t len) {
181 for (; len > 0; len--) {
205 return reinterpret_cast<char*
>(b);
208 return reinterpret_cast<const char*
>(b);
212 return reinterpret_cast<const uint8_t*
>(s);
225 constexpr uint32_t get_host_order() noexcept {
227 constexpr uint8_t b[4] { 0x44, 0x43, 0x42, 0x41 };
392 template <
typename Dummy_type>
struct has_endian_little : std::integral_constant<bool, endian_t::little == endian_t::native> {};
412 template <
typename Dummy_type>
struct has_endian_big : std::integral_constant<bool, endian_t::big == endian_t::native> {};
434 template <jau::req::
unsigned_
integral T>
444 template <jau::req::
unsigned_
integral T>
454 template <jau::req::
unsigned_
integral T>
464 template <jau::req::
unsigned_
integral T>
475 template <jau::req::
signed_
integral T>
476 constexpr T
be_to_cpu(T
const n)
noexcept {
485 template <jau::req::
signed_
integral T>
486 constexpr T
cpu_to_be(T
const h)
noexcept {
495 template <jau::req::
signed_
integral T>
496 constexpr T
le_to_cpu(T
const l)
noexcept {
505 template <jau::req::
signed_
integral T>
506 constexpr T
cpu_to_le(T
const h)
noexcept {
637 static constexpr std::array<uint8_t, 256> BitRevTable256 =
638 []()
constexpr -> std::array<uint8_t, 256> {
640 std::array<uint8_t, 256> result{};
641 for (
size_t i = 0; i < 256; ++i) {
643 result[i] = ( (i * 0x80200802_u64) & 0x0884422110_u64 ) * 0x0101010101_u64 >> 32;
653 constexpr uint8_t
rev_bits(uint8_t v)
noexcept {
return impl::BitRevTable256[v]; };
659 return ( uint16_t( impl::BitRevTable256[ v & 0xff] ) << 8) |
660 ( uint16_t( impl::BitRevTable256[(v >> 8) & 0xff] ) );
667 return ( uint32_t( impl::BitRevTable256[ v & 0xff] ) << 24) |
668 ( uint32_t( impl::BitRevTable256[(v >> 8) & 0xff] ) << 16) |
669 ( uint32_t( impl::BitRevTable256[(v >> 16) & 0xff] ) << 8) |
670 ( uint32_t( impl::BitRevTable256[(v >> 24) & 0xff] ) );
677 return ( uint64_t( impl::BitRevTable256[ v & 0xff] ) << 56) |
678 ( uint64_t( impl::BitRevTable256[(v >> 8) & 0xff] ) << 48) |
679 ( uint64_t( impl::BitRevTable256[(v >> 16) & 0xff] ) << 40) |
680 ( uint64_t( impl::BitRevTable256[(v >> 24) & 0xff] ) << 32) |
681 ( uint64_t( impl::BitRevTable256[(v >> 32) & 0xff] ) << 24) |
682 ( uint64_t( impl::BitRevTable256[(v >> 40) & 0xff] ) << 16) |
683 ( uint64_t( impl::BitRevTable256[(v >> 48) & 0xff] ) << 8) |
684 ( uint64_t( impl::BitRevTable256[(v >> 56) & 0xff] ) );
688 template<jau::req::
unsigned_
integral T>
690 if ( n >=
sizeof(T) * CHAR_BIT ) {
691 return std::numeric_limits<T>::max();
693 return (T(1) << n) - T(1);
704 template<jau::req::
unsigned_
integral T>
706 if ( n >=
sizeof(T) * CHAR_BIT ) {
709 v &= (T(1) << n) - T(1);
712 for (v >>= 1; v; v >>= 1) {
726 constexpr void put_uint8(uint8_t * buffer,
const uint8_t v)
noexcept
730 constexpr uint8_t
get_uint8(uint8_t
const * buffer)
noexcept
734 constexpr int8_t
get_int8(uint8_t
const * buffer)
noexcept
757 constexpr void put_uint16(uint8_t * buffer,
const uint16_t v)
noexcept
780 constexpr uint16_t
get_uint16(uint8_t
const * buffer)
noexcept
804 constexpr void put_int16(uint8_t * buffer,
const int16_t v)
noexcept
827 constexpr int16_t
get_int16(uint8_t
const * buffer)
noexcept
849 constexpr void put_uint32(uint8_t * buffer,
const uint32_t v)
noexcept
865 constexpr uint32_t
get_uint32(uint8_t
const * buffer)
noexcept
882 constexpr void put_int32(uint8_t * buffer,
const int32_t v)
noexcept
898 constexpr int32_t
get_int32(uint8_t
const * buffer)
noexcept
915 constexpr void put_uint64(uint8_t * buffer,
const uint64_t & v)
noexcept
931 constexpr uint64_t
get_uint64(uint8_t
const * buffer)
noexcept
948 constexpr void put_int64(uint8_t * buffer,
const int64_t & v)
noexcept
964 constexpr int64_t
get_int64(uint8_t
const * buffer)
noexcept
1091 template<
typename T>
1093 typename std::enable_if_t<
1094 std::is_standard_layout_v<T>,
1115 template<
typename T>
1117 typename std::enable_if_t<
1118 std::is_standard_layout_v<T>,
1134 template<
typename T>
1136 typename std::enable_if_t<
1137 std::is_standard_layout_v<T>,
1157 template<
typename T>
1159 typename std::enable_if_t<
1160 std::is_standard_layout_v<T>,
constexpr uint192dp_t get_uint192(uint8_t const *buffer) noexcept
See get_uint16() for reference.
constexpr T cpu_to_be(T const h) noexcept
constexpr bool has_endian_big_v
Value access of big-endian type trait for convenience .
constexpr uint128dp_t get_uint128(uint8_t const *buffer) noexcept
See get_uint16() for reference.
constexpr int64_t get_int64(uint8_t const *buffer) noexcept
See get_int16() for reference.
constexpr T get_packed_value(const packed_t< T > *source, const lb_endian_t byte_order) noexcept
Return packed_t::store after converting it to from either lb_endian::little or lb_endian::big dependi...
constexpr bool is_little_endian() noexcept
Evaluates true if platform is running in little endian mode, i.e.
constexpr bool is_big_endian() noexcept
Evaluates true if platform is running in big endian mode, i.e.
constexpr std::enable_if_t< std::is_standard_layout_v< T >, T > get_value(uint8_t const *buffer) noexcept
Returns a T value from the given byte address using packed_t to resolve a potential memory alignment ...
constexpr void put_uint256(uint8_t *buffer, const uint256dp_t &v) noexcept
See put_uint16() for reference.
constexpr bool is_defined_endian(const endian_t &v) noexcept
Evaluates true if the given endian is defined, i.e.
static constexpr T bit_mask(size_t n) noexcept
Returns the T bit mask of n-bits, i.e.
bit_order_t
Bit order type, i.e.
constexpr uint16_t get_uint16(uint8_t const *buffer) noexcept
Returns a uint16_t value from the given byte address using packed_t to resolve a potential memory ali...
constexpr bool is_little_or_big_endian() noexcept
Evaluates true if platform is running in little or big endian mode, i.e.
std::string_view to_string(const endian_t v) noexcept
Return std::string representation of the given endian.
constexpr endian_t to_endian(const lb_endian_t v) noexcept
constexpr uint32_t get_uint32(uint8_t const *buffer) noexcept
See get_uint16() for reference.
char * cast_uint8_ptr_to_char(uint8_t *b) noexcept
constexpr T bswap(T const &source) noexcept
constexpr void put_uint32(uint8_t *buffer, const uint32_t v) noexcept
See put_uint16() for reference.
constexpr int16_t get_int16(uint8_t const *buffer) noexcept
Returns a int16_t value from the given byte address using packed_t to resolve a potential memory alig...
endian_t
Endian identifier, indicating endianess of all scalar types.
constexpr int32_t get_int32(uint8_t const *buffer) noexcept
See get_int16() for reference.
constexpr uint256dp_t get_uint256(uint8_t const *buffer) noexcept
See get_uint16() for reference.
constexpr void put_uint192(uint8_t *buffer, const uint192dp_t &v) noexcept
See put_uint16() for reference.
constexpr bool has_endian_little_v
Value access of little-endian type trait for convenience .
constexpr void put_int16(uint8_t *buffer, const int16_t v) noexcept
Put the given int16_t value into the given byte address using packed_t to resolve a potential memory ...
constexpr void put_uint8(uint8_t *buffer, const uint8_t v) noexcept
constexpr T le_to_cpu(T const l) noexcept
lb_endian_t
Simplified reduced endian type only covering little- and big-endian.
constexpr void put_uint64(uint8_t *buffer, const uint64_t &v) noexcept
See put_uint16() for reference.
constexpr void put_uint16(uint8_t *buffer, const uint16_t v) noexcept
Put the given uint16_t value into the given byte address using packed_t to resolve a potential memory...
constexpr void put_uint128(uint8_t *buffer, const uint128dp_t &v) noexcept
See put_uint16() for reference.
constexpr std::enable_if_t< std::is_standard_layout_v< T >, void > put_value(uint8_t *buffer, const T &v) noexcept
Put the given T value into the given byte address using packed_t to resolve a potential memory alignm...
constexpr lb_endian_t to_lb_endian(const endian_t v) noexcept
constexpr void put_int64(uint8_t *buffer, const int64_t &v) noexcept
See put_int16() for reference.
constexpr void put_int32(uint8_t *buffer, const int32_t v) noexcept
See put_int16() for reference.
constexpr T be_to_cpu(T const n) noexcept
constexpr uint64_t get_uint64(uint8_t const *buffer) noexcept
See get_uint16() for reference.
constexpr int8_t get_int8(uint8_t const *buffer) noexcept
constexpr uint8_t rev_bits(uint8_t v) noexcept
Reverse bits of one byte.
constexpr uint8_t get_uint8(uint8_t const *buffer) noexcept
constexpr T cpu_to_le(T const h) noexcept
const uint8_t * cast_char_ptr_to_uint8(const char *s) noexcept
@ lsb
Identifier for least-significant-bit (lsb) first.
@ msb
Identifier for most-significant-bit (msb) first.
@ pdp
Identifier for DEC PDP-11, aka ENDIAN_LITTLE_WORD.
@ undefined
Undetermined endian.
@ native
Identifier for native platform type, one of the above.
@ little
Identifier for little endian.
@ honeywell
Identifier for Honeywell 316, aka ENDIAN_BIG_WORD.
@ big
Identifier for big endian.
@ little
Identifier for little endian, equivalent to endian::little.
@ big
Identifier for big endian, equivalent to endian::big.
constexpr std::enable_if_t< sizeof(Dest)==sizeof(Source) &&std::is_trivially_copyable_v< Dest > &&std::is_trivially_copyable_v< Source >, Dest > bit_cast(const Source &src) noexcept
C++20 bit_cast<>(arg) implementation for C++17.
#define PRAGMA_DISABLE_WARNING_PUSH
consteval_cxx20 bool has_builtin_bit_cast() noexcept
Query whether __builtin_bit_cast(Dest_type, arg) is available via __has_builtin(__builtin_bit_cast).
constexpr std::enable_if_t< sizeof(Dest)==sizeof(Source) &&std::is_pointer_v< Source > &&std::is_pointer_v< Dest >, Dest > pointer_cast(const Source &src) noexcept
A constexpr pointer cast implementation for C++17, inspired by C++20 bit_cast<>(arg).
#define PRAGMA_DISABLE_WARNING_MULTICHAR
#define PRAGMA_DISABLE_WARNING_POP
uint_bytes_t< sizeof(unsigned long int)> nsize_t
Natural 'size_t' alternative using uint<XX>_t with xx = sizeof(unsigned long int)*8 as its natural si...
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
A big-endian type trait for convenience .
A little-endian type trait for convenience .
Support aligned memory transfer from and to potentially unaligned memory.
A 128-bit packed uint8_t data array.
A 196-bit packed uint8_t data array.
A 256-bit packed uint8_t data array.