i2pd/libi2pd/LittleBigEndian.h
Anatolii Cherednichenko 55534ea002 Reformat code
2022-08-30 02:11:28 +03:00

218 lines
No EOL
4.6 KiB
C++

/*
* 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