[wpiutil] Remove bit.hpp; replace with C++23 bit (#8792)

#7492 didn't catch all the uses and #7973 patched out byteswap in
Sleipnir for some reason (despite having upgraded compilers already)?
This commit is contained in:
Gold856
2026-06-29 11:37:27 -04:00
committed by GitHub
parent 54b0239984
commit 852e0dfd8e
18 changed files with 776 additions and 836 deletions

View File

@@ -60,7 +60,6 @@ macro(add_doxygen_docs)
"wpi/SmallVector.h"
"wpi/StringExtras.h"
"wpi/StringMap.h"
"wpi/SwapByteOrder.h"
"wpi/type_traits.h"
"wpi/VersionTuple.h"
"wpi/WindowsError.h"

View File

@@ -89,7 +89,6 @@ doxygen(
"*/wpi/util/ErrorHandling.hpp",
"*/wpi/util/SmallVector.hpp",
"*/wpi/util/StringExtras.hpp",
"*/wpi/util/bit.hpp",
"*/wpi/util/raw_ostream.hpp",
# Sleipnir
"*/sleipnir/optimization/solver/interior_point.hpp",

View File

@@ -96,7 +96,6 @@ doxygen.sourceSets.main {
exclude 'wpi/util/ErrorHandling.hpp'
exclude 'wpi/util/SmallVector.hpp'
exclude 'wpi/util/StringExtras.hpp'
exclude 'wpi/util/bit.hpp'
exclude 'wpi/util/raw_ostream.hpp'
// Sleipnir

View File

@@ -5,6 +5,7 @@
#include "WebSocketConnection.hpp"
#include <algorithm>
#include <bit>
#include <span>
#include "wpi/net/WebSocket.hpp"
@@ -124,8 +125,7 @@ void WebSocketConnection::SendPing(uint64_t time) {
WPI_DEBUG4(m_logger, "conn: sending ping {}", time);
auto buf = AllocBuf();
buf.len = 8;
wpi::util::support::endian::write64<wpi::util::endianness::native>(buf.base,
time);
wpi::util::support::endian::write64<std::endian::native>(buf.base, time);
m_ws.SendPing({buf}, [selfweak = weak_from_this()](auto bufs, auto err) {
if (auto self = selfweak.lock()) {
self->m_err = err;

View File

@@ -60,11 +60,13 @@ def run_global_replacements(wpiutil_llvm_files: list[Path]):
content = content.replace('#include "wpi/util/DataTypes.h"\n', "")
content = content.replace('#include "wpi/util/llvm-config.h"\n', "")
content = content.replace('#include "wpi/util/abi-breaking.h"\n', "")
content = content.replace('#include "wpi/util/bit.h"\n', "")
content = content.replace('#include "wpi/util/config.h"\n', "")
content = content.replace('#include "wpi/util/Signals.h"\n', "")
content = content.replace('#include "wpi/util/Process.h"\n', "")
content = content.replace('#include "wpi/util/Path.h"\n', "")
content = content.replace('#include "wpi/util/Program.h"\n', "")
content = content.replace('#include "wpi/util/SwapByteOrder.h"\n', "")
# Fix include guards
content = content.replace("LLVM_ADT_", "WPIUTIL_WPI_")

View File

@@ -14,7 +14,7 @@ Subject: [PATCH 01/34] Remove StringRef, ArrayRef, and Optional
llvm/include/llvm/Support/VersionTuple.h | 6 --
.../llvm/Support/Windows/WindowsSupport.h | 4 +-
llvm/include/llvm/Support/raw_ostream.h | 46 ++++----
llvm/lib/Support/ConvertUTFWrapper.cpp | 39 +++----
llvm/lib/Support/ConvertUTFWrapper.cpp | 39 ++++---
llvm/lib/Support/ErrorHandling.cpp | 21 ++--
llvm/lib/Support/SmallVector.cpp | 5 +-
llvm/lib/Support/VersionTuple.cpp | 49 ---------
@@ -25,7 +25,7 @@ Subject: [PATCH 01/34] Remove StringRef, ArrayRef, and Optional
llvm/unittests/ADT/SmallStringTest.cpp | 50 ++++-----
llvm/unittests/ADT/SmallVectorTest.cpp | 36 ++-----
llvm/unittests/Support/ConvertUTFTest.cpp | 42 ++++----
21 files changed, 226 insertions(+), 315 deletions(-)
21 files changed, 225 insertions(+), 316 deletions(-)
diff --git a/llvm/include/llvm/ADT/PointerUnion.h b/llvm/include/llvm/ADT/PointerUnion.h
index d9087dd1c516ee265aa00851ca98b1df09936f3e..c3d6458777d186a700c359089c4afcac8db0185a 100644
@@ -749,10 +749,10 @@ index 70916d8e4adb0f98984ff335187a083a3091bc58..19df8739b6013c1b1a1527f5880a040d
LLVM_ABI raw_ostream &operator<<(raw_ostream &OS, std::nullopt_t);
diff --git a/llvm/lib/Support/ConvertUTFWrapper.cpp b/llvm/lib/Support/ConvertUTFWrapper.cpp
index 76ead00c977bd37147048d321b425a9a9e76497a..39f151c716dacfef07038551add0f84a09b0cb62 100644
index 76ead00c977bd37147048d321b425a9a9e76497a..448dbde16986172f506c247a1cd3a78a311f1fa2 100644
--- a/llvm/lib/Support/ConvertUTFWrapper.cpp
+++ b/llvm/lib/Support/ConvertUTFWrapper.cpp
@@ -6,23 +6,24 @@
@@ -6,23 +6,23 @@
//
//===----------------------------------------------------------------------===//
@@ -760,7 +760,6 @@ index 76ead00c977bd37147048d321b425a9a9e76497a..39f151c716dacfef07038551add0f84a
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/SwapByteOrder.h"
+#include <span>
#include <string>
+#include <string_view>
@@ -782,7 +781,7 @@ index 76ead00c977bd37147048d321b425a9a9e76497a..39f151c716dacfef07038551add0f84a
result = sourceIllegal;
ErrorPtr = Pos;
} else {
@@ -75,12 +76,12 @@ bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr) {
@@ -75,12 +75,12 @@ bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr) {
return true;
}
@@ -797,7 +796,7 @@ index 76ead00c977bd37147048d321b425a9a9e76497a..39f151c716dacfef07038551add0f84a
assert(Out.empty());
// Error out on an uneven byte count.
@@ -131,14 +132,14 @@ bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out) {
@@ -131,14 +131,14 @@ bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out) {
return true;
}
@@ -815,7 +814,7 @@ index 76ead00c977bd37147048d321b425a9a9e76497a..39f151c716dacfef07038551add0f84a
assert(Out.empty());
// Error out on an uneven byte count.
@@ -189,14 +190,14 @@ bool convertUTF32ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out) {
@@ -189,14 +189,14 @@ bool convertUTF32ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out) {
return true;
}
@@ -833,7 +832,7 @@ index 76ead00c977bd37147048d321b425a9a9e76497a..39f151c716dacfef07038551add0f84a
SmallVectorImpl<UTF16> &DstUTF16) {
assert(DstUTF16.empty());
@@ -207,8 +208,8 @@ bool convertUTF8ToUTF16String(StringRef SrcUTF8,
@@ -207,8 +207,8 @@ bool convertUTF8ToUTF16String(StringRef SrcUTF8,
return true;
}
@@ -844,7 +843,7 @@ index 76ead00c977bd37147048d321b425a9a9e76497a..39f151c716dacfef07038551add0f84a
// Allocate the same number of UTF-16 code units as UTF-8 code units. Encoding
// as UTF-16 should always require the same amount or less code units than the
@@ -239,7 +240,7 @@ static_assert(sizeof(wchar_t) == 1 || sizeof(wchar_t) == 2 ||
@@ -239,7 +239,7 @@ static_assert(sizeof(wchar_t) == 1 || sizeof(wchar_t) == 2 ||
"Expected wchar_t to be 1, 2, or 4 bytes");
template <typename TResult>
@@ -853,7 +852,7 @@ index 76ead00c977bd37147048d321b425a9a9e76497a..39f151c716dacfef07038551add0f84a
TResult &Result) {
// Even in the case of UTF-16, the number of bytes in a UTF-8 string is
// at least as large as the number of elements in the resulting wide
@@ -255,7 +256,7 @@ static inline bool ConvertUTF8toWideInternal(llvm::StringRef Source,
@@ -255,7 +255,7 @@ static inline bool ConvertUTF8toWideInternal(llvm::StringRef Source,
return true;
}
@@ -862,7 +861,7 @@ index 76ead00c977bd37147048d321b425a9a9e76497a..39f151c716dacfef07038551add0f84a
return ConvertUTF8toWideInternal(Source, Result);
}
@@ -264,7 +265,7 @@ bool ConvertUTF8toWide(const char *Source, std::wstring &Result) {
@@ -264,7 +264,7 @@ bool ConvertUTF8toWide(const char *Source, std::wstring &Result) {
Result.clear();
return true;
}
@@ -871,7 +870,7 @@ index 76ead00c977bd37147048d321b425a9a9e76497a..39f151c716dacfef07038551add0f84a
}
bool convertWideToUTF8(const std::wstring &Source, std::string &Result) {
@@ -279,7 +280,7 @@ bool convertWideToUTF8(const std::wstring &Source, std::string &Result) {
@@ -279,7 +279,7 @@ bool convertWideToUTF8(const std::wstring &Source, std::string &Result) {
return true;
} else if (sizeof(wchar_t) == 2) {
return convertUTF16ToUTF8String(
@@ -880,6 +879,11 @@ index 76ead00c977bd37147048d321b425a9a9e76497a..39f151c716dacfef07038551add0f84a
Source.size()),
Result);
} else if (sizeof(wchar_t) == 4) {
@@ -314,4 +314,3 @@ bool IsSingleCodeUnitUTF32Codepoint(unsigned V) {
}
} // end namespace llvm
-
diff --git a/llvm/lib/Support/ErrorHandling.cpp b/llvm/lib/Support/ErrorHandling.cpp
index 097041f1ae282a0387da8f839e5e37fe350d5d51..fc9d118e85508cdf86553bb63cce4a1c567045b7 100644
--- a/llvm/lib/Support/ErrorHandling.cpp

View File

@@ -26,7 +26,7 @@ index a47d68406acf38350a67ce846af4f0c1a5818db1..85152589f7e0f3d31163c5aab109cedf
namespace llvm {
diff --git a/llvm/lib/Support/ConvertUTFWrapper.cpp b/llvm/lib/Support/ConvertUTFWrapper.cpp
index 39f151c716dacfef07038551add0f84a09b0cb62..d15c9652b0b79e5ce7a708d30844d0ece3944d2c 100644
index 448dbde16986172f506c247a1cd3a78a311f1fa2..ce588eec8995e076dd28164157bed46c2039867e 100644
--- a/llvm/lib/Support/ConvertUTFWrapper.cpp
+++ b/llvm/lib/Support/ConvertUTFWrapper.cpp
@@ -7,6 +7,7 @@
@@ -35,8 +35,8 @@ index 39f151c716dacfef07038551add0f84a09b0cb62..d15c9652b0b79e5ce7a708d30844d0ec
#include "llvm/Support/ConvertUTF.h"
+#include "llvm/Support/SmallVector.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SwapByteOrder.h"
#include <span>
#include <string>
diff --git a/llvm/lib/Support/ErrorHandling.cpp b/llvm/lib/Support/ErrorHandling.cpp
index fcbc70535bf9869f72d001ec214d7046e975961a..c4366de2aec2f1730954aecfc627dd0e164481ab 100644
--- a/llvm/lib/Support/ErrorHandling.cpp

View File

@@ -42,10 +42,10 @@ index d5f66c4525dd5b2e2cdb4ab5e4d523c19e36b25f..6d746c88be56f42a1056a26d44b4ab0a
/**
* Converts a stream of raw bytes assumed to be UTF32 into a UTF8 std::string.
diff --git a/llvm/lib/Support/ConvertUTFWrapper.cpp b/llvm/lib/Support/ConvertUTFWrapper.cpp
index d15c9652b0b79e5ce7a708d30844d0ece3944d2c..a14e5a6fb155c31a5f4db6b7b39a429186825651 100644
index ce588eec8995e076dd28164157bed46c2039867e..17b2760fe5c579a61e85188d482cbc9ec28f6c09 100644
--- a/llvm/lib/Support/ConvertUTFWrapper.cpp
+++ b/llvm/lib/Support/ConvertUTFWrapper.cpp
@@ -82,7 +82,7 @@ bool hasUTF16ByteOrderMark(span<const char> S) {
@@ -81,7 +81,7 @@ bool hasUTF16ByteOrderMark(span<const char> S) {
(S[0] == '\xfe' && S[1] == '\xff')));
}
@@ -54,7 +54,7 @@ index d15c9652b0b79e5ce7a708d30844d0ece3944d2c..a14e5a6fb155c31a5f4db6b7b39a4291
assert(Out.empty());
// Error out on an uneven byte count.
@@ -133,7 +133,7 @@ bool convertUTF16ToUTF8String(span<const char> SrcBytes, std::string &Out) {
@@ -132,7 +132,7 @@ bool convertUTF16ToUTF8String(span<const char> SrcBytes, std::string &Out) {
return true;
}
@@ -63,7 +63,7 @@ index d15c9652b0b79e5ce7a708d30844d0ece3944d2c..a14e5a6fb155c31a5f4db6b7b39a4291
return convertUTF16ToUTF8String(
span<const char>(reinterpret_cast<const char *>(Src.data()),
Src.size() * sizeof(UTF16)),
@@ -269,7 +269,7 @@ bool ConvertUTF8toWide(const char *Source, std::wstring &Result) {
@@ -268,7 +268,7 @@ bool ConvertUTF8toWide(const char *Source, std::wstring &Result) {
return ConvertUTF8toWide(std::string_view(Source), Result);
}

View File

@@ -7,9 +7,11 @@ Subject: [PATCH 25/34] Use C++20 <bit> header
llvm/include/llvm/ADT/DenseMap.h | 1 +
llvm/include/llvm/ADT/PointerUnion.h | 2 +-
llvm/include/llvm/ADT/SmallPtrSet.h | 6 +-
llvm/include/llvm/ADT/bit.h | 286 -------------------------
llvm/include/llvm/Support/MathExtras.h | 23 +-
5 files changed, 17 insertions(+), 301 deletions(-)
llvm/include/llvm/Support/Endian.h | 159 +++++++++++++------------
llvm/include/llvm/Support/MathExtras.h | 23 ++--
llvm/lib/Support/ConvertUTFWrapper.cpp | 5 +-
llvm/unittests/Support/EndianTest.cpp | 60 ++++------
7 files changed, 125 insertions(+), 131 deletions(-)
diff --git a/llvm/include/llvm/ADT/DenseMap.h b/llvm/include/llvm/ADT/DenseMap.h
index 41199ac39da56994d9086600e6dfc1dad2c93ce0..2c23fa2d268d34429faa0ed7b1d889c2c5ea4f9c 100644
@@ -67,310 +69,412 @@ index c07de1a110479ed625b112cc5b30d0bd5d56430f..474aa405d789e8c291d3bfc16a653ad0
/// SmallStorage - Fixed size storage used in 'small mode'.
const void *SmallStorage[SmallSizePowTwo];
diff --git a/llvm/include/llvm/ADT/bit.h b/llvm/include/llvm/ADT/bit.h
index 5971b75045b6b5f40b46900b685faf2e475c5a7f..3426ea7602a95f7292ec262ed246527c840dc176 100644
--- a/llvm/include/llvm/ADT/bit.h
+++ b/llvm/include/llvm/ADT/bit.h
@@ -28,44 +28,6 @@
#include <cstdlib> // for _byteswap_{ushort,ulong,uint64}
#endif
diff --git a/llvm/include/llvm/Support/Endian.h b/llvm/include/llvm/Support/Endian.h
index f5f4381c1003572024223da4825363d93a60aad9..1c5e447374e5dc1738a1e3fc6511395ef0829820 100644
--- a/llvm/include/llvm/Support/Endian.h
+++ b/llvm/include/llvm/Support/Endian.h
@@ -16,6 +16,7 @@
#include "llvm/ADT/bit.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/SwapByteOrder.h"
+#include <bit>
#include <cassert>
#include <cstddef>
#include <cstdint>
@@ -41,25 +42,25 @@ struct PickAlignment {
namespace endian {
-#if defined(__linux__) || defined(__GNU__) || defined(__HAIKU__) || \
- defined(__Fuchsia__) || defined(__EMSCRIPTEN__) || defined(__NetBSD__) || \
- defined(__OpenBSD__) || defined(__DragonFly__) || defined(__managarm__)
-#include <endian.h>
-#elif defined(_AIX)
-#include <sys/machine.h>
-#elif defined(__sun)
-/* Solaris provides _BIG_ENDIAN/_LITTLE_ENDIAN selector in sys/types.h */
-#include <sys/types.h>
-#define BIG_ENDIAN 4321
-#define LITTLE_ENDIAN 1234
-#if defined(_BIG_ENDIAN)
-#define BYTE_ORDER BIG_ENDIAN
-#else
-#define BYTE_ORDER LITTLE_ENDIAN
-#endif
-#elif defined(__MVS__)
-#define BIG_ENDIAN 4321
-#define LITTLE_ENDIAN 1234
-#define BYTE_ORDER BIG_ENDIAN
-#else
-#if !defined(BYTE_ORDER) && !defined(_WIN32)
-#include <machine/endian.h>
-#endif
-#endif
-
-#ifdef _MSC_VER
-// Declare these intrinsics manually rather including intrin.h. It's very
-// expensive, and bit.h is popular via MathExtras.h.
-// #include <intrin.h>
-extern "C" {
-unsigned char _BitScanForward(unsigned long *_Index, unsigned long _Mask);
-unsigned char _BitScanForward64(unsigned long *_Index, unsigned __int64 _Mask);
-unsigned char _BitScanReverse(unsigned long *_Index, unsigned long _Mask);
-unsigned char _BitScanReverse64(unsigned long *_Index, unsigned __int64 _Mask);
-}
-#endif
-
namespace llvm {
enum class endianness {
@@ -143,254 +105,6 @@ template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
}
template <typename value_type>
-[[nodiscard]] inline value_type byte_swap(value_type value, endianness endian) {
- if (endian != llvm::endianness::native)
- sys::swapByteOrder(value);
+[[nodiscard]] inline value_type byte_swap(value_type value, std::endian endian) {
+ if (endian != std::endian::native)
+ return std::byteswap(value);
return value;
}
-template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
-[[nodiscard]] constexpr inline bool has_single_bit(T Value) noexcept {
- return (Value != 0) && ((Value & (Value - 1)) == 0);
-}
-
-/// Count the number of set bits in a value.
-/// Ex. popcount(0xF000F000) = 8
-/// Returns 0 if Value is zero.
-template <typename T> [[nodiscard]] constexpr int popcount(T Value) noexcept {
- static_assert(std::is_unsigned_v<T>, "T must be an unsigned integer type");
- static_assert(sizeof(T) <= 8, "T must be 8 bytes or less");
-
- if constexpr (sizeof(T) <= 4) {
-#if defined(__GNUC__)
- return (int)__builtin_popcount(Value);
-#else
- uint32_t V = Value;
- V = V - ((V >> 1) & 0x55555555);
- V = (V & 0x33333333) + ((V >> 2) & 0x33333333);
- return int(((V + (V >> 4) & 0xF0F0F0F) * 0x1010101) >> 24);
-#endif
- } else {
-#if defined(__GNUC__)
- return (int)__builtin_popcountll(Value);
-#else
- uint64_t V = Value;
- V = V - ((V >> 1) & 0x5555555555555555ULL);
- V = (V & 0x3333333333333333ULL) + ((V >> 2) & 0x3333333333333333ULL);
- V = (V + (V >> 4)) & 0x0F0F0F0F0F0F0F0FULL;
- return int((uint64_t)(V * 0x0101010101010101ULL) >> 56);
-#endif
- }
-}
-
-/// Count number of 0's from the least significant bit to the most
-/// stopping at the first 1.
-///
-/// A constexpr version of countr_zero.
-///
-/// Only unsigned integral types are allowed.
-///
-/// Returns std::numeric_limits<T>::digits on an input of 0.
-template <typename T> [[nodiscard]] constexpr int countr_zero_constexpr(T Val) {
- static_assert(std::is_unsigned_v<T>,
- "Only unsigned integral types are allowed.");
- // "(Val & -Val) - 1" generates a mask with all bits set up to (but not
- // including) the least significant set bit of Val.
- return llvm::popcount(static_cast<std::make_unsigned_t<T>>((Val & -Val) - 1));
-}
-
-/// Count number of 0's from the least significant bit to the most
-/// stopping at the first 1.
-///
-/// Only unsigned integral types are allowed.
-///
-/// Returns std::numeric_limits<T>::digits on an input of 0.
-template <typename T> [[nodiscard]] int countr_zero(T Val) {
- static_assert(std::is_unsigned_v<T>,
- "Only unsigned integral types are allowed.");
- if (!Val)
- return std::numeric_limits<T>::digits;
-
- // Use the intrinsic if available.
- if constexpr (sizeof(T) <= 4) {
-#if __has_builtin(__builtin_ctz) || defined(__GNUC__)
- return __builtin_ctz(Val);
-#elif defined(_MSC_VER)
- unsigned long Index;
- _BitScanForward(&Index, Val);
- return Index;
-#endif
- } else if constexpr (sizeof(T) == 8) {
-#if __has_builtin(__builtin_ctzll) || defined(__GNUC__)
- return __builtin_ctzll(Val);
-#elif defined(_MSC_VER) && defined(_M_X64)
- unsigned long Index;
- _BitScanForward64(&Index, Val);
- return Index;
-#endif
- }
-
- return countr_zero_constexpr(Val);
-}
-
-/// Count number of 0's from the most significant bit to the least
-/// stopping at the first 1.
-///
-/// Only unsigned integral types are allowed.
-///
-/// Returns std::numeric_limits<T>::digits on an input of 0.
-template <typename T> [[nodiscard]] int countl_zero(T Val) {
- static_assert(std::is_unsigned_v<T>,
- "Only unsigned integral types are allowed.");
- if (!Val)
- return std::numeric_limits<T>::digits;
-
- // Use the intrinsic if available.
- if constexpr (sizeof(T) == 4) {
-#if __has_builtin(__builtin_clz) || defined(__GNUC__)
- return __builtin_clz(Val);
-#elif defined(_MSC_VER)
- unsigned long Index;
- _BitScanReverse(&Index, Val);
- return Index ^ 31;
-#endif
- } else if constexpr (sizeof(T) == 8) {
-#if __has_builtin(__builtin_clzll) || defined(__GNUC__)
- return __builtin_clzll(Val);
-#elif defined(_MSC_VER) && defined(_M_X64)
- unsigned long Index;
- _BitScanReverse64(&Index, Val);
- return Index ^ 63;
-#endif
- }
-
- // Fall back to the bisection method.
- unsigned ZeroBits = 0;
- for (T Shift = std::numeric_limits<T>::digits >> 1; Shift; Shift >>= 1) {
- T Tmp = Val >> Shift;
- if (Tmp)
- Val = Tmp;
- else
- ZeroBits |= Shift;
- }
- return ZeroBits;
-}
-
-/// Count the number of ones from the most significant bit to the first
-/// zero bit.
-///
-/// Ex. countl_one(0xFF0FFF00) == 8.
-/// Only unsigned integral types are allowed.
-///
-/// Returns std::numeric_limits<T>::digits on an input of all ones.
-template <typename T> [[nodiscard]] int countl_one(T Value) {
- static_assert(std::is_unsigned_v<T>,
- "Only unsigned integral types are allowed.");
- return llvm::countl_zero<T>(~Value);
-}
-
-/// Count the number of ones from the least significant bit to the first
-/// zero bit.
-///
-/// Ex. countr_one(0x00FF00FF) == 8.
-/// Only unsigned integral types are allowed.
-///
-/// Returns std::numeric_limits<T>::digits on an input of all ones.
-template <typename T> [[nodiscard]] int countr_one(T Value) {
- static_assert(std::is_unsigned_v<T>,
- "Only unsigned integral types are allowed.");
- return llvm::countr_zero<T>(~Value);
-}
-
-/// Returns the number of bits needed to represent Value if Value is nonzero.
-/// Returns 0 otherwise.
-///
-/// Ex. bit_width(5) == 3.
-template <typename T> [[nodiscard]] int bit_width(T Value) {
- static_assert(std::is_unsigned_v<T>,
- "Only unsigned integral types are allowed.");
- return std::numeric_limits<T>::digits - llvm::countl_zero(Value);
-}
-
-/// Returns the number of bits needed to represent Value if Value is nonzero.
-/// Returns 0 otherwise.
-///
-/// A constexpr version of bit_width.
-///
-/// Ex. bit_width_constexpr(5) == 3.
-template <typename T> [[nodiscard]] constexpr int bit_width_constexpr(T Value) {
- static_assert(std::is_unsigned_v<T>,
- "Only unsigned integral types are allowed.");
- int Width = 0;
- while (Value > 0) {
- Value >>= 1;
- ++Width;
- }
- return Width;
-}
-
-/// Returns the largest integral power of two no greater than Value if Value is
-/// nonzero. Returns 0 otherwise.
-///
-/// Ex. bit_floor(5) == 4.
-template <typename T> [[nodiscard]] T bit_floor(T Value) {
- static_assert(std::is_unsigned_v<T>,
- "Only unsigned integral types are allowed.");
- if (!Value)
- return 0;
- return T(1) << (llvm::bit_width(Value) - 1);
-}
-
-/// Returns the smallest integral power of two no smaller than Value if Value is
-/// nonzero. Returns 1 otherwise.
-///
-/// Ex. bit_ceil(5) == 8.
-///
-/// The return value is undefined if the input is larger than the largest power
-/// of two representable in T.
-template <typename T> [[nodiscard]] T bit_ceil(T Value) {
- static_assert(std::is_unsigned_v<T>,
- "Only unsigned integral types are allowed.");
- if (Value < 2)
- return 1;
- return T(1) << llvm::bit_width<T>(Value - 1u);
-}
-
-/// Returns the smallest integral power of two no smaller than Value if Value is
-/// nonzero. Returns 1 otherwise.
-///
-/// Ex. bit_ceil(5) == 8.
-///
-/// The return value is undefined if the input is larger than the largest power
-/// of two representable in T.
-template <typename T> [[nodiscard]] constexpr T bit_ceil_constexpr(T Value) {
- static_assert(std::is_unsigned_v<T>,
- "Only unsigned integral types are allowed.");
- if (Value < 2)
- return 1;
- return T(1) << llvm::bit_width_constexpr<T>(Value - 1u);
-}
-
-template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
-[[nodiscard]] constexpr T rotl(T V, int R) {
- constexpr unsigned N = std::numeric_limits<T>::digits;
-
- static_assert(has_single_bit(N), "& (N - 1) is only valid for powers of two");
- R = R & (N - 1);
-
- if (R == 0)
- return V;
-
- return (V << R) | (V >> (N - R));
-}
-
-template <typename T, typename = std::enable_if_t<std::is_unsigned_v<T>>>
-[[nodiscard]] constexpr T rotr(T V, int R) {
- constexpr unsigned N = std::numeric_limits<T>::digits;
-
- static_assert(has_single_bit(N), "& (N - 1) is only valid for powers of two");
- R = R & (N - 1);
-
- if (R == 0)
- return V;
-
- return (V >> R) | (V << (N - R));
-}
-
} // namespace llvm
/// Swap the bytes of value to match the given endianness.
-template <typename value_type, endianness endian>
+template <typename value_type, std::endian endian>
[[nodiscard]]
LLVM_DEPRECATED("Pass endian as a function argument instead",
"byte_swap") inline value_type byte_swap(value_type value) {
- if constexpr (endian != llvm::endianness::native)
- sys::swapByteOrder(value);
+ if constexpr (endian != std::endian::native)
+ return std::byteswap(value);
return value;
}
#endif
/// Read a value of a particular endianness from memory.
template <typename value_type, std::size_t alignment = unaligned>
-[[nodiscard]] inline value_type read(const void *memory, endianness endian) {
+[[nodiscard]] inline value_type read(const void *memory, std::endian endian) {
value_type ret;
memcpy(static_cast<void *>(&ret),
@@ -69,7 +70,7 @@ template <typename value_type, std::size_t alignment = unaligned>
return byte_swap<value_type>(ret, endian);
}
-template <typename value_type, endianness endian, std::size_t alignment>
+template <typename value_type, std::endian endian, std::size_t alignment>
[[nodiscard]] LLVM_DEPRECATED("Pass endian as a function argument instead",
"read") inline value_type
read(const void *memory) {
@@ -81,13 +82,13 @@ template <typename value_type, endianness endian, std::size_t alignment>
template <typename value_type, std::size_t alignment = unaligned,
typename CharT>
[[nodiscard]] inline value_type readNext(const CharT *&memory,
- endianness endian) {
+ std::endian endian) {
value_type ret = read<value_type, alignment>(memory, endian);
memory += sizeof(value_type);
return ret;
}
-template <typename value_type, endianness endian,
+template <typename value_type, std::endian endian,
std::size_t alignment = unaligned, typename CharT>
[[nodiscard]] inline value_type readNext(const CharT *&memory) {
return readNext<value_type, alignment, CharT>(memory, endian);
@@ -95,14 +96,14 @@ template <typename value_type, endianness endian,
/// Write a value to memory with a particular endianness.
template <typename value_type, std::size_t alignment = unaligned>
-inline void write(void *memory, value_type value, endianness endian) {
+inline void write(void *memory, value_type value, std::endian endian) {
value = byte_swap<value_type>(value, endian);
memcpy(LLVM_ASSUME_ALIGNED(
memory, (detail::PickAlignment<value_type, alignment>::value)),
&value, sizeof(value_type));
}
-template <typename value_type, endianness endian, std::size_t alignment>
+template <typename value_type, std::endian endian, std::size_t alignment>
LLVM_DEPRECATED("Pass endian as a function argument instead", "write")
inline void write(void *memory, value_type value) {
write<value_type, alignment>(memory, value, endian);
@@ -112,12 +113,12 @@ inline void write(void *memory, value_type value) {
/// value.
template <typename value_type, std::size_t alignment = unaligned,
typename CharT>
-inline void writeNext(CharT *&memory, value_type value, endianness endian) {
+inline void writeNext(CharT *&memory, value_type value, std::endian endian) {
write(memory, value, endian);
memory += sizeof(value_type);
}
-template <typename value_type, endianness endian,
+template <typename value_type, std::endian endian,
std::size_t alignment = unaligned, typename CharT>
inline void writeNext(CharT *&memory, value_type value) {
writeNext<value_type, alignment, CharT>(memory, value, endian);
@@ -128,7 +129,7 @@ using make_unsigned_t = std::make_unsigned_t<value_type>;
/// Read a value of a particular endianness from memory, for a location
/// that starts at the given bit offset within the first byte.
-template <typename value_type, endianness endian, std::size_t alignment>
+template <typename value_type, std::endian endian, std::size_t alignment>
[[nodiscard]] inline value_type readAtBitAlignment(const void *memory,
uint64_t startBit) {
assert(startBit < 8);
@@ -163,7 +164,7 @@ template <typename value_type, endianness endian, std::size_t alignment>
/// Write a value to memory with a particular endianness, for a location
/// that starts at the given bit offset within the first byte.
-template <typename value_type, endianness endian, std::size_t alignment>
+template <typename value_type, std::endian endian, std::size_t alignment>
inline void writeAtBitAlignment(void *memory, value_type value,
uint64_t startBit) {
assert(startBit < 8);
@@ -217,11 +218,11 @@ inline void writeAtBitAlignment(void *memory, value_type value,
namespace detail {
-template <typename ValueType, endianness Endian, std::size_t Alignment,
+template <typename ValueType, std::endian Endian, std::size_t Alignment,
std::size_t ALIGN = PickAlignment<ValueType, Alignment>::value>
struct packed_endian_specific_integral {
using value_type = ValueType;
- static constexpr endianness endian = Endian;
+ static constexpr std::endian endian = Endian;
static constexpr std::size_t alignment = Alignment;
packed_endian_specific_integral() = default;
@@ -284,210 +285,210 @@ public:
} // end namespace detail
using ulittle8_t =
- detail::packed_endian_specific_integral<uint8_t, llvm::endianness::little,
+ detail::packed_endian_specific_integral<uint8_t, std::endian::little,
unaligned>;
using ulittle16_t =
- detail::packed_endian_specific_integral<uint16_t, llvm::endianness::little,
+ detail::packed_endian_specific_integral<uint16_t, std::endian::little,
unaligned>;
using ulittle32_t =
- detail::packed_endian_specific_integral<uint32_t, llvm::endianness::little,
+ detail::packed_endian_specific_integral<uint32_t, std::endian::little,
unaligned>;
using ulittle64_t =
- detail::packed_endian_specific_integral<uint64_t, llvm::endianness::little,
+ detail::packed_endian_specific_integral<uint64_t, std::endian::little,
unaligned>;
using little16_t =
- detail::packed_endian_specific_integral<int16_t, llvm::endianness::little,
+ detail::packed_endian_specific_integral<int16_t, std::endian::little,
unaligned>;
using little32_t =
- detail::packed_endian_specific_integral<int32_t, llvm::endianness::little,
+ detail::packed_endian_specific_integral<int32_t, std::endian::little,
unaligned>;
using little64_t =
- detail::packed_endian_specific_integral<int64_t, llvm::endianness::little,
+ detail::packed_endian_specific_integral<int64_t, std::endian::little,
unaligned>;
using aligned_ulittle16_t =
- detail::packed_endian_specific_integral<uint16_t, llvm::endianness::little,
+ detail::packed_endian_specific_integral<uint16_t, std::endian::little,
aligned>;
using aligned_ulittle32_t =
- detail::packed_endian_specific_integral<uint32_t, llvm::endianness::little,
+ detail::packed_endian_specific_integral<uint32_t, std::endian::little,
aligned>;
using aligned_ulittle64_t =
- detail::packed_endian_specific_integral<uint64_t, llvm::endianness::little,
+ detail::packed_endian_specific_integral<uint64_t, std::endian::little,
aligned>;
using aligned_little16_t =
- detail::packed_endian_specific_integral<int16_t, llvm::endianness::little,
+ detail::packed_endian_specific_integral<int16_t, std::endian::little,
aligned>;
using aligned_little32_t =
- detail::packed_endian_specific_integral<int32_t, llvm::endianness::little,
+ detail::packed_endian_specific_integral<int32_t, std::endian::little,
aligned>;
using aligned_little64_t =
- detail::packed_endian_specific_integral<int64_t, llvm::endianness::little,
+ detail::packed_endian_specific_integral<int64_t, std::endian::little,
aligned>;
using ubig16_t =
- detail::packed_endian_specific_integral<uint16_t, llvm::endianness::big,
+ detail::packed_endian_specific_integral<uint16_t, std::endian::big,
unaligned>;
using ubig32_t =
- detail::packed_endian_specific_integral<uint32_t, llvm::endianness::big,
+ detail::packed_endian_specific_integral<uint32_t, std::endian::big,
unaligned>;
using ubig64_t =
- detail::packed_endian_specific_integral<uint64_t, llvm::endianness::big,
+ detail::packed_endian_specific_integral<uint64_t, std::endian::big,
unaligned>;
using big16_t =
- detail::packed_endian_specific_integral<int16_t, llvm::endianness::big,
+ detail::packed_endian_specific_integral<int16_t, std::endian::big,
unaligned>;
using big32_t =
- detail::packed_endian_specific_integral<int32_t, llvm::endianness::big,
+ detail::packed_endian_specific_integral<int32_t, std::endian::big,
unaligned>;
using big64_t =
- detail::packed_endian_specific_integral<int64_t, llvm::endianness::big,
+ detail::packed_endian_specific_integral<int64_t, std::endian::big,
unaligned>;
using aligned_ubig16_t =
- detail::packed_endian_specific_integral<uint16_t, llvm::endianness::big,
+ detail::packed_endian_specific_integral<uint16_t, std::endian::big,
aligned>;
using aligned_ubig32_t =
- detail::packed_endian_specific_integral<uint32_t, llvm::endianness::big,
+ detail::packed_endian_specific_integral<uint32_t, std::endian::big,
aligned>;
using aligned_ubig64_t =
- detail::packed_endian_specific_integral<uint64_t, llvm::endianness::big,
+ detail::packed_endian_specific_integral<uint64_t, std::endian::big,
aligned>;
using aligned_big16_t =
- detail::packed_endian_specific_integral<int16_t, llvm::endianness::big,
+ detail::packed_endian_specific_integral<int16_t, std::endian::big,
aligned>;
using aligned_big32_t =
- detail::packed_endian_specific_integral<int32_t, llvm::endianness::big,
+ detail::packed_endian_specific_integral<int32_t, std::endian::big,
aligned>;
using aligned_big64_t =
- detail::packed_endian_specific_integral<int64_t, llvm::endianness::big,
+ detail::packed_endian_specific_integral<int64_t, std::endian::big,
aligned>;
using unaligned_uint16_t =
- detail::packed_endian_specific_integral<uint16_t, llvm::endianness::native,
+ detail::packed_endian_specific_integral<uint16_t, std::endian::native,
unaligned>;
using unaligned_uint32_t =
- detail::packed_endian_specific_integral<uint32_t, llvm::endianness::native,
+ detail::packed_endian_specific_integral<uint32_t, std::endian::native,
unaligned>;
using unaligned_uint64_t =
- detail::packed_endian_specific_integral<uint64_t, llvm::endianness::native,
+ detail::packed_endian_specific_integral<uint64_t, std::endian::native,
unaligned>;
using unaligned_int16_t =
- detail::packed_endian_specific_integral<int16_t, llvm::endianness::native,
+ detail::packed_endian_specific_integral<int16_t, std::endian::native,
unaligned>;
using unaligned_int32_t =
- detail::packed_endian_specific_integral<int32_t, llvm::endianness::native,
+ detail::packed_endian_specific_integral<int32_t, std::endian::native,
unaligned>;
using unaligned_int64_t =
- detail::packed_endian_specific_integral<int64_t, llvm::endianness::native,
+ detail::packed_endian_specific_integral<int64_t, std::endian::native,
unaligned>;
template <typename T>
using little_t =
- detail::packed_endian_specific_integral<T, llvm::endianness::little,
+ detail::packed_endian_specific_integral<T, std::endian::little,
unaligned>;
template <typename T>
-using big_t = detail::packed_endian_specific_integral<T, llvm::endianness::big,
+using big_t = detail::packed_endian_specific_integral<T, std::endian::big,
unaligned>;
template <typename T>
using aligned_little_t =
- detail::packed_endian_specific_integral<T, llvm::endianness::little,
+ detail::packed_endian_specific_integral<T, std::endian::little,
aligned>;
template <typename T>
using aligned_big_t =
- detail::packed_endian_specific_integral<T, llvm::endianness::big, aligned>;
+ detail::packed_endian_specific_integral<T, std::endian::big, aligned>;
namespace endian {
-template <typename T, endianness E> [[nodiscard]] inline T read(const void *P) {
+template <typename T, std::endian E> [[nodiscard]] inline T read(const void *P) {
return *(const detail::packed_endian_specific_integral<T, E, unaligned> *)P;
}
-[[nodiscard]] inline uint16_t read16(const void *P, endianness E) {
+[[nodiscard]] inline uint16_t read16(const void *P, std::endian E) {
return read<uint16_t>(P, E);
}
-[[nodiscard]] inline uint32_t read32(const void *P, endianness E) {
+[[nodiscard]] inline uint32_t read32(const void *P, std::endian E) {
return read<uint32_t>(P, E);
}
-[[nodiscard]] inline uint64_t read64(const void *P, endianness E) {
+[[nodiscard]] inline uint64_t read64(const void *P, std::endian E) {
return read<uint64_t>(P, E);
}
-template <endianness E> [[nodiscard]] inline uint16_t read16(const void *P) {
+template <std::endian E> [[nodiscard]] inline uint16_t read16(const void *P) {
return read<uint16_t, E>(P);
}
-template <endianness E> [[nodiscard]] inline uint32_t read32(const void *P) {
+template <std::endian E> [[nodiscard]] inline uint32_t read32(const void *P) {
return read<uint32_t, E>(P);
}
-template <endianness E> [[nodiscard]] inline uint64_t read64(const void *P) {
+template <std::endian E> [[nodiscard]] inline uint64_t read64(const void *P) {
return read<uint64_t, E>(P);
}
[[nodiscard]] inline uint16_t read16le(const void *P) {
- return read16<llvm::endianness::little>(P);
+ return read16<std::endian::little>(P);
}
[[nodiscard]] inline uint32_t read32le(const void *P) {
- return read32<llvm::endianness::little>(P);
+ return read32<std::endian::little>(P);
}
[[nodiscard]] inline uint64_t read64le(const void *P) {
- return read64<llvm::endianness::little>(P);
+ return read64<std::endian::little>(P);
}
[[nodiscard]] inline uint16_t read16be(const void *P) {
- return read16<llvm::endianness::big>(P);
+ return read16<std::endian::big>(P);
}
[[nodiscard]] inline uint32_t read32be(const void *P) {
- return read32<llvm::endianness::big>(P);
+ return read32<std::endian::big>(P);
}
[[nodiscard]] inline uint64_t read64be(const void *P) {
- return read64<llvm::endianness::big>(P);
+ return read64<std::endian::big>(P);
}
-template <typename T, endianness E> inline void write(void *P, T V) {
+template <typename T, std::endian E> inline void write(void *P, T V) {
*(detail::packed_endian_specific_integral<T, E, unaligned> *)P = V;
}
-inline void write16(void *P, uint16_t V, endianness E) {
+inline void write16(void *P, uint16_t V, std::endian E) {
write<uint16_t>(P, V, E);
}
-inline void write32(void *P, uint32_t V, endianness E) {
+inline void write32(void *P, uint32_t V, std::endian E) {
write<uint32_t>(P, V, E);
}
-inline void write64(void *P, uint64_t V, endianness E) {
+inline void write64(void *P, uint64_t V, std::endian E) {
write<uint64_t>(P, V, E);
}
-template <endianness E> inline void write16(void *P, uint16_t V) {
+template <std::endian E> inline void write16(void *P, uint16_t V) {
write<uint16_t, E>(P, V);
}
-template <endianness E> inline void write32(void *P, uint32_t V) {
+template <std::endian E> inline void write32(void *P, uint32_t V) {
write<uint32_t, E>(P, V);
}
-template <endianness E> inline void write64(void *P, uint64_t V) {
+template <std::endian E> inline void write64(void *P, uint64_t V) {
write<uint64_t, E>(P, V);
}
inline void write16le(void *P, uint16_t V) {
- write16<llvm::endianness::little>(P, V);
+ write16<std::endian::little>(P, V);
}
inline void write32le(void *P, uint32_t V) {
- write32<llvm::endianness::little>(P, V);
+ write32<std::endian::little>(P, V);
}
inline void write64le(void *P, uint64_t V) {
- write64<llvm::endianness::little>(P, V);
+ write64<std::endian::little>(P, V);
}
inline void write16be(void *P, uint16_t V) {
- write16<llvm::endianness::big>(P, V);
+ write16<std::endian::big>(P, V);
}
inline void write32be(void *P, uint32_t V) {
- write32<llvm::endianness::big>(P, V);
+ write32<std::endian::big>(P, V);
}
inline void write64be(void *P, uint64_t V) {
- write64<llvm::endianness::big>(P, V);
+ write64<std::endian::big>(P, V);
}
} // end namespace endian
diff --git a/llvm/include/llvm/Support/MathExtras.h b/llvm/include/llvm/Support/MathExtras.h
index 0735d9c9f756349a19c5aa2ec34ceca5d8274f16..38b1486c54be5102025192b3b90e86e54ab347c0 100644
--- a/llvm/include/llvm/Support/MathExtras.h
@@ -460,3 +564,227 @@ index 0735d9c9f756349a19c5aa2ec34ceca5d8274f16..38b1486c54be5102025192b3b90e86e5
}
/// A and B are either alignments or offsets. Return the minimum alignment that
diff --git a/llvm/lib/Support/ConvertUTFWrapper.cpp b/llvm/lib/Support/ConvertUTFWrapper.cpp
index 17b2760fe5c579a61e85188d482cbc9ec28f6c09..7f5d8958230414edf9db69ff08dd36d02c00f37d 100644
--- a/llvm/lib/Support/ConvertUTFWrapper.cpp
+++ b/llvm/lib/Support/ConvertUTFWrapper.cpp
@@ -9,6 +9,7 @@
#include "llvm/Support/ConvertUTF.h"
#include "llvm/Support/SmallVector.h"
#include "llvm/Support/ErrorHandling.h"
+#include <bit>
#include <span>
#include <string>
#include <string_view>
@@ -102,7 +103,7 @@ bool convertUTF16ToUTF8String(span<const char> SrcBytes, SmallVectorImpl<char> &
if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_SWAPPED) {
ByteSwapped.insert(ByteSwapped.end(), Src, SrcEnd);
for (UTF16 &I : ByteSwapped)
- I = llvm::byteswap<uint16_t>(I);
+ I = std::byteswap(I);
Src = &ByteSwapped[0];
SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1;
}
@@ -160,7 +161,7 @@ bool convertUTF32ToUTF8String(span<const char> SrcBytes, std::string &Out) {
if (Src[0] == UNI_UTF32_BYTE_ORDER_MARK_SWAPPED) {
ByteSwapped.insert(ByteSwapped.end(), Src, SrcEnd);
for (UTF32 &I : ByteSwapped)
- I = llvm::byteswap<uint32_t>(I);
+ I = std::byteswap(I);
Src = &ByteSwapped[0];
SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1;
}
diff --git a/llvm/unittests/Support/EndianTest.cpp b/llvm/unittests/Support/EndianTest.cpp
index 0ee631db74ac1f70ca5e9bb4cf6cdcb1d2205e57..d707fdb55c7c97b21310b48bf3c23e328dd644aa 100644
--- a/llvm/unittests/Support/EndianTest.cpp
+++ b/llvm/unittests/Support/EndianTest.cpp
@@ -24,33 +24,32 @@ TEST(Endian, Read) {
unsigned char littleval[] = {0x00, 0x04, 0x03, 0x02, 0x01};
int32_t BigAsHost = 0x00010203;
EXPECT_EQ(BigAsHost,
- (endian::read<int32_t, unaligned>(bigval, llvm::endianness::big)));
+ (endian::read<int32_t, unaligned>(bigval, std::endian::big)));
int32_t LittleAsHost = 0x02030400;
EXPECT_EQ(LittleAsHost, (endian::read<int32_t, unaligned>(
- littleval, llvm::endianness::little)));
+ littleval, std::endian::little)));
EXPECT_EQ(
- (endian::read<int32_t, unaligned>(bigval + 1, llvm::endianness::big)),
- (endian::read<int32_t, unaligned>(littleval + 1,
- llvm::endianness::little)));
+ (endian::read<int32_t, unaligned>(bigval + 1, std::endian::big)),
+ (endian::read<int32_t, unaligned>(littleval + 1, std::endian::little)));
}
TEST(Endian, WriteNext) {
unsigned char bigval[] = {0x00, 0x00}, *p = bigval;
- endian::writeNext<int16_t, llvm::endianness::big>(p, short(0xaabb));
+ endian::writeNext<int16_t, std::endian::big>(p, short(0xaabb));
EXPECT_EQ(bigval[0], 0xaa);
EXPECT_EQ(bigval[1], 0xbb);
EXPECT_EQ(p, bigval + 2);
char littleval[8] = {}, *q = littleval;
- endian::writeNext<uint32_t, llvm::endianness::little>(q, 0x44556677);
+ endian::writeNext<uint32_t, std::endian::little>(q, 0x44556677);
EXPECT_EQ(littleval[0], 0x77);
EXPECT_EQ(littleval[1], 0x66);
EXPECT_EQ(littleval[2], 0x55);
EXPECT_EQ(littleval[3], 0x44);
EXPECT_EQ(q, littleval + 4);
- endian::writeNext<uint32_t>(q, 0x11223344, llvm::endianness::little);
+ endian::writeNext<uint32_t>(q, 0x11223344, std::endian::little);
EXPECT_EQ(littleval[4], 0x44);
EXPECT_EQ(littleval[5], 0x33);
EXPECT_EQ(littleval[6], 0x22);
@@ -63,10 +62,10 @@ TEST(Endian, ReadBitAligned) {
unsigned char littleval[] = {0x3f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff};
unsigned char bigval[] = {0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0};
EXPECT_EQ(
- (endian::readAtBitAlignment<int, llvm::endianness::little, unaligned>(
+ (endian::readAtBitAlignment<int, std::endian::little, unaligned>(
&littleval[0], 6)),
0x0);
- EXPECT_EQ((endian::readAtBitAlignment<int, llvm::endianness::big, unaligned>(
+ EXPECT_EQ((endian::readAtBitAlignment<int, std::endian::big, unaligned>(
&bigval[0], 6)),
0x0);
// Test to make sure that signed right shift of 0xf0000000 is masked
@@ -74,18 +73,18 @@ TEST(Endian, ReadBitAligned) {
unsigned char littleval2[] = {0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00};
unsigned char bigval2[] = {0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
EXPECT_EQ(
- (endian::readAtBitAlignment<int, llvm::endianness::little, unaligned>(
+ (endian::readAtBitAlignment<int, std::endian::little, unaligned>(
&littleval2[0], 4)),
0x0f000000);
- EXPECT_EQ((endian::readAtBitAlignment<int, llvm::endianness::big, unaligned>(
+ EXPECT_EQ((endian::readAtBitAlignment<int, std::endian::big, unaligned>(
&bigval2[0], 4)),
0x0f000000);
// Test to make sure left shift of start bit doesn't overflow.
EXPECT_EQ(
- (endian::readAtBitAlignment<int, llvm::endianness::little, unaligned>(
+ (endian::readAtBitAlignment<int, std::endian::little, unaligned>(
&littleval2[0], 1)),
0x78000000);
- EXPECT_EQ((endian::readAtBitAlignment<int, llvm::endianness::big, unaligned>(
+ EXPECT_EQ((endian::readAtBitAlignment<int, std::endian::big, unaligned>(
&bigval2[0], 1)),
0x78000000);
// Test to make sure 64-bit int doesn't overflow.
@@ -94,11 +93,11 @@ TEST(Endian, ReadBitAligned) {
unsigned char bigval3[] = {0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
EXPECT_EQ(
- (endian::readAtBitAlignment<int64_t, llvm::endianness::little, unaligned>(
+ (endian::readAtBitAlignment<int64_t, std::endian::little, unaligned>(
&littleval3[0], 4)),
0x0f00000000000000);
EXPECT_EQ(
- (endian::readAtBitAlignment<int64_t, llvm::endianness::big, unaligned>(
+ (endian::readAtBitAlignment<int64_t, std::endian::big, unaligned>(
&bigval3[0], 4)),
0x0f00000000000000);
}
@@ -107,7 +106,7 @@ TEST(Endian, WriteBitAligned) {
// This test ensures that signed right shift of 0xffffaa is masked
// properly.
unsigned char bigval[8] = {0x00};
- endian::writeAtBitAlignment<int32_t, llvm::endianness::big, unaligned>(
+ endian::writeAtBitAlignment<int32_t, std::endian::big, unaligned>(
bigval, (int)0xffffaaaa, 4);
EXPECT_EQ(bigval[0], 0xff);
EXPECT_EQ(bigval[1], 0xfa);
@@ -119,7 +118,7 @@ TEST(Endian, WriteBitAligned) {
EXPECT_EQ(bigval[7], 0x0f);
unsigned char littleval[8] = {0x00};
- endian::writeAtBitAlignment<int32_t, llvm::endianness::little, unaligned>(
+ endian::writeAtBitAlignment<int32_t, std::endian::little, unaligned>(
littleval, (int)0xffffaaaa, 4);
EXPECT_EQ(littleval[0], 0xa0);
EXPECT_EQ(littleval[1], 0xaa);
@@ -133,7 +132,7 @@ TEST(Endian, WriteBitAligned) {
// This test makes sure 1<<31 doesn't overflow.
// Test to make sure left shift of start bit doesn't overflow.
unsigned char bigval2[8] = {0x00};
- endian::writeAtBitAlignment<int32_t, llvm::endianness::big, unaligned>(
+ endian::writeAtBitAlignment<int32_t, std::endian::big, unaligned>(
bigval2, (int)0xffffffff, 1);
EXPECT_EQ(bigval2[0], 0xff);
EXPECT_EQ(bigval2[1], 0xff);
@@ -145,7 +144,7 @@ TEST(Endian, WriteBitAligned) {
EXPECT_EQ(bigval2[7], 0x01);
unsigned char littleval2[8] = {0x00};
- endian::writeAtBitAlignment<int32_t, llvm::endianness::little, unaligned>(
+ endian::writeAtBitAlignment<int32_t, std::endian::little, unaligned>(
littleval2, (int)0xffffffff, 1);
EXPECT_EQ(littleval2[0], 0xfe);
EXPECT_EQ(littleval2[1], 0xff);
@@ -158,7 +157,7 @@ TEST(Endian, WriteBitAligned) {
// Test to make sure 64-bit int doesn't overflow.
unsigned char bigval64[16] = {0x00};
- endian::writeAtBitAlignment<int64_t, llvm::endianness::big, unaligned>(
+ endian::writeAtBitAlignment<int64_t, std::endian::big, unaligned>(
bigval64, (int64_t)0xffffffffffffffff, 1);
EXPECT_EQ(bigval64[0], 0xff);
EXPECT_EQ(bigval64[1], 0xff);
@@ -178,7 +177,7 @@ TEST(Endian, WriteBitAligned) {
EXPECT_EQ(bigval64[15], 0x01);
unsigned char littleval64[16] = {0x00};
- endian::writeAtBitAlignment<int64_t, llvm::endianness::little, unaligned>(
+ endian::writeAtBitAlignment<int64_t, std::endian::little, unaligned>(
littleval64, (int64_t)0xffffffffffffffff, 1);
EXPECT_EQ(littleval64[0], 0xfe);
EXPECT_EQ(littleval64[1], 0xff);
@@ -200,26 +199,26 @@ TEST(Endian, WriteBitAligned) {
TEST(Endian, Write) {
unsigned char data[5];
- endian::write<int32_t, unaligned>(data, -1362446643, llvm::endianness::big);
+ endian::write<int32_t, unaligned>(data, -1362446643, std::endian::big);
EXPECT_EQ(data[0], 0xAE);
EXPECT_EQ(data[1], 0xCA);
EXPECT_EQ(data[2], 0xB6);
EXPECT_EQ(data[3], 0xCD);
endian::write<int32_t, unaligned>(data + 1, -1362446643,
- llvm::endianness::big);
+ std::endian::big);
EXPECT_EQ(data[1], 0xAE);
EXPECT_EQ(data[2], 0xCA);
EXPECT_EQ(data[3], 0xB6);
EXPECT_EQ(data[4], 0xCD);
endian::write<int32_t, unaligned>(data, -1362446643,
- llvm::endianness::little);
+ std::endian::little);
EXPECT_EQ(data[0], 0xCD);
EXPECT_EQ(data[1], 0xB6);
EXPECT_EQ(data[2], 0xCA);
EXPECT_EQ(data[3], 0xAE);
endian::write<int32_t, unaligned>(data + 1, -1362446643,
- llvm::endianness::little);
+ std::endian::little);
EXPECT_EQ(data[1], 0xCD);
EXPECT_EQ(data[2], 0xB6);
EXPECT_EQ(data[3], 0xCA);
@@ -239,13 +238,4 @@ TEST(Endian, PackedEndianSpecificIntegral) {
EXPECT_EQ(big_val->value(), little_val->value());
}
-TEST(Endian, PacketEndianSpecificIntegralAsEnum) {
- enum class Test : uint16_t { ONETWO = 0x0102, TWOONE = 0x0201 };
- unsigned char bytes[] = {0x01, 0x02};
- using LittleTest = little_t<Test>;
- using BigTest = big_t<Test>;
- EXPECT_EQ(Test::TWOONE, *reinterpret_cast<LittleTest *>(bytes));
- EXPECT_EQ(Test::ONETWO, *reinterpret_cast<BigTest *>(bytes));
-}
-
} // end anon namespace

View File

@@ -6,6 +6,7 @@
#include <stdint.h>
#include <bit>
#include <cassert>
#include <span>
#include <string>
@@ -14,7 +15,6 @@
#include <vector>
#include "wpi/util/StringMap.hpp"
#include "wpi/util/bit.hpp"
namespace wpi::util {
@@ -457,7 +457,7 @@ class DynamicStruct {
float GetFloatField(const StructFieldDescriptor* field,
size_t arrIndex = 0) const {
assert(field->m_type == StructFieldType::FLOAT);
return bit_cast<float>(
return std::bit_cast<float>(
static_cast<uint32_t>(GetFieldImpl(field, arrIndex)));
}
@@ -471,7 +471,7 @@ class DynamicStruct {
double GetDoubleField(const StructFieldDescriptor* field,
size_t arrIndex = 0) const {
assert(field->m_type == StructFieldType::DOUBLE);
return bit_cast<double>(GetFieldImpl(field, arrIndex));
return std::bit_cast<double>(GetFieldImpl(field, arrIndex));
}
/**
@@ -591,7 +591,7 @@ class MutableDynamicStruct : public DynamicStruct {
void SetFloatField(const StructFieldDescriptor* field, float value,
size_t arrIndex = 0) {
assert(field->m_type == StructFieldType::FLOAT);
SetFieldImpl(field, bit_cast<uint32_t>(value), arrIndex);
SetFieldImpl(field, std::bit_cast<uint32_t>(value), arrIndex);
}
/**
@@ -604,7 +604,7 @@ class MutableDynamicStruct : public DynamicStruct {
void SetDoubleField(const StructFieldDescriptor* field, double value,
size_t arrIndex = 0) {
assert(field->m_type == StructFieldType::DOUBLE);
SetFieldImpl(field, bit_cast<uint64_t>(value), arrIndex);
SetFieldImpl(field, std::bit_cast<uint64_t>(value), arrIndex);
}
/**

View File

@@ -6,6 +6,7 @@
#include <stdint.h>
#include <bit>
#include <concepts>
#include <memory>
#include <span>
@@ -19,7 +20,6 @@
#include "wpi/util/Endian.hpp"
#include "wpi/util/array.hpp"
#include "wpi/util/bit.hpp"
#include "wpi/util/ct_string.hpp"
#include "wpi/util/function_ref.hpp"
#include "wpi/util/mutex.hpp"
@@ -687,10 +687,10 @@ struct Struct<float> {
static constexpr size_t GetSize() { return 4; }
static constexpr std::string_view GetSchema() { return "float value"; }
static float Unpack(std::span<const uint8_t> data) {
return bit_cast<float>(support::endian::read32le(data.data()));
return std::bit_cast<float>(support::endian::read32le(data.data()));
}
static void Pack(std::span<uint8_t> data, float value) {
support::endian::write32le(data.data(), bit_cast<uint32_t>(value));
support::endian::write32le(data.data(), std::bit_cast<uint32_t>(value));
}
};
@@ -704,10 +704,10 @@ struct Struct<double> {
static constexpr size_t GetSize() { return 8; }
static constexpr std::string_view GetSchema() { return "double value"; }
static double Unpack(std::span<const uint8_t> data) {
return bit_cast<double>(support::endian::read64le(data.data()));
return std::bit_cast<double>(support::endian::read64le(data.data()));
}
static void Pack(std::span<uint8_t> data, double value) {
support::endian::write64le(data.data(), bit_cast<uint64_t>(value));
support::endian::write64le(data.data(), std::bit_cast<uint64_t>(value));
}
};

View File

@@ -9,7 +9,7 @@
#include "wpi/util/ConvertUTF.hpp"
#include "wpi/util/SmallVector.hpp"
#include "wpi/util/ErrorHandling.hpp"
#include "wpi/util/SwapByteOrder.hpp"
#include <bit>
#include <span>
#include <string>
#include <string_view>
@@ -103,7 +103,7 @@ bool convertUTF16ToUTF8String(std::span<const char> SrcBytes, SmallVectorImpl<ch
if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_SWAPPED) {
ByteSwapped.insert(ByteSwapped.end(), Src, SrcEnd);
for (UTF16 &I : ByteSwapped)
I = wpi::util::byteswap<uint16_t>(I);
I = std::byteswap(I);
Src = &ByteSwapped[0];
SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1;
}
@@ -161,7 +161,7 @@ bool convertUTF32ToUTF8String(std::span<const char> SrcBytes, std::string &Out)
if (Src[0] == UNI_UTF32_BYTE_ORDER_MARK_SWAPPED) {
ByteSwapped.insert(ByteSwapped.end(), Src, SrcEnd);
for (UTF32 &I : ByteSwapped)
I = wpi::util::byteswap<uint32_t>(I);
I = std::byteswap(I);
Src = &ByteSwapped[0];
SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1;
}
@@ -316,4 +316,3 @@ bool IsSingleCodeUnitUTF32Codepoint(unsigned V) {
}
} // end namespace wpi::util

View File

@@ -13,9 +13,8 @@
#ifndef WPIUTIL_WPI_ENDIAN_H
#define WPIUTIL_WPI_ENDIAN_H
#include "wpi/util/bit.hpp"
#include "wpi/util/Compiler.hpp"
#include "wpi/util/SwapByteOrder.hpp"
#include <bit>
#include <cassert>
#include <cstddef>
#include <cstdint>
@@ -41,25 +40,25 @@ struct PickAlignment {
namespace endian {
template <typename value_type>
[[nodiscard]] inline value_type byte_swap(value_type value, endianness endian) {
if (endian != wpi::util::endianness::native)
sys::swapByteOrder(value);
[[nodiscard]] inline value_type byte_swap(value_type value, std::endian endian) {
if (endian != std::endian::native)
return std::byteswap(value);
return value;
}
/// Swap the bytes of value to match the given endianness.
template <typename value_type, endianness endian>
template <typename value_type, std::endian endian>
[[nodiscard]]
LLVM_DEPRECATED("Pass endian as a function argument instead",
"byte_swap") inline value_type byte_swap(value_type value) {
if constexpr (endian != wpi::util::endianness::native)
sys::swapByteOrder(value);
if constexpr (endian != std::endian::native)
return std::byteswap(value);
return value;
}
/// Read a value of a particular endianness from memory.
template <typename value_type, std::size_t alignment = unaligned>
[[nodiscard]] inline value_type read(const void *memory, endianness endian) {
[[nodiscard]] inline value_type read(const void *memory, std::endian endian) {
value_type ret;
memcpy(static_cast<void *>(&ret),
@@ -69,7 +68,7 @@ template <typename value_type, std::size_t alignment = unaligned>
return byte_swap<value_type>(ret, endian);
}
template <typename value_type, endianness endian, std::size_t alignment>
template <typename value_type, std::endian endian, std::size_t alignment>
[[nodiscard]] LLVM_DEPRECATED("Pass endian as a function argument instead",
"read") inline value_type
read(const void *memory) {
@@ -81,13 +80,13 @@ template <typename value_type, endianness endian, std::size_t alignment>
template <typename value_type, std::size_t alignment = unaligned,
typename CharT>
[[nodiscard]] inline value_type readNext(const CharT *&memory,
endianness endian) {
std::endian endian) {
value_type ret = read<value_type, alignment>(memory, endian);
memory += sizeof(value_type);
return ret;
}
template <typename value_type, endianness endian,
template <typename value_type, std::endian endian,
std::size_t alignment = unaligned, typename CharT>
[[nodiscard]] inline value_type readNext(const CharT *&memory) {
return readNext<value_type, alignment, CharT>(memory, endian);
@@ -95,14 +94,14 @@ template <typename value_type, endianness endian,
/// Write a value to memory with a particular endianness.
template <typename value_type, std::size_t alignment = unaligned>
inline void write(void *memory, value_type value, endianness endian) {
inline void write(void *memory, value_type value, std::endian endian) {
value = byte_swap<value_type>(value, endian);
memcpy(LLVM_ASSUME_ALIGNED(
memory, (detail::PickAlignment<value_type, alignment>::value)),
&value, sizeof(value_type));
}
template <typename value_type, endianness endian, std::size_t alignment>
template <typename value_type, std::endian endian, std::size_t alignment>
LLVM_DEPRECATED("Pass endian as a function argument instead", "write")
inline void write(void *memory, value_type value) {
write<value_type, alignment>(memory, value, endian);
@@ -112,12 +111,12 @@ inline void write(void *memory, value_type value) {
/// value.
template <typename value_type, std::size_t alignment = unaligned,
typename CharT>
inline void writeNext(CharT *&memory, value_type value, endianness endian) {
inline void writeNext(CharT *&memory, value_type value, std::endian endian) {
write(memory, value, endian);
memory += sizeof(value_type);
}
template <typename value_type, endianness endian,
template <typename value_type, std::endian endian,
std::size_t alignment = unaligned, typename CharT>
inline void writeNext(CharT *&memory, value_type value) {
writeNext<value_type, alignment, CharT>(memory, value, endian);
@@ -128,7 +127,7 @@ using make_unsigned_t = std::make_unsigned_t<value_type>;
/// Read a value of a particular endianness from memory, for a location
/// that starts at the given bit offset within the first byte.
template <typename value_type, endianness endian, std::size_t alignment>
template <typename value_type, std::endian endian, std::size_t alignment>
[[nodiscard]] inline value_type readAtBitAlignment(const void *memory,
uint64_t startBit) {
assert(startBit < 8);
@@ -163,7 +162,7 @@ template <typename value_type, endianness endian, std::size_t alignment>
/// Write a value to memory with a particular endianness, for a location
/// that starts at the given bit offset within the first byte.
template <typename value_type, endianness endian, std::size_t alignment>
template <typename value_type, std::endian endian, std::size_t alignment>
inline void writeAtBitAlignment(void *memory, value_type value,
uint64_t startBit) {
assert(startBit < 8);
@@ -217,11 +216,11 @@ inline void writeAtBitAlignment(void *memory, value_type value,
namespace detail {
template <typename ValueType, endianness Endian, std::size_t Alignment,
template <typename ValueType, std::endian Endian, std::size_t Alignment,
std::size_t ALIGN = PickAlignment<ValueType, Alignment>::value>
struct packed_endian_specific_integral {
using value_type = ValueType;
static constexpr endianness endian = Endian;
static constexpr std::endian endian = Endian;
static constexpr std::size_t alignment = Alignment;
packed_endian_specific_integral() = default;
@@ -284,210 +283,210 @@ public:
} // end namespace detail
using ulittle8_t =
detail::packed_endian_specific_integral<uint8_t, wpi::util::endianness::little,
detail::packed_endian_specific_integral<uint8_t, std::endian::little,
unaligned>;
using ulittle16_t =
detail::packed_endian_specific_integral<uint16_t, wpi::util::endianness::little,
detail::packed_endian_specific_integral<uint16_t, std::endian::little,
unaligned>;
using ulittle32_t =
detail::packed_endian_specific_integral<uint32_t, wpi::util::endianness::little,
detail::packed_endian_specific_integral<uint32_t, std::endian::little,
unaligned>;
using ulittle64_t =
detail::packed_endian_specific_integral<uint64_t, wpi::util::endianness::little,
detail::packed_endian_specific_integral<uint64_t, std::endian::little,
unaligned>;
using little16_t =
detail::packed_endian_specific_integral<int16_t, wpi::util::endianness::little,
detail::packed_endian_specific_integral<int16_t, std::endian::little,
unaligned>;
using little32_t =
detail::packed_endian_specific_integral<int32_t, wpi::util::endianness::little,
detail::packed_endian_specific_integral<int32_t, std::endian::little,
unaligned>;
using little64_t =
detail::packed_endian_specific_integral<int64_t, wpi::util::endianness::little,
detail::packed_endian_specific_integral<int64_t, std::endian::little,
unaligned>;
using aligned_ulittle16_t =
detail::packed_endian_specific_integral<uint16_t, wpi::util::endianness::little,
detail::packed_endian_specific_integral<uint16_t, std::endian::little,
aligned>;
using aligned_ulittle32_t =
detail::packed_endian_specific_integral<uint32_t, wpi::util::endianness::little,
detail::packed_endian_specific_integral<uint32_t, std::endian::little,
aligned>;
using aligned_ulittle64_t =
detail::packed_endian_specific_integral<uint64_t, wpi::util::endianness::little,
detail::packed_endian_specific_integral<uint64_t, std::endian::little,
aligned>;
using aligned_little16_t =
detail::packed_endian_specific_integral<int16_t, wpi::util::endianness::little,
detail::packed_endian_specific_integral<int16_t, std::endian::little,
aligned>;
using aligned_little32_t =
detail::packed_endian_specific_integral<int32_t, wpi::util::endianness::little,
detail::packed_endian_specific_integral<int32_t, std::endian::little,
aligned>;
using aligned_little64_t =
detail::packed_endian_specific_integral<int64_t, wpi::util::endianness::little,
detail::packed_endian_specific_integral<int64_t, std::endian::little,
aligned>;
using ubig16_t =
detail::packed_endian_specific_integral<uint16_t, wpi::util::endianness::big,
detail::packed_endian_specific_integral<uint16_t, std::endian::big,
unaligned>;
using ubig32_t =
detail::packed_endian_specific_integral<uint32_t, wpi::util::endianness::big,
detail::packed_endian_specific_integral<uint32_t, std::endian::big,
unaligned>;
using ubig64_t =
detail::packed_endian_specific_integral<uint64_t, wpi::util::endianness::big,
detail::packed_endian_specific_integral<uint64_t, std::endian::big,
unaligned>;
using big16_t =
detail::packed_endian_specific_integral<int16_t, wpi::util::endianness::big,
detail::packed_endian_specific_integral<int16_t, std::endian::big,
unaligned>;
using big32_t =
detail::packed_endian_specific_integral<int32_t, wpi::util::endianness::big,
detail::packed_endian_specific_integral<int32_t, std::endian::big,
unaligned>;
using big64_t =
detail::packed_endian_specific_integral<int64_t, wpi::util::endianness::big,
detail::packed_endian_specific_integral<int64_t, std::endian::big,
unaligned>;
using aligned_ubig16_t =
detail::packed_endian_specific_integral<uint16_t, wpi::util::endianness::big,
detail::packed_endian_specific_integral<uint16_t, std::endian::big,
aligned>;
using aligned_ubig32_t =
detail::packed_endian_specific_integral<uint32_t, wpi::util::endianness::big,
detail::packed_endian_specific_integral<uint32_t, std::endian::big,
aligned>;
using aligned_ubig64_t =
detail::packed_endian_specific_integral<uint64_t, wpi::util::endianness::big,
detail::packed_endian_specific_integral<uint64_t, std::endian::big,
aligned>;
using aligned_big16_t =
detail::packed_endian_specific_integral<int16_t, wpi::util::endianness::big,
detail::packed_endian_specific_integral<int16_t, std::endian::big,
aligned>;
using aligned_big32_t =
detail::packed_endian_specific_integral<int32_t, wpi::util::endianness::big,
detail::packed_endian_specific_integral<int32_t, std::endian::big,
aligned>;
using aligned_big64_t =
detail::packed_endian_specific_integral<int64_t, wpi::util::endianness::big,
detail::packed_endian_specific_integral<int64_t, std::endian::big,
aligned>;
using unaligned_uint16_t =
detail::packed_endian_specific_integral<uint16_t, wpi::util::endianness::native,
detail::packed_endian_specific_integral<uint16_t, std::endian::native,
unaligned>;
using unaligned_uint32_t =
detail::packed_endian_specific_integral<uint32_t, wpi::util::endianness::native,
detail::packed_endian_specific_integral<uint32_t, std::endian::native,
unaligned>;
using unaligned_uint64_t =
detail::packed_endian_specific_integral<uint64_t, wpi::util::endianness::native,
detail::packed_endian_specific_integral<uint64_t, std::endian::native,
unaligned>;
using unaligned_int16_t =
detail::packed_endian_specific_integral<int16_t, wpi::util::endianness::native,
detail::packed_endian_specific_integral<int16_t, std::endian::native,
unaligned>;
using unaligned_int32_t =
detail::packed_endian_specific_integral<int32_t, wpi::util::endianness::native,
detail::packed_endian_specific_integral<int32_t, std::endian::native,
unaligned>;
using unaligned_int64_t =
detail::packed_endian_specific_integral<int64_t, wpi::util::endianness::native,
detail::packed_endian_specific_integral<int64_t, std::endian::native,
unaligned>;
template <typename T>
using little_t =
detail::packed_endian_specific_integral<T, wpi::util::endianness::little,
detail::packed_endian_specific_integral<T, std::endian::little,
unaligned>;
template <typename T>
using big_t = detail::packed_endian_specific_integral<T, wpi::util::endianness::big,
using big_t = detail::packed_endian_specific_integral<T, std::endian::big,
unaligned>;
template <typename T>
using aligned_little_t =
detail::packed_endian_specific_integral<T, wpi::util::endianness::little,
detail::packed_endian_specific_integral<T, std::endian::little,
aligned>;
template <typename T>
using aligned_big_t =
detail::packed_endian_specific_integral<T, wpi::util::endianness::big, aligned>;
detail::packed_endian_specific_integral<T, std::endian::big, aligned>;
namespace endian {
template <typename T, endianness E> [[nodiscard]] inline T read(const void *P) {
template <typename T, std::endian E> [[nodiscard]] inline T read(const void *P) {
return *(const detail::packed_endian_specific_integral<T, E, unaligned> *)P;
}
[[nodiscard]] inline uint16_t read16(const void *P, endianness E) {
[[nodiscard]] inline uint16_t read16(const void *P, std::endian E) {
return read<uint16_t>(P, E);
}
[[nodiscard]] inline uint32_t read32(const void *P, endianness E) {
[[nodiscard]] inline uint32_t read32(const void *P, std::endian E) {
return read<uint32_t>(P, E);
}
[[nodiscard]] inline uint64_t read64(const void *P, endianness E) {
[[nodiscard]] inline uint64_t read64(const void *P, std::endian E) {
return read<uint64_t>(P, E);
}
template <endianness E> [[nodiscard]] inline uint16_t read16(const void *P) {
template <std::endian E> [[nodiscard]] inline uint16_t read16(const void *P) {
return read<uint16_t, E>(P);
}
template <endianness E> [[nodiscard]] inline uint32_t read32(const void *P) {
template <std::endian E> [[nodiscard]] inline uint32_t read32(const void *P) {
return read<uint32_t, E>(P);
}
template <endianness E> [[nodiscard]] inline uint64_t read64(const void *P) {
template <std::endian E> [[nodiscard]] inline uint64_t read64(const void *P) {
return read<uint64_t, E>(P);
}
[[nodiscard]] inline uint16_t read16le(const void *P) {
return read16<wpi::util::endianness::little>(P);
return read16<std::endian::little>(P);
}
[[nodiscard]] inline uint32_t read32le(const void *P) {
return read32<wpi::util::endianness::little>(P);
return read32<std::endian::little>(P);
}
[[nodiscard]] inline uint64_t read64le(const void *P) {
return read64<wpi::util::endianness::little>(P);
return read64<std::endian::little>(P);
}
[[nodiscard]] inline uint16_t read16be(const void *P) {
return read16<wpi::util::endianness::big>(P);
return read16<std::endian::big>(P);
}
[[nodiscard]] inline uint32_t read32be(const void *P) {
return read32<wpi::util::endianness::big>(P);
return read32<std::endian::big>(P);
}
[[nodiscard]] inline uint64_t read64be(const void *P) {
return read64<wpi::util::endianness::big>(P);
return read64<std::endian::big>(P);
}
template <typename T, endianness E> inline void write(void *P, T V) {
template <typename T, std::endian E> inline void write(void *P, T V) {
*(detail::packed_endian_specific_integral<T, E, unaligned> *)P = V;
}
inline void write16(void *P, uint16_t V, endianness E) {
inline void write16(void *P, uint16_t V, std::endian E) {
write<uint16_t>(P, V, E);
}
inline void write32(void *P, uint32_t V, endianness E) {
inline void write32(void *P, uint32_t V, std::endian E) {
write<uint32_t>(P, V, E);
}
inline void write64(void *P, uint64_t V, endianness E) {
inline void write64(void *P, uint64_t V, std::endian E) {
write<uint64_t>(P, V, E);
}
template <endianness E> inline void write16(void *P, uint16_t V) {
template <std::endian E> inline void write16(void *P, uint16_t V) {
write<uint16_t, E>(P, V);
}
template <endianness E> inline void write32(void *P, uint32_t V) {
template <std::endian E> inline void write32(void *P, uint32_t V) {
write<uint32_t, E>(P, V);
}
template <endianness E> inline void write64(void *P, uint64_t V) {
template <std::endian E> inline void write64(void *P, uint64_t V) {
write<uint64_t, E>(P, V);
}
inline void write16le(void *P, uint16_t V) {
write16<wpi::util::endianness::little>(P, V);
write16<std::endian::little>(P, V);
}
inline void write32le(void *P, uint32_t V) {
write32<wpi::util::endianness::little>(P, V);
write32<std::endian::little>(P, V);
}
inline void write64le(void *P, uint64_t V) {
write64<wpi::util::endianness::little>(P, V);
write64<std::endian::little>(P, V);
}
inline void write16be(void *P, uint16_t V) {
write16<wpi::util::endianness::big>(P, V);
write16<std::endian::big>(P, V);
}
inline void write32be(void *P, uint32_t V) {
write32<wpi::util::endianness::big>(P, V);
write32<std::endian::big>(P, V);
}
inline void write64be(void *P, uint64_t V) {
write64<wpi::util::endianness::big>(P, V);
write64<std::endian::big>(P, V);
}
} // end namespace endian

View File

@@ -14,7 +14,6 @@
#define WPIUTIL_WPI_MATHEXTRAS_H
#include "wpi/util/STLForwardCompat.hpp"
#include "wpi/util/bit.hpp"
#include "wpi/util/Compiler.hpp"
#include <bit>
#include <cassert>

View File

@@ -1,68 +0,0 @@
//===- SwapByteOrder.h - Generic and optimized byte swaps -------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This file declares generic and optimized functions to swap the byte order of
// an integral type.
//
//===----------------------------------------------------------------------===//
#ifndef WPIUTIL_WPI_SWAPBYTEORDER_H
#define WPIUTIL_WPI_SWAPBYTEORDER_H
#include "wpi/util/STLForwardCompat.hpp"
#include "wpi/util/bit.hpp"
#include <cstdint>
#include <type_traits>
namespace wpi::util {
namespace sys {
constexpr bool IsBigEndianHost =
wpi::util::endianness::native == wpi::util::endianness::big;
constexpr bool IsLittleEndianHost = !IsBigEndianHost;
inline unsigned char getSwappedBytes(unsigned char C) { return wpi::util::byteswap(C); }
inline signed char getSwappedBytes( signed char C) { return wpi::util::byteswap(C); }
inline char getSwappedBytes( char C) { return wpi::util::byteswap(C); }
inline unsigned short getSwappedBytes(unsigned short C) { return wpi::util::byteswap(C); }
inline signed short getSwappedBytes( signed short C) { return wpi::util::byteswap(C); }
inline unsigned int getSwappedBytes(unsigned int C) { return wpi::util::byteswap(C); }
inline signed int getSwappedBytes( signed int C) { return wpi::util::byteswap(C); }
inline unsigned long getSwappedBytes(unsigned long C) { return wpi::util::byteswap(C); }
inline signed long getSwappedBytes( signed long C) { return wpi::util::byteswap(C); }
inline unsigned long long getSwappedBytes(unsigned long long C) { return wpi::util::byteswap(C); }
inline signed long long getSwappedBytes( signed long long C) { return wpi::util::byteswap(C); }
inline float getSwappedBytes(float C) {
return wpi::util::bit_cast<float>(wpi::util::byteswap(wpi::util::bit_cast<uint32_t>(C)));
}
inline double getSwappedBytes(double C) {
return wpi::util::bit_cast<double>(wpi::util::byteswap(wpi::util::bit_cast<uint64_t>(C)));
}
template <typename T>
inline std::enable_if_t<std::is_enum_v<T>, T> getSwappedBytes(T C) {
return static_cast<T>(wpi::util::byteswap(wpi::util::to_underlying(C)));
}
template<typename T>
inline void swapByteOrder(T &Value) {
Value = getSwappedBytes(Value);
}
} // end namespace sys
} // end namespace wpi::util
#endif

View File

@@ -1,110 +0,0 @@
//===-- llvm/ADT/bit.h - C++20 <bit> ----------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file implements the C++20 <bit> header.
///
//===----------------------------------------------------------------------===//
#ifndef WPIUTIL_WPI_BIT_H
#define WPIUTIL_WPI_BIT_H
#include "wpi/util/Compiler.hpp"
#include <cstddef> // for std::size_t
#include <cstdint>
#include <limits>
#include <type_traits>
#if !__has_builtin(__builtin_bit_cast)
#include <cstring>
#endif
#if defined(_MSC_VER) && !defined(_DEBUG)
#include <cstdlib> // for _byteswap_{ushort,ulong,uint64}
#endif
namespace wpi::util {
enum class endianness {
big,
little,
#if defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN
native = big
#else
native = little
#endif
};
// This implementation of bit_cast is different from the C++20 one in two ways:
// - It isn't constexpr because that requires compiler support.
// - It requires trivially-constructible To, to avoid UB in the implementation.
template <
typename To, typename From,
typename = std::enable_if_t<sizeof(To) == sizeof(From)>,
typename = std::enable_if_t<std::is_trivially_constructible<To>::value>,
typename = std::enable_if_t<std::is_trivially_copyable<To>::value>,
typename = std::enable_if_t<std::is_trivially_copyable<From>::value>>
[[nodiscard]] inline To bit_cast(const From &from) noexcept {
#if __has_builtin(__builtin_bit_cast)
return __builtin_bit_cast(To, from);
#else
To to;
std::memcpy(&to, &from, sizeof(To));
return to;
#endif
}
/// Reverses the bytes in the given integer value V.
template <typename T, typename = std::enable_if_t<std::is_integral_v<T>>>
[[nodiscard]] constexpr T byteswap(T V) noexcept {
if constexpr (sizeof(T) == 1) {
return V;
} else if constexpr (sizeof(T) == 2) {
uint16_t UV = V;
#if defined(_MSC_VER) && !defined(_DEBUG)
// The DLL version of the runtime lacks these functions (bug!?), but in a
// release build they're replaced with BSWAP instructions anyway.
return _byteswap_ushort(UV);
#else
uint16_t Hi = UV << 8;
uint16_t Lo = UV >> 8;
return Hi | Lo;
#endif
} else if constexpr (sizeof(T) == 4) {
uint32_t UV = V;
#if __has_builtin(__builtin_bswap32)
return __builtin_bswap32(UV);
#elif defined(_MSC_VER) && !defined(_DEBUG)
return _byteswap_ulong(UV);
#else
uint32_t Byte0 = UV & 0x000000FF;
uint32_t Byte1 = UV & 0x0000FF00;
uint32_t Byte2 = UV & 0x00FF0000;
uint32_t Byte3 = UV & 0xFF000000;
return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24);
#endif
} else if constexpr (sizeof(T) == 8) {
uint64_t UV = V;
#if __has_builtin(__builtin_bswap64)
return __builtin_bswap64(UV);
#elif defined(_MSC_VER) && !defined(_DEBUG)
return _byteswap_uint64(UV);
#else
uint64_t Hi = wpi::util::byteswap<uint32_t>(UV);
uint32_t Lo = wpi::util::byteswap<uint32_t>(UV >> 32);
return (Hi << 32) | Lo;
#endif
} else {
static_assert(!sizeof(T *), "Don't know how to handle the given type.");
return 0;
}
}
} // namespace wpi::util
#endif

View File

@@ -23,33 +23,32 @@ TEST(Endian, Read) {
unsigned char littleval[] = {0x00, 0x04, 0x03, 0x02, 0x01};
int32_t BigAsHost = 0x00010203;
EXPECT_EQ(BigAsHost,
(endian::read<int32_t, unaligned>(bigval, wpi::util::endianness::big)));
(endian::read<int32_t, unaligned>(bigval, std::endian::big)));
int32_t LittleAsHost = 0x02030400;
EXPECT_EQ(LittleAsHost, (endian::read<int32_t, unaligned>(
littleval, wpi::util::endianness::little)));
littleval, std::endian::little)));
EXPECT_EQ(
(endian::read<int32_t, unaligned>(bigval + 1, wpi::util::endianness::big)),
(endian::read<int32_t, unaligned>(littleval + 1,
wpi::util::endianness::little)));
(endian::read<int32_t, unaligned>(bigval + 1, std::endian::big)),
(endian::read<int32_t, unaligned>(littleval + 1, std::endian::little)));
}
TEST(Endian, WriteNext) {
unsigned char bigval[] = {0x00, 0x00}, *p = bigval;
endian::writeNext<int16_t, wpi::util::endianness::big>(p, short(0xaabb));
endian::writeNext<int16_t, std::endian::big>(p, short(0xaabb));
EXPECT_EQ(bigval[0], 0xaa);
EXPECT_EQ(bigval[1], 0xbb);
EXPECT_EQ(p, bigval + 2);
char littleval[8] = {}, *q = littleval;
endian::writeNext<uint32_t, wpi::util::endianness::little>(q, 0x44556677);
endian::writeNext<uint32_t, std::endian::little>(q, 0x44556677);
EXPECT_EQ(littleval[0], 0x77);
EXPECT_EQ(littleval[1], 0x66);
EXPECT_EQ(littleval[2], 0x55);
EXPECT_EQ(littleval[3], 0x44);
EXPECT_EQ(q, littleval + 4);
endian::writeNext<uint32_t>(q, 0x11223344, wpi::util::endianness::little);
endian::writeNext<uint32_t>(q, 0x11223344, std::endian::little);
EXPECT_EQ(littleval[4], 0x44);
EXPECT_EQ(littleval[5], 0x33);
EXPECT_EQ(littleval[6], 0x22);
@@ -62,10 +61,10 @@ TEST(Endian, ReadBitAligned) {
unsigned char littleval[] = {0x3f, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff};
unsigned char bigval[] = {0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xc0};
EXPECT_EQ(
(endian::readAtBitAlignment<int, wpi::util::endianness::little, unaligned>(
(endian::readAtBitAlignment<int, std::endian::little, unaligned>(
&littleval[0], 6)),
0x0);
EXPECT_EQ((endian::readAtBitAlignment<int, wpi::util::endianness::big, unaligned>(
EXPECT_EQ((endian::readAtBitAlignment<int, std::endian::big, unaligned>(
&bigval[0], 6)),
0x0);
// Test to make sure that signed right shift of 0xf0000000 is masked
@@ -73,18 +72,18 @@ TEST(Endian, ReadBitAligned) {
unsigned char littleval2[] = {0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00};
unsigned char bigval2[] = {0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
EXPECT_EQ(
(endian::readAtBitAlignment<int, wpi::util::endianness::little, unaligned>(
(endian::readAtBitAlignment<int, std::endian::little, unaligned>(
&littleval2[0], 4)),
0x0f000000);
EXPECT_EQ((endian::readAtBitAlignment<int, wpi::util::endianness::big, unaligned>(
EXPECT_EQ((endian::readAtBitAlignment<int, std::endian::big, unaligned>(
&bigval2[0], 4)),
0x0f000000);
// Test to make sure left shift of start bit doesn't overflow.
EXPECT_EQ(
(endian::readAtBitAlignment<int, wpi::util::endianness::little, unaligned>(
(endian::readAtBitAlignment<int, std::endian::little, unaligned>(
&littleval2[0], 1)),
0x78000000);
EXPECT_EQ((endian::readAtBitAlignment<int, wpi::util::endianness::big, unaligned>(
EXPECT_EQ((endian::readAtBitAlignment<int, std::endian::big, unaligned>(
&bigval2[0], 1)),
0x78000000);
// Test to make sure 64-bit int doesn't overflow.
@@ -93,11 +92,11 @@ TEST(Endian, ReadBitAligned) {
unsigned char bigval3[] = {0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
EXPECT_EQ(
(endian::readAtBitAlignment<int64_t, wpi::util::endianness::little, unaligned>(
(endian::readAtBitAlignment<int64_t, std::endian::little, unaligned>(
&littleval3[0], 4)),
0x0f00000000000000);
EXPECT_EQ(
(endian::readAtBitAlignment<int64_t, wpi::util::endianness::big, unaligned>(
(endian::readAtBitAlignment<int64_t, std::endian::big, unaligned>(
&bigval3[0], 4)),
0x0f00000000000000);
}
@@ -106,7 +105,7 @@ TEST(Endian, WriteBitAligned) {
// This test ensures that signed right shift of 0xffffaa is masked
// properly.
unsigned char bigval[8] = {0x00};
endian::writeAtBitAlignment<int32_t, wpi::util::endianness::big, unaligned>(
endian::writeAtBitAlignment<int32_t, std::endian::big, unaligned>(
bigval, (int)0xffffaaaa, 4);
EXPECT_EQ(bigval[0], 0xff);
EXPECT_EQ(bigval[1], 0xfa);
@@ -118,7 +117,7 @@ TEST(Endian, WriteBitAligned) {
EXPECT_EQ(bigval[7], 0x0f);
unsigned char littleval[8] = {0x00};
endian::writeAtBitAlignment<int32_t, wpi::util::endianness::little, unaligned>(
endian::writeAtBitAlignment<int32_t, std::endian::little, unaligned>(
littleval, (int)0xffffaaaa, 4);
EXPECT_EQ(littleval[0], 0xa0);
EXPECT_EQ(littleval[1], 0xaa);
@@ -132,7 +131,7 @@ TEST(Endian, WriteBitAligned) {
// This test makes sure 1<<31 doesn't overflow.
// Test to make sure left shift of start bit doesn't overflow.
unsigned char bigval2[8] = {0x00};
endian::writeAtBitAlignment<int32_t, wpi::util::endianness::big, unaligned>(
endian::writeAtBitAlignment<int32_t, std::endian::big, unaligned>(
bigval2, (int)0xffffffff, 1);
EXPECT_EQ(bigval2[0], 0xff);
EXPECT_EQ(bigval2[1], 0xff);
@@ -144,7 +143,7 @@ TEST(Endian, WriteBitAligned) {
EXPECT_EQ(bigval2[7], 0x01);
unsigned char littleval2[8] = {0x00};
endian::writeAtBitAlignment<int32_t, wpi::util::endianness::little, unaligned>(
endian::writeAtBitAlignment<int32_t, std::endian::little, unaligned>(
littleval2, (int)0xffffffff, 1);
EXPECT_EQ(littleval2[0], 0xfe);
EXPECT_EQ(littleval2[1], 0xff);
@@ -157,7 +156,7 @@ TEST(Endian, WriteBitAligned) {
// Test to make sure 64-bit int doesn't overflow.
unsigned char bigval64[16] = {0x00};
endian::writeAtBitAlignment<int64_t, wpi::util::endianness::big, unaligned>(
endian::writeAtBitAlignment<int64_t, std::endian::big, unaligned>(
bigval64, (int64_t)0xffffffffffffffff, 1);
EXPECT_EQ(bigval64[0], 0xff);
EXPECT_EQ(bigval64[1], 0xff);
@@ -177,7 +176,7 @@ TEST(Endian, WriteBitAligned) {
EXPECT_EQ(bigval64[15], 0x01);
unsigned char littleval64[16] = {0x00};
endian::writeAtBitAlignment<int64_t, wpi::util::endianness::little, unaligned>(
endian::writeAtBitAlignment<int64_t, std::endian::little, unaligned>(
littleval64, (int64_t)0xffffffffffffffff, 1);
EXPECT_EQ(littleval64[0], 0xfe);
EXPECT_EQ(littleval64[1], 0xff);
@@ -199,26 +198,26 @@ TEST(Endian, WriteBitAligned) {
TEST(Endian, Write) {
unsigned char data[5];
endian::write<int32_t, unaligned>(data, -1362446643, wpi::util::endianness::big);
endian::write<int32_t, unaligned>(data, -1362446643, std::endian::big);
EXPECT_EQ(data[0], 0xAE);
EXPECT_EQ(data[1], 0xCA);
EXPECT_EQ(data[2], 0xB6);
EXPECT_EQ(data[3], 0xCD);
endian::write<int32_t, unaligned>(data + 1, -1362446643,
wpi::util::endianness::big);
std::endian::big);
EXPECT_EQ(data[1], 0xAE);
EXPECT_EQ(data[2], 0xCA);
EXPECT_EQ(data[3], 0xB6);
EXPECT_EQ(data[4], 0xCD);
endian::write<int32_t, unaligned>(data, -1362446643,
wpi::util::endianness::little);
std::endian::little);
EXPECT_EQ(data[0], 0xCD);
EXPECT_EQ(data[1], 0xB6);
EXPECT_EQ(data[2], 0xCA);
EXPECT_EQ(data[3], 0xAE);
endian::write<int32_t, unaligned>(data + 1, -1362446643,
wpi::util::endianness::little);
std::endian::little);
EXPECT_EQ(data[1], 0xCD);
EXPECT_EQ(data[2], 0xB6);
EXPECT_EQ(data[3], 0xCA);
@@ -238,13 +237,4 @@ TEST(Endian, PackedEndianSpecificIntegral) {
EXPECT_EQ(big_val->value(), little_val->value());
}
TEST(Endian, PacketEndianSpecificIntegralAsEnum) {
enum class Test : uint16_t { ONETWO = 0x0102, TWOONE = 0x0201 };
unsigned char bytes[] = {0x01, 0x02};
using LittleTest = little_t<Test>;
using BigTest = big_t<Test>;
EXPECT_EQ(Test::TWOONE, *reinterpret_cast<LittleTest *>(bytes));
EXPECT_EQ(Test::ONETWO, *reinterpret_cast<BigTest *>(bytes));
}
} // end anon namespace

View File

@@ -1,200 +0,0 @@
//===- unittests/Support/SwapByteOrderTest.cpp - swap byte order test -----===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "wpi/util/SwapByteOrder.hpp"
#include "gtest/gtest.h"
#include <cstdlib>
#include <ctime>
using namespace wpi::util;
#undef max
namespace {
// In these first two tests all of the original_uintx values are truncated
// except for 64. We could avoid this, but there's really no point.
TEST(getSwappedBytes, UnsignedRoundTrip) {
// The point of the bit twiddling of magic is to test with and without bits
// in every byte.
uint64_t value = 1;
for (std::size_t i = 0; i <= sizeof(value); ++i) {
uint8_t original_uint8 = static_cast<uint8_t>(value);
EXPECT_EQ(original_uint8,
sys::getSwappedBytes(sys::getSwappedBytes(original_uint8)));
uint16_t original_uint16 = static_cast<uint16_t>(value);
EXPECT_EQ(original_uint16,
sys::getSwappedBytes(sys::getSwappedBytes(original_uint16)));
uint32_t original_uint32 = static_cast<uint32_t>(value);
EXPECT_EQ(original_uint32,
sys::getSwappedBytes(sys::getSwappedBytes(original_uint32)));
uint64_t original_uint64 = static_cast<uint64_t>(value);
EXPECT_EQ(original_uint64,
sys::getSwappedBytes(sys::getSwappedBytes(original_uint64)));
value = (value << 8) | 0x55; // binary 0101 0101.
}
}
TEST(getSwappedBytes, SignedRoundTrip) {
// The point of the bit twiddling of magic is to test with and without bits
// in every byte.
uint64_t value = 1;
for (std::size_t i = 0; i <= sizeof(value); ++i) {
int8_t original_int8 = static_cast<int8_t>(value);
EXPECT_EQ(original_int8,
sys::getSwappedBytes(sys::getSwappedBytes(original_int8)));
int16_t original_int16 = static_cast<int16_t>(value);
EXPECT_EQ(original_int16,
sys::getSwappedBytes(sys::getSwappedBytes(original_int16)));
int32_t original_int32 = static_cast<int32_t>(value);
EXPECT_EQ(original_int32,
sys::getSwappedBytes(sys::getSwappedBytes(original_int32)));
int64_t original_int64 = static_cast<int64_t>(value);
EXPECT_EQ(original_int64,
sys::getSwappedBytes(sys::getSwappedBytes(original_int64)));
// Test other sign.
value *= -1;
original_int8 = static_cast<int8_t>(value);
EXPECT_EQ(original_int8,
sys::getSwappedBytes(sys::getSwappedBytes(original_int8)));
original_int16 = static_cast<int16_t>(value);
EXPECT_EQ(original_int16,
sys::getSwappedBytes(sys::getSwappedBytes(original_int16)));
original_int32 = static_cast<int32_t>(value);
EXPECT_EQ(original_int32,
sys::getSwappedBytes(sys::getSwappedBytes(original_int32)));
original_int64 = static_cast<int64_t>(value);
EXPECT_EQ(original_int64,
sys::getSwappedBytes(sys::getSwappedBytes(original_int64)));
// Return to normal sign and twiddle.
value *= -1;
value = (value << 8) | 0x55; // binary 0101 0101.
}
}
TEST(getSwappedBytes, uint8_t) {
EXPECT_EQ(uint8_t(0x11), sys::getSwappedBytes(uint8_t(0x11)));
}
TEST(getSwappedBytes, uint16_t) {
EXPECT_EQ(uint16_t(0x1122), sys::getSwappedBytes(uint16_t(0x2211)));
}
TEST(getSwappedBytes, uint32_t) {
EXPECT_EQ(uint32_t(0x11223344), sys::getSwappedBytes(uint32_t(0x44332211)));
}
TEST(getSwappedBytes, uint64_t) {
EXPECT_EQ(uint64_t(0x1122334455667788ULL),
sys::getSwappedBytes(uint64_t(0x8877665544332211ULL)));
}
TEST(getSwappedBytes, int8_t) {
EXPECT_EQ(int8_t(0x11), sys::getSwappedBytes(int8_t(0x11)));
}
TEST(getSwappedBytes, int16_t) {
EXPECT_EQ(int16_t(0x1122), sys::getSwappedBytes(int16_t(0x2211)));
}
TEST(getSwappedBytes, int32_t) {
EXPECT_EQ(int32_t(0x11223344), sys::getSwappedBytes(int32_t(0x44332211)));
}
TEST(getSwappedBytes, int64_t) {
EXPECT_EQ(int64_t(0x1122334455667788LL),
sys::getSwappedBytes(int64_t(0x8877665544332211LL)));
}
TEST(getSwappedBytes, float) {
EXPECT_EQ(1.79366203433576585078237386661e-43f, sys::getSwappedBytes(-0.0f));
// 0x11223344
EXPECT_EQ(7.1653228759765625e2f, sys::getSwappedBytes(1.2795344e-28f));
}
TEST(getSwappedBytes, double) {
EXPECT_EQ(6.32404026676795576546008054871e-322, sys::getSwappedBytes(-0.0));
// 0x1122334455667788
EXPECT_EQ(-7.08687663657301358331704585496e-268,
sys::getSwappedBytes(3.84141202447173065923064450234e-226));
}
TEST(swapByteOrder, uint8_t) {
uint8_t value = 0x11;
sys::swapByteOrder(value);
EXPECT_EQ(uint8_t(0x11), value);
}
TEST(swapByteOrder, uint16_t) {
uint16_t value = 0x2211;
sys::swapByteOrder(value);
EXPECT_EQ(uint16_t(0x1122), value);
}
TEST(swapByteOrder, uint32_t) {
uint32_t value = 0x44332211;
sys::swapByteOrder(value);
EXPECT_EQ(uint32_t(0x11223344), value);
}
TEST(swapByteOrder, uint64_t) {
uint64_t value = 0x8877665544332211ULL;
sys::swapByteOrder(value);
EXPECT_EQ(uint64_t(0x1122334455667788ULL), value);
}
TEST(swapByteOrder, int8_t) {
int8_t value = 0x11;
sys::swapByteOrder(value);
EXPECT_EQ(int8_t(0x11), value);
}
TEST(swapByteOrder, int16_t) {
int16_t value = 0x2211;
sys::swapByteOrder(value);
EXPECT_EQ(int16_t(0x1122), value);
}
TEST(swapByteOrder, int32_t) {
int32_t value = 0x44332211;
sys::swapByteOrder(value);
EXPECT_EQ(int32_t(0x11223344), value);
}
TEST(swapByteOrder, int64_t) {
int64_t value = 0x8877665544332211LL;
sys::swapByteOrder(value);
EXPECT_EQ(int64_t(0x1122334455667788LL), value);
}
TEST(swapByteOrder, float) {
float value = 7.1653228759765625e2f; // 0x44332211
sys::swapByteOrder(value);
EXPECT_EQ(1.2795344e-28f, value);
}
TEST(swapByteOrder, double) {
double value = -7.08687663657301358331704585496e-268; // 0x8877665544332211
sys::swapByteOrder(value);
EXPECT_EQ(3.84141202447173065923064450234e-226, value);
}
}