hessian2/byte_order.h (147 lines of code) (raw):
#pragma once
#include <cstddef>
#include <cstdint>
#ifdef __APPLE__
#include <libkern/OSByteOrder.h>
#define htole16(x) OSSwapHostToLittleInt16((x))
#define htole32(x) OSSwapHostToLittleInt32((x))
#define htole64(x) OSSwapHostToLittleInt64((x))
#define le16toh(x) OSSwapLittleToHostInt16((x))
#define le32toh(x) OSSwapLittleToHostInt32((x))
#define le64toh(x) OSSwapLittleToHostInt64((x))
#define htobe16(x) OSSwapHostToBigInt16((x))
#define htobe32(x) OSSwapHostToBigInt32((x))
#define htobe64(x) OSSwapHostToBigInt64((x))
#define be16toh(x) OSSwapBigToHostInt16((x))
#define be32toh(x) OSSwapBigToHostInt32((x))
#define be64toh(x) OSSwapBigToHostInt64((x))
#elif (defined WIN32) || (defined _WIN32)
// Ensure that WinSock2.h contains htonll and ntohll.
#undef NO_EXTRA_HTON_FUNCTIONS
#define INCL_EXTRA_HTON_FUNCTIONS
#include <WinSock2.h>
// <winsock2.h> includes <windows.h>, so undef some interfering symbols
#undef DELETE
#undef GetMessage
#define htole16(x) (x)
#define htole32(x) (x)
#define htole64(x) (x)
#define le16toh(x) (x)
#define le32toh(x) (x)
#define le64toh(x) (x)
#define htobe16(x) htons((x))
#define htobe32(x) htonl((x))
#define htobe64(x) htonll((x))
#define be16toh(x) ntohs((x))
#define be32toh(x) ntohl((x))
#define be64toh(x) ntohll((x))
#else
#include <endian.h>
#endif
namespace Hessian2 {
enum class ByteOrderType { Host, LittleEndian, BigEndian };
template <ByteOrderType, typename Integral, size_t = sizeof(Integral)>
struct ByteOrderConverter;
// convenience function that converts an integer from host byte-order to a
// specified endianness
template <ByteOrderType Endianness, typename T>
inline T toEndian(T value) {
return ByteOrderConverter<Endianness, T>::to(value);
}
// convenience function that converts an integer from a specified endianness to
// host byte-order
template <ByteOrderType Endianness, typename T>
inline T fromEndian(T value) {
return ByteOrderConverter<Endianness, T>::from(value);
}
// Implementation details below
// implementation details of ByteOrderConverter for 8-bit host endianness
// integers
template <typename T>
struct ByteOrderConverter<ByteOrderType::Host, T, sizeof(uint8_t)> {
static_assert(sizeof(T) == sizeof(uint8_t), "incorrect type width");
static T to(T value) { return value; }
static T from(T value) { return value; }
};
// implementation details of ByteOrderConverter for 16-bit host endianness
// integers
template <typename T>
struct ByteOrderConverter<ByteOrderType::Host, T, sizeof(uint16_t)> {
static_assert(sizeof(T) == sizeof(uint16_t), "incorrect type width");
static T to(T value) { return value; }
static T from(T value) { return value; }
};
// implementation details of ByteOrderConverter for 32-bit host endianness
// integers
template <typename T>
struct ByteOrderConverter<ByteOrderType::Host, T, sizeof(uint32_t)> {
static_assert(sizeof(T) == sizeof(uint32_t), "incorrect type width");
static T to(T value) { return value; }
static T from(T value) { return value; }
};
// implementation details of ByteOrderConverter for 64-bit host endianness
// integers
template <typename T>
struct ByteOrderConverter<ByteOrderType::Host, T, sizeof(uint64_t)> {
static_assert(sizeof(T) == sizeof(uint64_t), "incorrect type width");
static T to(T value) { return value; }
static T from(T value) { return value; }
};
// implementation details of ByteOrderConverter for 8-bit little endian
// integers
template <typename T>
struct ByteOrderConverter<ByteOrderType::LittleEndian, T, sizeof(uint8_t)> {
static_assert(sizeof(T) == sizeof(uint8_t), "incorrect type width");
static T to(T value) { return value; }
static T from(T value) { return value; }
};
// implementation details of ByteOrderConverter for 16-bit little endian
// integers
template <typename T>
struct ByteOrderConverter<ByteOrderType::LittleEndian, T, sizeof(uint16_t)> {
static_assert(sizeof(T) == sizeof(uint16_t), "incorrect type width");
static T to(T value) {
return static_cast<T>(htole16(static_cast<uint16_t>(value)));
}
static T from(T value) {
return static_cast<T>(le16toh(static_cast<uint16_t>(value)));
}
};
// implementation details of ByteOrderConverter for 32-bit little endian
// integers
template <typename T>
struct ByteOrderConverter<ByteOrderType::LittleEndian, T, sizeof(uint32_t)> {
static_assert(sizeof(T) == sizeof(uint32_t), "incorrect type width");
static T to(T value) {
return static_cast<T>(htole32(static_cast<uint32_t>(value)));
}
static T from(T value) {
return static_cast<T>(le32toh(static_cast<uint32_t>(value)));
}
};
// implementation details of ByteOrderConverter for 64-bit little endian
// integers
template <typename T>
struct ByteOrderConverter<ByteOrderType::LittleEndian, T, sizeof(uint64_t)> {
static_assert(sizeof(T) == sizeof(uint64_t), "incorrect type width");
static T to(T value) {
return static_cast<T>(htole64(static_cast<uint64_t>(value)));
}
static T from(T value) {
return static_cast<T>(le64toh(static_cast<uint64_t>(value)));
}
};
// implementation details of ByteOrderConverter for 8-bit big endian integers
template <typename T>
struct ByteOrderConverter<ByteOrderType::BigEndian, T, sizeof(uint8_t)> {
static_assert(sizeof(T) == sizeof(uint8_t), "incorrect type width");
static T to(T value) { return value; }
static T from(T value) { return value; }
};
// implementation details of ByteOrderConverter for 16-bit big endian integers
template <typename T>
struct ByteOrderConverter<ByteOrderType::BigEndian, T, sizeof(uint16_t)> {
static_assert(sizeof(T) == sizeof(uint16_t), "incorrect type width");
static T to(T value) {
return static_cast<T>(htobe16(static_cast<uint16_t>(value)));
}
static T from(T value) {
return static_cast<T>(be16toh(static_cast<uint16_t>(value)));
}
};
// implementation details of ByteOrderConverter for 32-bit big endian integers
template <typename T>
struct ByteOrderConverter<ByteOrderType::BigEndian, T, sizeof(uint32_t)> {
static_assert(sizeof(T) == sizeof(uint32_t), "incorrect type width");
static T to(T value) {
return static_cast<T>(htobe32(static_cast<uint32_t>(value)));
}
static T from(T value) {
return static_cast<T>(be32toh(static_cast<uint32_t>(value)));
}
};
// implementation details of ByteOrderConverter for 64-bit big endian integers
template <typename T>
struct ByteOrderConverter<ByteOrderType::BigEndian, T, sizeof(uint64_t)> {
static_assert(sizeof(T) == sizeof(uint64_t), "incorrect type width");
static T to(T value) {
return static_cast<T>(htobe64(static_cast<uint64_t>(value)));
}
static T from(T value) {
return static_cast<T>(be64toh(static_cast<uint64_t>(value)));
}
};
} // namespace Hessian2