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