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.
266 lines
5.7 KiB
266 lines
5.7 KiB
/* <endian_types.h>
|
|
*
|
|
* Quick hack to handle endianness and word length issues.
|
|
* Defines _le, _be, and _ne variants to standard ISO types
|
|
* like int32_t, that are stored in little-endian, big-endian,
|
|
* and native-endian byteorder in memory, respectively.
|
|
* Caveat: int32_le_t and friends cannot be used in vararg
|
|
* functions like printf() without an explicit cast.
|
|
*
|
|
* Copyright (c) 2003-2005 Daniel Kobras <kobras@debian.org>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#ifndef _ENDIAN_TYPES_H
|
|
#define _ENDIAN_TYPES_H
|
|
|
|
/* Needed for BYTE_ORDER and BIG/LITTLE_ENDIAN macros. */
|
|
#ifndef _BSD_SOURCE
|
|
# define _BSD_SOURCE
|
|
# include <endian.h>
|
|
# undef _BSD_SOURCE
|
|
#else
|
|
# include <endian.h>
|
|
#endif
|
|
|
|
#include <sys/types.h>
|
|
#include <byteswap.h>
|
|
|
|
static inline int8_t bswap(const int8_t& x)
|
|
{
|
|
return x;
|
|
}
|
|
|
|
static inline u_int8_t bswap(const u_int8_t& x)
|
|
{
|
|
return x;
|
|
}
|
|
|
|
static inline int16_t bswap(const int16_t& x)
|
|
{
|
|
return bswap_16(x);
|
|
}
|
|
|
|
static inline u_int16_t bswap(const u_int16_t& x)
|
|
{
|
|
return bswap_16(x);
|
|
}
|
|
|
|
static inline int32_t bswap(const int32_t& x)
|
|
{
|
|
return bswap_32(x);
|
|
}
|
|
|
|
static inline u_int32_t bswap(const u_int32_t& x)
|
|
{
|
|
return bswap_32(x);
|
|
}
|
|
|
|
static inline int64_t bswap(const int64_t& x)
|
|
{
|
|
return bswap_64(x);
|
|
}
|
|
|
|
static inline u_int64_t bswap(const u_int64_t& x)
|
|
{
|
|
return bswap_64(x);
|
|
}
|
|
|
|
#define le_to_cpu cpu_to_le
|
|
#define be_to_cpu cpu_to_be
|
|
|
|
template <class T> static inline T cpu_to_le(const T& x)
|
|
{
|
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
return x;
|
|
#else
|
|
return bswap(x);
|
|
#endif
|
|
}
|
|
|
|
template <class T> static inline T cpu_to_be(const T& x)
|
|
{
|
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
return bswap(x);
|
|
#else
|
|
return x;
|
|
#endif
|
|
}
|
|
|
|
template <class T> class le_t {
|
|
T m;
|
|
T read() const {
|
|
return le_to_cpu(m);
|
|
};
|
|
void write(const T& n) {
|
|
m = cpu_to_le(n);
|
|
};
|
|
public:
|
|
le_t(void) {
|
|
m = 0;
|
|
};
|
|
le_t(const T& o) {
|
|
write(o);
|
|
};
|
|
operator T() const {
|
|
return read();
|
|
};
|
|
le_t<T> operator++() {
|
|
write(read() + 1);
|
|
return *this;
|
|
};
|
|
le_t<T> operator++(int) {
|
|
write(read() + 1);
|
|
return *this;
|
|
};
|
|
le_t<T> operator--() {
|
|
write(read() - 1);
|
|
return *this;
|
|
};
|
|
le_t<T> operator--(int) {
|
|
write(read() - 1);
|
|
return *this;
|
|
};
|
|
le_t<T>& operator+=(const T& t) {
|
|
write(read() + t);
|
|
return *this;
|
|
};
|
|
le_t<T>& operator-=(const T& t) {
|
|
write(read() - t);
|
|
return *this;
|
|
};
|
|
le_t<T>& operator&=(const le_t<T>& t) {
|
|
m &= t.m;
|
|
return *this;
|
|
};
|
|
le_t<T>& operator|=(const le_t<T>& t) {
|
|
m |= t.m;
|
|
return *this;
|
|
};
|
|
} __attribute__((packed));
|
|
|
|
/* Just copy-and-pasted from le_t. Too lazy to do it right. */
|
|
|
|
template <class T> class be_t {
|
|
T m;
|
|
T read() const {
|
|
return be_to_cpu(m);
|
|
};
|
|
void write(const T& n) {
|
|
m = cpu_to_be(n);
|
|
};
|
|
public:
|
|
be_t(void) {
|
|
m = 0;
|
|
};
|
|
be_t(const T& o) {
|
|
write(o);
|
|
};
|
|
operator T() const {
|
|
return read();
|
|
};
|
|
be_t<T> operator++() {
|
|
write(read() + 1);
|
|
return *this;
|
|
};
|
|
be_t<T> operator++(int) {
|
|
write(read() + 1);
|
|
return *this;
|
|
};
|
|
be_t<T> operator--() {
|
|
write(read() - 1);
|
|
return *this;
|
|
};
|
|
be_t<T> operator--(int) {
|
|
write(read() - 1);
|
|
return *this;
|
|
};
|
|
be_t<T>& operator+=(const T& t) {
|
|
write(read() + t);
|
|
return *this;
|
|
};
|
|
be_t<T>& operator-=(const T& t) {
|
|
write(read() - t);
|
|
return *this;
|
|
};
|
|
be_t<T>& operator&=(const be_t<T>& t) {
|
|
m &= t.m;
|
|
return *this;
|
|
};
|
|
be_t<T>& operator|=(const be_t<T>& t) {
|
|
m |= t.m;
|
|
return *this;
|
|
};
|
|
} __attribute__((packed));
|
|
|
|
/* Define types of native endianness similar to the little and big endian
|
|
* versions below. Not really necessary but useful occasionally to emphasize
|
|
* endianness of data.
|
|
*/
|
|
|
|
typedef int8_t int8_ne_t;
|
|
typedef int16_t int16_ne_t;
|
|
typedef int32_t int32_ne_t;
|
|
typedef int64_t int64_ne_t;
|
|
typedef u_int8_t u_int8_ne_t;
|
|
typedef u_int16_t u_int16_ne_t;
|
|
typedef u_int32_t u_int32_ne_t;
|
|
typedef u_int64_t u_int64_ne_t;
|
|
|
|
|
|
/* The classes work on their native endianness as well, but obviously
|
|
* introduce some overhead. Use the faster typedefs to native types
|
|
* therefore, unless you're debugging.
|
|
*/
|
|
|
|
#if BYTE_ORDER == LITTLE_ENDIAN
|
|
typedef int8_ne_t int8_le_t;
|
|
typedef int16_ne_t int16_le_t;
|
|
typedef int32_ne_t int32_le_t;
|
|
typedef int64_ne_t int64_le_t;
|
|
typedef u_int8_ne_t u_int8_le_t;
|
|
typedef u_int16_ne_t u_int16_le_t;
|
|
typedef u_int32_ne_t u_int32_le_t;
|
|
typedef u_int64_ne_t u_int64_le_t;
|
|
typedef int8_t int8_be_t;
|
|
typedef be_t<int16_t> int16_be_t;
|
|
typedef be_t<int32_t> int32_be_t;
|
|
typedef be_t<int64_t> int64_be_t;
|
|
typedef u_int8_t u_int8_be_t;
|
|
typedef be_t<u_int16_t> u_int16_be_t;
|
|
typedef be_t<u_int32_t> u_int32_be_t;
|
|
typedef be_t<u_int64_t> u_int64_be_t;
|
|
#else
|
|
typedef int8_ne_t int8_be_t;
|
|
typedef int16_ne_t int16_be_t;
|
|
typedef int32_ne_t int32_be_t;
|
|
typedef int64_ne_t int64_be_t;
|
|
typedef u_int8_ne_t u_int8_be_t;
|
|
typedef u_int16_ne_t u_int16_be_t;
|
|
typedef u_int32_ne_t u_int32_be_t;
|
|
typedef u_int64_ne_t u_int64_be_t;
|
|
typedef int8_t int8_le_t;
|
|
typedef le_t<int16_t> int16_le_t;
|
|
typedef le_t<int32_t> int32_le_t;
|
|
typedef le_t<int64_t> int64_le_t;
|
|
typedef u_int8_t u_int8_le_t;
|
|
typedef le_t<u_int16_t> u_int16_le_t;
|
|
typedef le_t<u_int32_t> u_int32_le_t;
|
|
typedef le_t<u_int64_t> u_int64_le_t;
|
|
#endif
|
|
|
|
#endif
|