2121
2222#include < bit>
2323#include < concepts>
24+ #include < cstdint>
2425
2526// / \file iceberg/util/endian.h
2627// / \brief Endianness conversion utilities
2728
2829namespace iceberg {
2930
30- // / \brief Concept for values that can be written in little- endian format.
31+ // / \brief Concept for values that can be converted to/from another endian format.
3132template <typename T>
3233concept EndianConvertible = std::is_arithmetic_v<T> && !std::same_as<T, bool >;
3334
@@ -37,20 +38,7 @@ constexpr T ToLittleEndian(T value) {
3738 if constexpr (std::endian::native == std::endian::little || sizeof (T) <= 1 ) {
3839 return value;
3940 } else {
40- if constexpr (std::is_integral_v<T>) {
41- return std::byteswap (value);
42- } else if constexpr (std::is_floating_point_v<T>) {
43- // For floats, use the bit_cast -> byteswap -> bit_cast pattern.
44- if constexpr (sizeof (T) == sizeof (uint32_t )) {
45- uint32_t int_representation = std::bit_cast<uint32_t >(value);
46- int_representation = std::byteswap (int_representation);
47- return std::bit_cast<T>(int_representation);
48- } else if constexpr (sizeof (T) == sizeof (uint64_t )) {
49- uint64_t int_representation = std::bit_cast<uint64_t >(value);
50- int_representation = std::byteswap (int_representation);
51- return std::bit_cast<T>(int_representation);
52- }
53- }
41+ return ByteSwap (value);
5442 }
5543}
5644
@@ -60,20 +48,7 @@ constexpr T FromLittleEndian(T value) {
6048 if constexpr (std::endian::native == std::endian::little || sizeof (T) <= 1 ) {
6149 return value;
6250 } else {
63- if constexpr (std::is_integral_v<T>) {
64- return std::byteswap (value);
65- } else if constexpr (std::is_floating_point_v<T>) {
66- // For floats, use the bit_cast -> byteswap -> bit_cast pattern.
67- if constexpr (sizeof (T) == sizeof (uint32_t )) {
68- uint32_t int_representation = std::bit_cast<uint32_t >(value);
69- int_representation = std::byteswap (int_representation);
70- return std::bit_cast<T>(int_representation);
71- } else if constexpr (sizeof (T) == sizeof (uint64_t )) {
72- uint64_t int_representation = std::bit_cast<uint64_t >(value);
73- int_representation = std::byteswap (int_representation);
74- return std::bit_cast<T>(int_representation);
75- }
76- }
51+ return ByteSwap (value);
7752 }
7853}
7954
@@ -83,19 +58,7 @@ constexpr T ToBigEndian(T value) {
8358 if constexpr (std::endian::native == std::endian::big || sizeof (T) <= 1 ) {
8459 return value;
8560 } else {
86- if constexpr (std::is_integral_v<T>) {
87- return std::byteswap (value);
88- } else if constexpr (std::is_floating_point_v<T>) {
89- if constexpr (sizeof (T) == sizeof (uint32_t )) {
90- uint32_t int_representation = std::bit_cast<uint32_t >(value);
91- int_representation = std::byteswap (int_representation);
92- return std::bit_cast<T>(int_representation);
93- } else if constexpr (sizeof (T) == sizeof (uint64_t )) {
94- uint64_t int_representation = std::bit_cast<uint64_t >(value);
95- int_representation = std::byteswap (int_representation);
96- return std::bit_cast<T>(int_representation);
97- }
98- }
61+ return ByteSwap (value);
9962 }
10063}
10164
@@ -105,18 +68,25 @@ constexpr T FromBigEndian(T value) {
10568 if constexpr (std::endian::native == std::endian::big || sizeof (T) <= 1 ) {
10669 return value;
10770 } else {
108- if constexpr (std::is_integral_v<T>) {
109- return std::byteswap (value);
110- } else if constexpr (std::is_floating_point_v<T>) {
111- if constexpr (sizeof (T) == sizeof (uint32_t )) {
112- uint32_t int_representation = std::bit_cast<uint32_t >(value);
113- int_representation = std::byteswap (int_representation);
114- return std::bit_cast<T>(int_representation);
115- } else if constexpr (sizeof (T) == sizeof (uint64_t )) {
116- uint64_t int_representation = std::bit_cast<uint64_t >(value);
117- int_representation = std::byteswap (int_representation);
118- return std::bit_cast<T>(int_representation);
119- }
71+ return ByteSwap (value);
72+ }
73+ }
74+
75+ // / \brief Byte-swap a value. For floating-point types, only support 32-bit and 64-bit
76+ // / floats.
77+ template <EndianConvertible T>
78+ constexpr T ByteSwap (T value) {
79+ if constexpr (sizeof (T) <= 1 ) {
80+ return value;
81+ } else if constexpr (std::is_integral_v<T>) {
82+ return std::byteswap (value);
83+ } else if constexpr (std::is_floating_point_v<T>) {
84+ if constexpr (sizeof (T) == sizeof (uint32_t )) {
85+ return std::bit_cast<T>(std::byteswap (std::bit_cast<uint32_t >(value)));
86+ } else if constexpr (sizeof (T) == sizeof (uint64_t )) {
87+ return std::bit_cast<T>(std::byteswap (std::bit_cast<uint64_t >(value)));
88+ } else {
89+ static_assert (false , " Unsupported floating-point size for endian conversion." );
12090 }
12191 }
12292}
0 commit comments