Skip to content

Commit

Permalink
Add fallback if C++20 bit_cast is missing
Browse files Browse the repository at this point in the history
  • Loading branch information
albin-johansson committed Oct 28, 2023
1 parent 963509c commit 9c2a372
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ MaxEmptyLinesToKeep: 1
InsertBraces: true
RemoveSemicolon: true
PackConstructorInitializers: Never
RequiresClausePosition: WithPreceding
RequiresClausePosition: OwnLine
# QualifierOrder: [ 'friend', 'inline', 'static', 'const', 'volatile', 'constexpr', 'restrict', 'type' ]

IndentWidth: 2
Expand Down
22 changes: 20 additions & 2 deletions modules/core/inc/tactile/core/platform/bits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
#include <bit> // bit_cast, endian, byteswap
#include <concepts> // integral, invocable
#include <cstddef> // byte
#include <cstring> // memcpy
#include <type_traits> // has_unique_object_representations_v
#include <type_traits> // is_trivially_copyable_v, is_trivially_constructible_v
#include <version> // __cpp_lib_byteswap

#include "tactile/core/container/array.hpp"
Expand All @@ -29,6 +31,22 @@ void each_byte(const IntType value, const CallableType& callable)
}
}

template <typename To, typename From>
requires(sizeof(To) == sizeof(From) && //
std::is_trivially_copyable_v<From> && //
std::is_trivially_copyable_v<To> && //
std::is_trivially_constructible_v<To>)
[[nodiscard]] auto interpret_as(const From& src) noexcept -> To
{
#if __cpp_lib_bit_cast >= 201806L
return std::bit_cast<To>(src);
#else
To dst;
std::memcpy(&dst, &src, sizeof dst);
return dst;
#endif
}

/**
* \brief Reverses the bytes in an integer value.
*
Expand All @@ -46,10 +64,10 @@ template <std::integral IntType>
#else
using ByteArray = Array<std::byte, sizeof(IntType)>;

const auto bytes = std::bit_cast<ByteArray>(value);
const auto bytes = interpret_as<ByteArray>(value);
std::reverse(bytes.begin(), bytes.end());

return std::bit_cast<IntType>(bytes);
return interpret_as<IntType>(bytes);
#endif
}

Expand Down
4 changes: 2 additions & 2 deletions modules/core/test/platform/bits_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ TEST(BitUtilities, ReverseBytes)
const uint32 original = 0xDEADBEEF;
const auto swapped = reverse_bytes(original);

const auto original_bytes = std::bit_cast<ByteArray>(original);
const auto swapped_bytes = std::bit_cast<ByteArray>(swapped);
const auto original_bytes = interpret_as<ByteArray>(original);
const auto swapped_bytes = interpret_as<ByteArray>(swapped);

EXPECT_EQ(original_bytes.at(0), swapped_bytes.at(3));
EXPECT_EQ(original_bytes.at(1), swapped_bytes.at(2));
Expand Down

0 comments on commit 9c2a372

Please sign in to comment.