Skip to content

Commit

Permalink
Restore byteswap utility
Browse files Browse the repository at this point in the history
  • Loading branch information
albin-johansson committed Oct 16, 2023
1 parent 33d994b commit a33afd1
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 5 deletions.
35 changes: 32 additions & 3 deletions modules/core/inc/tactile/core/platform/bits.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,14 @@

#pragma once

#include <bit> // endian
#include <concepts> // integral, invocable
#include <algorithm> // reverse
#include <bit> // bit_cast, endian, byteswap
#include <concepts> // integral, invocable
#include <cstddef> // byte
#include <type_traits> // has_unique_object_representations_v
#include <version> // __cpp_lib_byteswap

#include "tactile/core/container/array.hpp"
#include "tactile/core/prelude.hpp"

namespace tactile {
Expand All @@ -24,6 +29,30 @@ void each_byte(const IntType value, const CallableType& callable)
}
}

/**
* \brief Reverses the bytes in an integer value.
*
* \tparam IntType an integral type.
*
* \param value an integer value.
*
* \return a byteswapped integer.
*/
template <std::integral IntType>
[[nodiscard]] constexpr auto reverse_bytes(const IntType value) noexcept -> IntType
{
#if __cpp_lib_byteswap >= 202110L
return std::byteswap(value);
#else
using ByteArray = Array<std::byte, sizeof(IntType)>;

const auto bytes = std::bit_cast<ByteArray>(value);
std::ranges::reverse(bytes);

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

/**
* \brief Converts a native integer to a little endian integer.
*
Expand All @@ -34,7 +63,7 @@ void each_byte(const IntType value, const CallableType& callable)
template <std::integral IntType>
[[nodiscard]] constexpr auto to_little_endian(const IntType value) noexcept -> IntType
{
return (std::endian::native == std::endian::little) ? value : std::byteswap(value);
return (std::endian::native == std::endian::little) ? value : reverse_bytes(value);
}

} // namespace tactile
4 changes: 2 additions & 2 deletions modules/core/src/tactile/core/io/tile_matrix_encoding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

#include "tactile/core/io/tile_matrix_encoding.hpp"

#include <bit> // endian, byteswap
#include <bit> // endian
#include <concepts> // same_as
#include <cstring> // memcpy

Expand Down Expand Up @@ -55,7 +55,7 @@ auto tile_matrix_from_byte_stream(const ByteStream& byte_stream,

// Correct the byte ordering if we're on a big endian system.
if constexpr (std::endian::native == std::endian::big) {
tile_id = std::byteswap(tile_id);
tile_id = reverse_bytes(tile_id);
}

// Clear any flipping bits used by Tiled.
Expand Down
27 changes: 27 additions & 0 deletions modules/core/test/platform/bits_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright (C) 2023 Albin Johansson (GNU General Public License v3.0)

#include "tactile/core/platform/bits.hpp"

#include <bit> // bit_cast

#include <gtest/gtest.h>

#include "tactile/core/container/array.hpp"

using namespace tactile;

TEST(BitUtilities, ReverseBytes)
{
using ByteArray = Array<uint8, sizeof(uint32)>;

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);

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

0 comments on commit a33afd1

Please sign in to comment.