add endian helper

This commit is contained in:
Andrey Gusakov 2024-04-14 15:22:55 +03:00
parent 7bcee1b813
commit c531b98048
1 changed files with 95 additions and 0 deletions

View File

@ -0,0 +1,95 @@
#pragma once
// http://en.wikipedia.org/wiki/Endianness
#ifndef __BYTE_ORDER__
#error __BYTE_ORDER__ is not defined
#endif
#if defined(__BYTE_ORDER__)&&(__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
#define bigEndianHost true
#endif
#if defined(__BYTE_ORDER__)&&(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
#define bigEndianHost false
#endif
/* TODO: already defined in efilib.h
* TODO: move here? */
#if 0
static inline uint16_t SWAP_UINT16(uint16_t x)
{
return ((x << 8) | (x >> 8));
}
static inline uint32_t SWAP_UINT32(uint32_t x)
{
return (((x >> 24) & 0x000000ff) | ((x << 8) & 0x00ff0000) |
((x >> 8) & 0x0000ff00) | ((x << 24) & 0xff000000));
}
#endif
template <typename T>
class SwapEndian
{
public:
struct IncompleteType;
SwapEndian() { }
constexpr operator typename std::conditional_t<sizeof(T) == 4, T, IncompleteType>() const {
return SWAP_UINT32(rep);
}
constexpr SwapEndian(std::conditional_t<sizeof(T) == 4, T, IncompleteType> val) {
rep = SWAP_UINT32(val);
}
constexpr operator typename std::conditional_t<sizeof(T) == 2, T, IncompleteType>() const {
return SWAP_UINT16(rep);
}
constexpr SwapEndian(std::conditional_t<sizeof(T) == 2, T, IncompleteType> val) {
rep = SWAP_UINT32(val);
}
private:
T rep;
} __attribute__ ((packed));
#if defined(__BYTE_ORDER__)&&(__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
// Big endian storage types
using beint16_t = SwapEndian<int16_t>;
using beint32_t = SwapEndian<int32_t>;
using beuint16_t = SwapEndian<uint16_t>;
using beuint32_t = SwapEndian<uint32_t>;
// Natine Little endian storage types
using leint16_t = int16_t;
using leint32_t = int32_t;
using leuint16_t = uint16_t;
using leuint32_t = uint32_t;
#endif
#if defined(__BYTE_ORDER__)&&(__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
// Native Big endian storage types
using beint16_t = int16_t;
using beint32_t = int32_t;
using beuint16_t = uint16_t;
using beuint32_t = uint32_t;
// Little endian storage types
using leint16_t = SwapEndian<int16_t>;
using leint32_t = SwapEndian<int32_t>;
using leuint16_t = SwapEndian<uint16_t>;
using leuint32_t = SwapEndian<uint32_t>;
#endif
//static_assert(sizeof(buint8_t) == 1);
static_assert(sizeof(beint16_t) == 2);
static_assert(sizeof(beint32_t) == 4);
static_assert(sizeof(beuint16_t) == 2);
static_assert(sizeof(beuint32_t) == 4);
//static_assert(sizeof(luint8_t) == 1);
static_assert(sizeof(leint16_t) == 2);
static_assert(sizeof(leint32_t) == 4);
static_assert(sizeof(leuint16_t) == 2);
static_assert(sizeof(leuint32_t) == 4);