blob: af1b506d6cf452eba95a79170b494d9d5eade913 [file] [log] [blame]
//===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file declares generic functions to read and write endian specific data.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_SUPPORT_ENDIAN_H
#define LLVM_SUPPORT_ENDIAN_H
#include "llvm/Support/Host.h"
#include "llvm/Support/SwapByteOrder.h"
#include "llvm/Support/type_traits.h"
namespace llvm {
namespace support {
enum endianness {big, little};
enum alignment {unaligned, aligned};
namespace detail {
template<typename value_type, alignment align>
struct alignment_access_helper;
template<typename value_type>
struct alignment_access_helper<value_type, aligned>
{
value_type val;
};
// Provides unaligned loads and stores.
#pragma pack(push)
#pragma pack(1)
template<typename value_type>
struct alignment_access_helper<value_type, unaligned>
{
value_type val;
};
#pragma pack(pop)
} // end namespace detail
namespace endian {
template<typename value_type, alignment align>
static value_type read_le(const void *memory) {
value_type t =
reinterpret_cast<const detail::alignment_access_helper
<value_type, align> *>(memory)->val;
if (sys::isBigEndianHost())
return sys::SwapByteOrder(t);
return t;
}
template<typename value_type, alignment align>
static void write_le(void *memory, value_type value) {
if (sys::isBigEndianHost())
value = sys::SwapByteOrder(value);
reinterpret_cast<detail::alignment_access_helper<value_type, align> *>
(memory)->val = value;
}
template<typename value_type, alignment align>
static value_type read_be(const void *memory) {
value_type t =
reinterpret_cast<const detail::alignment_access_helper
<value_type, align> *>(memory)->val;
if (sys::isLittleEndianHost())
return sys::SwapByteOrder(t);
return t;
}
template<typename value_type, alignment align>
static void write_be(void *memory, value_type value) {
if (sys::isLittleEndianHost())
value = sys::SwapByteOrder(value);
reinterpret_cast<detail::alignment_access_helper<value_type, align> *>
(memory)->val = value;
}
}
namespace detail {
template<typename value_type,
endianness endian,
alignment align>
class packed_endian_specific_integral;
template<typename value_type>
class packed_endian_specific_integral<value_type, little, unaligned> {
public:
operator value_type() const {
return endian::read_le<value_type, unaligned>(Value);
}
private:
uint8_t Value[sizeof(value_type)];
};
template<typename value_type>
class packed_endian_specific_integral<value_type, big, unaligned> {
public:
operator value_type() const {
return endian::read_be<value_type, unaligned>(Value);
}
private:
uint8_t Value[sizeof(value_type)];
};
template<typename value_type>
class packed_endian_specific_integral<value_type, little, aligned> {
public:
operator value_type() const {
return endian::read_le<value_type, aligned>(&Value);
}
private:
value_type Value;
};
template<typename value_type>
class packed_endian_specific_integral<value_type, big, aligned> {
public:
operator value_type() const {
return endian::read_be<value_type, aligned>(&Value);
}
private:
value_type Value;
};
} // end namespace detail
typedef detail::packed_endian_specific_integral
<uint8_t, little, unaligned> ulittle8_t;
typedef detail::packed_endian_specific_integral
<uint16_t, little, unaligned> ulittle16_t;
typedef detail::packed_endian_specific_integral
<uint32_t, little, unaligned> ulittle32_t;
typedef detail::packed_endian_specific_integral
<uint64_t, little, unaligned> ulittle64_t;
typedef detail::packed_endian_specific_integral
<int8_t, little, unaligned> little8_t;
typedef detail::packed_endian_specific_integral
<int16_t, little, unaligned> little16_t;
typedef detail::packed_endian_specific_integral
<int32_t, little, unaligned> little32_t;
typedef detail::packed_endian_specific_integral
<int64_t, little, unaligned> little64_t;
typedef detail::packed_endian_specific_integral
<uint8_t, little, aligned> aligned_ulittle8_t;
typedef detail::packed_endian_specific_integral
<uint16_t, little, aligned> aligned_ulittle16_t;
typedef detail::packed_endian_specific_integral
<uint32_t, little, aligned> aligned_ulittle32_t;
typedef detail::packed_endian_specific_integral
<uint64_t, little, aligned> aligned_ulittle64_t;
typedef detail::packed_endian_specific_integral
<int8_t, little, aligned> aligned_little8_t;
typedef detail::packed_endian_specific_integral
<int16_t, little, aligned> aligned_little16_t;
typedef detail::packed_endian_specific_integral
<int32_t, little, aligned> aligned_little32_t;
typedef detail::packed_endian_specific_integral
<int64_t, little, aligned> aligned_little64_t;
typedef detail::packed_endian_specific_integral
<uint8_t, big, unaligned> ubig8_t;
typedef detail::packed_endian_specific_integral
<uint16_t, big, unaligned> ubig16_t;
typedef detail::packed_endian_specific_integral
<uint32_t, big, unaligned> ubig32_t;
typedef detail::packed_endian_specific_integral
<uint64_t, big, unaligned> ubig64_t;
typedef detail::packed_endian_specific_integral
<int8_t, big, unaligned> big8_t;
typedef detail::packed_endian_specific_integral
<int16_t, big, unaligned> big16_t;
typedef detail::packed_endian_specific_integral
<int32_t, big, unaligned> big32_t;
typedef detail::packed_endian_specific_integral
<int64_t, big, unaligned> big64_t;
typedef detail::packed_endian_specific_integral
<uint8_t, big, aligned> aligned_ubig8_t;
typedef detail::packed_endian_specific_integral
<uint16_t, big, aligned> aligned_ubig16_t;
typedef detail::packed_endian_specific_integral
<uint32_t, big, aligned> aligned_ubig32_t;
typedef detail::packed_endian_specific_integral
<uint64_t, big, aligned> aligned_ubig64_t;
typedef detail::packed_endian_specific_integral
<int8_t, big, aligned> aligned_big8_t;
typedef detail::packed_endian_specific_integral
<int16_t, big, aligned> aligned_big16_t;
typedef detail::packed_endian_specific_integral
<int32_t, big, aligned> aligned_big32_t;
typedef detail::packed_endian_specific_integral
<int64_t, big, aligned> aligned_big64_t;
} // end namespace llvm
} // end namespace support
#endif