endian.hpp: minor simplification

And stop pretending...
This commit is contained in:
Nekotekina 2020-12-11 21:06:19 +03:00
parent 7a015b6fc0
commit 33c3977036
2 changed files with 26 additions and 44 deletions

View File

@ -1,5 +1,7 @@
// No BOM and only basic ASCII in this file, or a neko will die
#include "stdafx.h"
static_assert(std::endian::native == std::endian::little || std::endian::native == std::endian::big);
static_assert(be_t<u16>(1) + be_t<u32>(2) + be_t<u64>(3) == 6);
static_assert(le_t<u16>(1) + le_t<u32>(2) + le_t<u64>(3) == 6);

View File

@ -1,43 +1,20 @@
#pragma once // No BOM and only basic ASCII in this header, or a neko will die
#include <cstdint>
#include "Utilities/types.h"
#if __has_include(<bit>)
#include <bit>
#else
#include <type_traits>
#endif
namespace stx
{
static_assert(std::endian::native == std::endian::little || std::endian::native == std::endian::big);
#ifdef _MSC_VER
template<class T, std::size_t... N>
static constexpr T bswap_impl(T i, std::index_sequence<N...>)
{
return static_cast<T>(((((i >> (N * 8)) & T{UINT8_MAX}) << ((sizeof(T) - 1 - N) * 8)) | ...));
};
template<class T, class U = typename std::make_unsigned<T>::type>
static constexpr U bswap(T i)
{
return bswap_impl<U>(i, std::make_index_sequence<sizeof(T)>{});
}
#endif
template <typename T, std::size_t Align = alignof(T), std::size_t Size = sizeof(T)>
struct se_storage
{
struct type8
{
alignas(Align > alignof(T) ? alignof(T) : Align) unsigned char data[sizeof(T)];
alignas(Align > alignof(T) ? alignof(T) : Align) uchar data[sizeof(T)];
};
struct type64
{
alignas(8) std::uint64_t data[sizeof(T) < 8 ? 1 : sizeof(T) / 8];
alignas(8) u64 data[sizeof(T) < 8 ? 1 : sizeof(T) / 8];
};
using type = std::conditional_t<(Align >= 8 && sizeof(T) % 8 == 0), type64, type8>;
@ -47,18 +24,18 @@ namespace stx
};
template <typename T>
struct se_storage<T, alignof(std::uint16_t), 2>
struct se_storage<T, 2, 2>
{
using type = std::uint16_t;
using type = u16;
static constexpr std::uint16_t swap(std::uint16_t src) noexcept
static constexpr u16 swap(u16 src) noexcept
{
#if defined(__GNUG__)
return __builtin_bswap16(src);
#else
if (std::is_constant_evaluated())
{
return stx::bswap(src);
return (src >> 8) | (src << 8);
}
return _byteswap_ushort(src);
@ -67,18 +44,19 @@ namespace stx
};
template <typename T>
struct se_storage<T, alignof(std::uint32_t), 4>
struct se_storage<T, 4, 4>
{
using type = std::uint32_t;
using type = u32;
static constexpr std::uint32_t swap(std::uint32_t src) noexcept
static constexpr u32 swap(u32 src) noexcept
{
#if defined(__GNUG__)
return __builtin_bswap32(src);
#else
if (std::is_constant_evaluated())
{
return stx::bswap(src);
const u32 v0 = ((src << 8) & 0xff00ff00) | ((src >> 8) & 0x00ff00ff);
return (v0 << 16) | (v0 >> 16);
}
return _byteswap_ulong(src);
@ -87,18 +65,20 @@ namespace stx
};
template <typename T>
struct se_storage<T, alignof(std::uint64_t), 8>
struct se_storage<T, 8, 8>
{
using type = std::uint64_t;
using type = u64;
static constexpr std::uint64_t swap(std::uint64_t src) noexcept
static constexpr u64 swap(u64 src) noexcept
{
#if defined(__GNUG__)
return __builtin_bswap64(src);
#else
if (std::is_constant_evaluated())
{
return stx::bswap(src);
const u64 v0 = ((src << 8) & 0xff00ff00ff00ff00) | ((src >> 8) & 0x00ff00ff00ff00ff);
const u64 v1 = ((v0 << 16) & 0xffff0000ffff0000) | ((v0 >> 16) & 0x0000ffff0000ffff);
return (v1 << 32) | (v1 >> 32);
}
return _byteswap_uint64(src);
@ -116,15 +96,15 @@ namespace stx
}
else if constexpr (sizeof(T) == 2)
{
return std::bit_cast<type>(se_storage<std::uint16_t>::swap(std::bit_cast<std::uint16_t>(src)));
return std::bit_cast<type>(se_storage<u16>::swap(std::bit_cast<u16>(src)));
}
else if constexpr (sizeof(T) == 4)
{
return std::bit_cast<type>(se_storage<std::uint32_t>::swap(std::bit_cast<std::uint32_t>(src)));
return std::bit_cast<type>(se_storage<u32>::swap(std::bit_cast<u32>(src)));
}
else if constexpr (sizeof(T) == 8)
{
return std::bit_cast<type>(se_storage<std::uint64_t>::swap(std::bit_cast<std::uint64_t>(src)));
return std::bit_cast<type>(se_storage<u64>::swap(std::bit_cast<u64>(src)));
}
else if constexpr (sizeof(T) % 8 == 0)
{
@ -134,7 +114,7 @@ namespace stx
// Swap u64 blocks
for (std::size_t i = 0; i < sizeof(T) / 8; i++)
{
dst.data[i] = se_storage<std::uint64_t>::swap(tmp.data[sizeof(T) / 8 - 1 - i]);
dst.data[i] = se_storage<u64>::swap(tmp.data[sizeof(T) / 8 - 1 - i]);
}
return std::bit_cast<type>(dst);
@ -182,13 +162,13 @@ namespace stx
static constexpr auto int_or_enum()
{
if constexpr (std::is_enum_v<simple_t<type>>)
if constexpr (std::is_enum_v<type>)
{
return std::underlying_type_t<simple_t<type>>{};
return std::underlying_type_t<type>{};
}
else
{
return simple_t<type>{};
return type{};
}
}