Skip to content

Commit

Permalink
feat(byteswap): adding signed versions, feature flags
Browse files Browse the repository at this point in the history
Also refactoring away from specialized approach and paving way for
(currently unimplemented) xor version

#77
  • Loading branch information
malachib committed Jan 3, 2025
1 parent c2bc088 commit 1461b33
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 18 deletions.
66 changes: 50 additions & 16 deletions src/estd/bit.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include "cstdint.h"
#include "internal/feature/bit.h"

namespace estd {

Expand All @@ -20,7 +21,8 @@ enum class endian

}

#if __cpp_lib_byteswap >= 202110L
#if (FEATURE_ESTD_BYTESWAP_MODE == FEATURE_ESTD_BYTESWAP_AUTO && __cpp_lib_byteswap >= 202110L) || \
FEATURE_ESTD_BYTESWAP_MODE == FEATURE_ESTD_BYTESWAP_STD
#include <bit>

namespace estd {
Expand All @@ -32,38 +34,70 @@ using std::byteswap;
#else
namespace estd {

template <class Unsigned>
constexpr Unsigned byteswap(Unsigned n) noexcept;
namespace detail {
#if FEATURE_ESTD_BYTESWAP_MODE == FEATURE_ESTD_BYTESWAP_XOR

#if __has_builtin(__builtin_bswap16)
template <>
constexpr uint16_t byteswap(uint16_t n) noexcept
#error manual xor non gcc/ non std mode not yet supported

#else // not xor (gcc)

#if __has_builtin(__builtin_bswap16) || FEATURE_ESTD_BYTESWAP_MODE == FEATURE_ESTD_BYTESWAP_GCC

constexpr uint16_t
byteswap(uint16_t n) noexcept
{
return __builtin_bswap16(n);
}

// ISO/IEC 9899:201x aka WG14 N1570 (https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf)
// Section 6.2.6.2 indicates one signed bit is present, and section 3.4.1 immplies it's always
// the high order bit. This gives us confidence that we can swap bits around safely, trusting that
// whoever "unswaps" them will end up with the expected high order signed bit.

constexpr int16_t
byteswap(int16_t n) noexcept
{
return __builtin_bswap16(n);
}

#endif

#if __has_builtin(__builtin_bswap32)
template <>
constexpr uint32_t byteswap(uint32_t n) noexcept
#if __has_builtin(__builtin_bswap32) || FEATURE_ESTD_BYTESWAP_MODE == FEATURE_ESTD_BYTESWAP_GCC

constexpr uint32_t
byteswap(uint32_t n) noexcept
{
return __builtin_bswap32(n);
}

constexpr int32_t
byteswap(int32_t n) noexcept
{
return __builtin_bswap32(n);
}

#endif

#if __has_builtin(__builtin_bswap64)
#if __has_builtin(__builtin_bswap64) || FEATURE_ESTD_BYTESWAP_MODE == FEATURE_ESTD_BYTESWAP_GCC

template <>
constexpr uint64_t byteswap(uint64_t n) noexcept
constexpr uint64_t
byteswap(uint64_t n) noexcept
{
#if __has_builtin(__builtin_bswap32)
return __builtin_bswap64(n);
#else
return 0;
#endif
}

#endif

#endif // not xor (gcc)
}

// Since spec indicates a templated function, we wrap up the specific ones
// in detail. This is better than specializing, since that can lead to linker ambiguities
template <class T>
constexpr T byteswap(T n) noexcept { return detail::byteswap(n); }

}



#endif
10 changes: 10 additions & 0 deletions src/estd/internal/feature/bit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#pragma once

#define FEATURE_ESTD_BYTESWAP_AUTO 0 // Prefer STD, then GCC (if available), then XOR
#define FEATURE_ESTD_BYTESWAP_STD 1 // Force STD mode, ignoring compiler indication of availability
#define FEATURE_ESTD_BYTESWAP_GCC 2 // Force GCC mode, ignoring compiler indication of availability
#define FEATURE_ESTD_BYTESWAP_XOR 3 // Force XOR (manual) mode, not implemented at this time

#ifndef FEATURE_ESTD_BYTESWAP_MODE
#define FEATURE_ESTD_BYTESWAP_MODE FEATURE_ESTD_BYTESWAP_AUTO
#endif
13 changes: 11 additions & 2 deletions test/catch/bit-test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,17 @@ TEST_CASE("bit operations")
{
SECTION("byteswap")
{
auto v = estd::byteswap<uint16_t>(0x1234);
SECTION("uint16_t")
{
auto v = estd::byteswap<uint16_t>(0x1234);

REQUIRE(v == 0x3412);
REQUIRE(v == 0x3412);
}
SECTION("int32_t")
{
auto v = estd::byteswap<int32_t>(0x1234);

REQUIRE(v == 0x34120000);
}
}
}

0 comments on commit 1461b33

Please sign in to comment.