123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- // Copyright 2017 Dolphin Emulator Project
- // SPDX-License-Identifier: GPL-2.0-or-later
- #pragma once
- #include <cstring>
- #include <type_traits>
- #ifdef __APPLE__
- #include <libkern/OSByteOrder.h>
- #elif defined(__linux__)
- #include <byteswap.h>
- #elif defined(__FreeBSD__)
- #include <sys/endian.h>
- #elif defined(__OpenBSD__)
- #include <endian.h>
- #endif
- #include <fmt/format.h>
- #include "Common/CommonTypes.h"
- namespace Common
- {
- inline u8 swap8(u8 data)
- {
- return data;
- }
- inline u32 swap24(const u8* data)
- {
- return (data[0] << 16) | (data[1] << 8) | data[2];
- }
- #if defined(ANDROID) || defined(__OpenBSD__)
- #undef swap16
- #undef swap32
- #undef swap64
- #endif
- #ifdef _WIN32
- inline u16 swap16(u16 data)
- {
- return _byteswap_ushort(data);
- }
- inline u32 swap32(u32 data)
- {
- return _byteswap_ulong(data);
- }
- inline u64 swap64(u64 data)
- {
- return _byteswap_uint64(data);
- }
- #elif __linux__
- inline u16 swap16(u16 data)
- {
- return bswap_16(data);
- }
- inline u32 swap32(u32 data)
- {
- return bswap_32(data);
- }
- inline u64 swap64(u64 data)
- {
- return bswap_64(data);
- }
- #elif __APPLE__
- inline __attribute__((always_inline)) u16 swap16(u16 data)
- {
- return OSSwapInt16(data);
- }
- inline __attribute__((always_inline)) u32 swap32(u32 data)
- {
- return OSSwapInt32(data);
- }
- inline __attribute__((always_inline)) u64 swap64(u64 data)
- {
- return OSSwapInt64(data);
- }
- #elif __FreeBSD__
- inline u16 swap16(u16 data)
- {
- return bswap16(data);
- }
- inline u32 swap32(u32 data)
- {
- return bswap32(data);
- }
- inline u64 swap64(u64 data)
- {
- return bswap64(data);
- }
- #else
- // Slow generic implementation.
- inline u16 swap16(u16 data)
- {
- return (data >> 8) | (data << 8);
- }
- inline u32 swap32(u32 data)
- {
- return (swap16(data) << 16) | swap16(data >> 16);
- }
- inline u64 swap64(u64 data)
- {
- return ((u64)swap32(data) << 32) | swap32(data >> 32);
- }
- #endif
- inline u16 swap16(const u8* data)
- {
- u16 value;
- std::memcpy(&value, data, sizeof(u16));
- return swap16(value);
- }
- inline u32 swap32(const u8* data)
- {
- u32 value;
- std::memcpy(&value, data, sizeof(u32));
- return swap32(value);
- }
- inline u64 swap64(const u8* data)
- {
- u64 value;
- std::memcpy(&value, data, sizeof(u64));
- return swap64(value);
- }
- template <int count>
- void swap(u8*);
- template <>
- inline void swap<1>(u8* data)
- {
- }
- template <>
- inline void swap<2>(u8* data)
- {
- const u16 value = swap16(data);
- std::memcpy(data, &value, sizeof(u16));
- }
- template <>
- inline void swap<4>(u8* data)
- {
- const u32 value = swap32(data);
- std::memcpy(data, &value, sizeof(u32));
- }
- template <>
- inline void swap<8>(u8* data)
- {
- const u64 value = swap64(data);
- std::memcpy(data, &value, sizeof(u64));
- }
- template <typename T>
- inline T FromBigEndian(T data)
- {
- static_assert(std::is_arithmetic<T>::value, "function only makes sense with arithmetic types");
- swap<sizeof(data)>(reinterpret_cast<u8*>(&data));
- return data;
- }
- template <typename value_type>
- struct BigEndianValue
- {
- static_assert(std::is_arithmetic<value_type>(), "value_type must be an arithmetic type");
- BigEndianValue() = default;
- explicit BigEndianValue(value_type val) { *this = val; }
- operator value_type() const { return FromBigEndian(raw); }
- BigEndianValue& operator=(value_type v)
- {
- raw = FromBigEndian(v);
- return *this;
- }
- private:
- value_type raw;
- };
- } // Namespace Common
- template <typename value_type>
- struct fmt::formatter<Common::BigEndianValue<value_type>>
- {
- fmt::formatter<value_type> m_formatter;
- constexpr auto parse(format_parse_context& ctx) { return m_formatter.parse(ctx); }
- template <typename FormatContext>
- auto format(const Common::BigEndianValue<value_type>& value, FormatContext& ctx) const
- {
- return m_formatter.format(value.operator value_type(), ctx);
- }
- };
|