Endian.h revision 280031
1//===- Endian.h - Utilities for IO with endian specific data ----*- C++ -*-===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file declares generic functions to read and write endian specific data.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_SUPPORT_ENDIAN_H
15#define LLVM_SUPPORT_ENDIAN_H
16
17#include "llvm/Support/AlignOf.h"
18#include "llvm/Support/Host.h"
19#include "llvm/Support/SwapByteOrder.h"
20
21namespace llvm {
22namespace support {
23enum endianness {big, little, native};
24
25// These are named values for common alignments.
26enum {aligned = 0, unaligned = 1};
27
28namespace detail {
29  /// \brief ::value is either alignment, or alignof(T) if alignment is 0.
30  template<class T, int alignment>
31  struct PickAlignment {
32    enum {value = alignment == 0 ? AlignOf<T>::Alignment : alignment};
33  };
34} // end namespace detail
35
36namespace endian {
37/// Swap the bytes of value to match the given endianness.
38template<typename value_type, endianness endian>
39inline value_type byte_swap(value_type value) {
40  if (endian != native && sys::IsBigEndianHost != (endian == big))
41    sys::swapByteOrder(value);
42  return value;
43}
44
45/// Read a value of a particular endianness from memory.
46template<typename value_type,
47         endianness endian,
48         std::size_t alignment>
49inline value_type read(const void *memory) {
50  value_type ret;
51
52  memcpy(&ret,
53         LLVM_ASSUME_ALIGNED(memory,
54           (detail::PickAlignment<value_type, alignment>::value)),
55         sizeof(value_type));
56  return byte_swap<value_type, endian>(ret);
57}
58
59/// Read a value of a particular endianness from a buffer, and increment the
60/// buffer past that value.
61template<typename value_type, endianness endian, std::size_t alignment>
62inline value_type readNext(const unsigned char *&memory) {
63  value_type ret = read<value_type, endian, alignment>(memory);
64  memory += sizeof(value_type);
65  return ret;
66}
67
68/// Write a value to memory with a particular endianness.
69template<typename value_type,
70         endianness endian,
71         std::size_t alignment>
72inline void write(void *memory, value_type value) {
73  value = byte_swap<value_type, endian>(value);
74  memcpy(LLVM_ASSUME_ALIGNED(memory,
75           (detail::PickAlignment<value_type, alignment>::value)),
76         &value,
77         sizeof(value_type));
78}
79} // end namespace endian
80
81namespace detail {
82template<typename value_type,
83         endianness endian,
84         std::size_t alignment>
85struct packed_endian_specific_integral {
86  operator value_type() const {
87    return endian::read<value_type, endian, alignment>(
88      (const void*)Value.buffer);
89  }
90
91  void operator=(value_type newValue) {
92    endian::write<value_type, endian, alignment>(
93      (void*)Value.buffer, newValue);
94  }
95
96  packed_endian_specific_integral &operator+=(value_type newValue) {
97    *this = *this + newValue;
98    return *this;
99  }
100
101  packed_endian_specific_integral &operator-=(value_type newValue) {
102    *this = *this - newValue;
103    return *this;
104  }
105
106private:
107  AlignedCharArray<PickAlignment<value_type, alignment>::value,
108                   sizeof(value_type)> Value;
109
110public:
111  struct ref {
112    explicit ref(void *Ptr) : Ptr(Ptr) {}
113
114    operator value_type() const {
115      return endian::read<value_type, endian, alignment>(Ptr);
116    }
117
118    void operator=(value_type NewValue) {
119      endian::write<value_type, endian, alignment>(Ptr, NewValue);
120    }
121
122  private:
123    void *Ptr;
124  };
125};
126
127} // end namespace detail
128
129typedef detail::packed_endian_specific_integral
130                  <uint16_t, little, unaligned> ulittle16_t;
131typedef detail::packed_endian_specific_integral
132                  <uint32_t, little, unaligned> ulittle32_t;
133typedef detail::packed_endian_specific_integral
134                  <uint64_t, little, unaligned> ulittle64_t;
135
136typedef detail::packed_endian_specific_integral
137                   <int16_t, little, unaligned> little16_t;
138typedef detail::packed_endian_specific_integral
139                   <int32_t, little, unaligned> little32_t;
140typedef detail::packed_endian_specific_integral
141                   <int64_t, little, unaligned> little64_t;
142
143typedef detail::packed_endian_specific_integral
144                    <uint16_t, little, aligned> aligned_ulittle16_t;
145typedef detail::packed_endian_specific_integral
146                    <uint32_t, little, aligned> aligned_ulittle32_t;
147typedef detail::packed_endian_specific_integral
148                    <uint64_t, little, aligned> aligned_ulittle64_t;
149
150typedef detail::packed_endian_specific_integral
151                     <int16_t, little, aligned> aligned_little16_t;
152typedef detail::packed_endian_specific_integral
153                     <int32_t, little, aligned> aligned_little32_t;
154typedef detail::packed_endian_specific_integral
155                     <int64_t, little, aligned> aligned_little64_t;
156
157typedef detail::packed_endian_specific_integral
158                  <uint16_t, big, unaligned>    ubig16_t;
159typedef detail::packed_endian_specific_integral
160                  <uint32_t, big, unaligned>    ubig32_t;
161typedef detail::packed_endian_specific_integral
162                  <uint64_t, big, unaligned>    ubig64_t;
163
164typedef detail::packed_endian_specific_integral
165                   <int16_t, big, unaligned>    big16_t;
166typedef detail::packed_endian_specific_integral
167                   <int32_t, big, unaligned>    big32_t;
168typedef detail::packed_endian_specific_integral
169                   <int64_t, big, unaligned>    big64_t;
170
171typedef detail::packed_endian_specific_integral
172                    <uint16_t, big, aligned>    aligned_ubig16_t;
173typedef detail::packed_endian_specific_integral
174                    <uint32_t, big, aligned>    aligned_ubig32_t;
175typedef detail::packed_endian_specific_integral
176                    <uint64_t, big, aligned>    aligned_ubig64_t;
177
178typedef detail::packed_endian_specific_integral
179                     <int16_t, big, aligned>    aligned_big16_t;
180typedef detail::packed_endian_specific_integral
181                     <int32_t, big, aligned>    aligned_big32_t;
182typedef detail::packed_endian_specific_integral
183                     <int64_t, big, aligned>    aligned_big64_t;
184
185typedef detail::packed_endian_specific_integral
186                  <uint16_t, native, unaligned> unaligned_uint16_t;
187typedef detail::packed_endian_specific_integral
188                  <uint32_t, native, unaligned> unaligned_uint32_t;
189typedef detail::packed_endian_specific_integral
190                  <uint64_t, native, unaligned> unaligned_uint64_t;
191
192typedef detail::packed_endian_specific_integral
193                   <int16_t, native, unaligned> unaligned_int16_t;
194typedef detail::packed_endian_specific_integral
195                   <int32_t, native, unaligned> unaligned_int32_t;
196typedef detail::packed_endian_specific_integral
197                   <int64_t, native, unaligned> unaligned_int64_t;
198} // end namespace llvm
199} // end namespace support
200
201#endif
202