mirror of https://github.com/PurpleI2P/i2pd.git
I2P: End-to-End encrypted and anonymous Internet
https://i2pd.website/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
4.0 KiB
250 lines
4.0 KiB
/* |
|
* 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<typename T> |
|
struct LittleEndian; |
|
|
|
template<typename T> |
|
struct BigEndian; |
|
|
|
// Little-Endian template |
|
|
|
#pragma pack(push,1) |
|
template<typename T> |
|
struct LittleEndian |
|
{ |
|
union |
|
{ |
|
unsigned char bytes[sizeof(T)]; |
|
T raw_value; |
|
}; |
|
|
|
LittleEndian(T t = T()) |
|
{ |
|
operator =(t); |
|
} |
|
|
|
LittleEndian(const LittleEndian<T> & t) |
|
{ |
|
raw_value = t.raw_value; |
|
} |
|
|
|
LittleEndian(const BigEndian<T> & 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<unsigned char>(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<T> operator ++ (int) |
|
{ |
|
LittleEndian<T> tmp(*this); |
|
operator ++ (); |
|
return tmp; |
|
} |
|
|
|
LittleEndian<T> & operator ++ () |
|
{ |
|
for (unsigned i = 0; i < sizeof(T); i++) |
|
{ |
|
++bytes[i]; |
|
if (bytes[i] != 0) |
|
break; |
|
} |
|
return (*this); |
|
} |
|
|
|
LittleEndian<T> operator -- (int) |
|
{ |
|
LittleEndian<T> tmp(*this); |
|
operator -- (); |
|
return tmp; |
|
} |
|
|
|
LittleEndian<T> & 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<typename T> |
|
struct BigEndian |
|
{ |
|
union |
|
{ |
|
unsigned char bytes[sizeof(T)]; |
|
T raw_value; |
|
}; |
|
|
|
BigEndian(T t = T()) |
|
{ |
|
operator =(t); |
|
} |
|
|
|
BigEndian(const BigEndian<T> & t) |
|
{ |
|
raw_value = t.raw_value; |
|
} |
|
|
|
BigEndian(const LittleEndian<T> & 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<T> operator ++ (int) |
|
{ |
|
BigEndian<T> tmp(*this); |
|
operator ++ (); |
|
return tmp; |
|
} |
|
|
|
BigEndian<T> & 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<T> operator -- (int) |
|
{ |
|
BigEndian<T> tmp(*this); |
|
operator -- (); |
|
return tmp; |
|
} |
|
|
|
BigEndian<T> & 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
|