/* * Copyright (c) 2013-2020, The PurpleI2P Project * * This file is part of Purple i2pd project and licensed under BSD3 * * See full license text in LICENSE file at top of project tree */ // LittleBigEndian.h fixed for 64-bits added union // #ifndef LITTLEBIGENDIAN_H #define LITTLEBIGENDIAN_H // Determine Little-Endian or Big-Endian #define CURRENT_BYTE_ORDER (*(int *)"\x01\x02\x03\x04") #define LITTLE_ENDIAN_BYTE_ORDER 0x04030201 #define BIG_ENDIAN_BYTE_ORDER 0x01020304 #define PDP_ENDIAN_BYTE_ORDER 0x02010403 #define IS_LITTLE_ENDIAN (CURRENT_BYTE_ORDER == LITTLE_ENDIAN_BYTE_ORDER) #define IS_BIG_ENDIAN (CURRENT_BYTE_ORDER == BIG_ENDIAN_BYTE_ORDER) #define IS_PDP_ENDIAN (CURRENT_BYTE_ORDER == PDP_ENDIAN_BYTE_ORDER) // Forward declaration template struct LittleEndian; template struct BigEndian; // Little-Endian template #pragma pack(push,1) template struct LittleEndian { union { unsigned char bytes[sizeof(T)]; T raw_value; }; LittleEndian(T t = T()) { operator =(t); } LittleEndian(const LittleEndian & t) { raw_value = t.raw_value; } LittleEndian(const BigEndian & t) { for (unsigned i = 0; i < sizeof(T); i++) bytes[i] = t.bytes[sizeof(T)-1-i]; } operator const T() const { T t = T(); for (unsigned i = 0; i < sizeof(T); i++) t |= T(bytes[i]) << (i << 3); return t; } const T operator = (const T t) { for (unsigned i = 0; i < sizeof(T); i++) bytes[sizeof(T)-1 - i] = static_cast(t >> (i << 3)); return t; } // operators const T operator += (const T t) { return (*this = *this + t); } const T operator -= (const T t) { return (*this = *this - t); } const T operator *= (const T t) { return (*this = *this * t); } const T operator /= (const T t) { return (*this = *this / t); } const T operator %= (const T t) { return (*this = *this % t); } LittleEndian operator ++ (int) { LittleEndian tmp(*this); operator ++ (); return tmp; } LittleEndian & operator ++ () { for (unsigned i = 0; i < sizeof(T); i++) { ++bytes[i]; if (bytes[i] != 0) break; } return (*this); } LittleEndian operator -- (int) { LittleEndian tmp(*this); operator -- (); return tmp; } LittleEndian & operator -- () { for (unsigned i = 0; i < sizeof(T); i++) { --bytes[i]; if (bytes[i] != (T)(-1)) break; } return (*this); } }; #pragma pack(pop) // Big-Endian template #pragma pack(push,1) template struct BigEndian { union { unsigned char bytes[sizeof(T)]; T raw_value; }; BigEndian(T t = T()) { operator =(t); } BigEndian(const BigEndian & t) { raw_value = t.raw_value; } BigEndian(const LittleEndian & t) { for (unsigned i = 0; i < sizeof(T); i++) bytes[i] = t.bytes[sizeof(T)-1-i]; } operator const T() const { T t = T(); for (unsigned i = 0; i < sizeof(T); i++) t |= T(bytes[sizeof(T) - 1 - i]) << (i << 3); return t; } const T operator = (const T t) { for (unsigned i = 0; i < sizeof(T); i++) bytes[sizeof(T) - 1 - i] = t >> (i << 3); return t; } // operators const T operator += (const T t) { return (*this = *this + t); } const T operator -= (const T t) { return (*this = *this - t); } const T operator *= (const T t) { return (*this = *this * t); } const T operator /= (const T t) { return (*this = *this / t); } const T operator %= (const T t) { return (*this = *this % t); } BigEndian operator ++ (int) { BigEndian tmp(*this); operator ++ (); return tmp; } BigEndian & operator ++ () { for (unsigned i = 0; i < sizeof(T); i++) { ++bytes[sizeof(T) - 1 - i]; if (bytes[sizeof(T) - 1 - i] != 0) break; } return (*this); } BigEndian operator -- (int) { BigEndian tmp(*this); operator -- (); return tmp; } BigEndian & operator -- () { for (unsigned i = 0; i < sizeof(T); i++) { --bytes[sizeof(T) - 1 - i]; if (bytes[sizeof(T) - 1 - i] != (T)(-1)) break; } return (*this); } }; #pragma pack(pop) #endif // LITTLEBIGENDIAN_H