Skip to content

Commit 16d9821

Browse files
committed
add endian
1 parent 87a755d commit 16d9821

File tree

1 file changed

+35
-17
lines changed

1 file changed

+35
-17
lines changed

src/iceberg/util/endian.h

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -19,57 +19,75 @@
1919

2020
#pragma once
2121

22-
#include <array>
2322
#include <bit>
2423
#include <concepts>
24+
#include <cstdint>
2525

2626
/// \file iceberg/util/endian.h
2727
/// \brief Endianness conversion utilities
2828

2929
namespace iceberg {
3030

31-
/// \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.
3232
template <typename T>
33-
concept EndianConvertible = std::is_arithmetic_v<T>;
33+
concept EndianConvertible = std::is_arithmetic_v<T> && !std::same_as<T, bool>;
3434

35-
/// \brief Concept for values that can be written in big-endian format,
36-
template <typename T>
37-
concept BigEndianWritable = std::same_as<T, std::array<uint8_t, 16>>;
35+
/// \brief Byte-swap a value. For floating-point types, only support 32-bit and 64-bit
36+
/// floats.
37+
template <EndianConvertible T>
38+
constexpr T ByteSwap(T value) {
39+
if constexpr (sizeof(T) <= 1) {
40+
return value;
41+
} else if constexpr (std::is_integral_v<T>) {
42+
return std::byteswap(value);
43+
} else if constexpr (std::is_floating_point_v<T>) {
44+
if constexpr (sizeof(T) == sizeof(uint32_t)) {
45+
return std::bit_cast<T>(std::byteswap(std::bit_cast<uint32_t>(value)));
46+
} else if constexpr (sizeof(T) == sizeof(uint64_t)) {
47+
return std::bit_cast<T>(std::byteswap(std::bit_cast<uint64_t>(value)));
48+
} else {
49+
static_assert(false, "Unsupported floating-point size for endian conversion.");
50+
}
51+
}
52+
}
3853

3954
/// \brief Convert a value to little-endian format.
4055
template <EndianConvertible T>
41-
T ToLittleEndian(T value) {
42-
if constexpr (std::endian::native != std::endian::little && sizeof(T) > 1) {
43-
return std::byteswap(value);
56+
constexpr T ToLittleEndian(T value) {
57+
if constexpr (std::endian::native == std::endian::little || sizeof(T) <= 1) {
58+
return value;
59+
} else {
60+
return ByteSwap(value);
4461
}
45-
return value;
4662
}
4763

4864
/// \brief Convert a value from little-endian format.
4965
template <EndianConvertible T>
50-
T FromLittleEndian(T value) {
51-
if constexpr (std::endian::native != std::endian::little && sizeof(T) > 1) {
52-
return std::byteswap(value);
66+
constexpr T FromLittleEndian(T value) {
67+
if constexpr (std::endian::native == std::endian::little || sizeof(T) <= 1) {
68+
return value;
69+
} else {
70+
return ByteSwap(value);
5371
}
54-
return value;
5572
}
5673

74+
/// \brief Convert a value to big-endian format.
5775
template <EndianConvertible T>
5876
constexpr T ToBigEndian(T value) {
5977
if constexpr (std::endian::native == std::endian::big || sizeof(T) <= 1) {
6078
return value;
6179
} else {
62-
return std::byteswap(value);
80+
return ByteSwap(value);
6381
}
6482
}
6583

66-
/// \brief Convert a value from big-endian format to native.
84+
/// \brief Convert a value from big-endian format.
6785
template <EndianConvertible T>
6886
constexpr T FromBigEndian(T value) {
6987
if constexpr (std::endian::native == std::endian::big || sizeof(T) <= 1) {
7088
return value;
7189
} else {
72-
return std::byteswap(value);
90+
return ByteSwap(value);
7391
}
7492
}
7593

0 commit comments

Comments
 (0)