Endian.h revision 224145
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/Host.h"
18#include "llvm/Support/SwapByteOrder.h"
19#include "llvm/Support/type_traits.h"
20
21namespace llvm {
22namespace support {
23
24enum endianness {big, little};
25enum alignment {unaligned, aligned};
26
27namespace detail {
28
29template<typename value_type, alignment align>
30struct alignment_access_helper;
31
32template<typename value_type>
33struct alignment_access_helper<value_type, aligned>
34{
35  value_type val;
36};
37
38// Provides unaligned loads and stores.
39#pragma pack(push)
40#pragma pack(1)
41template<typename value_type>
42struct alignment_access_helper<value_type, unaligned>
43{
44  value_type val;
45};
46#pragma pack(pop)
47
48} // end namespace detail
49
50namespace endian {
51  template<typename value_type, alignment align>
52  static value_type read_le(const void *memory) {
53    value_type t =
54      reinterpret_cast<const detail::alignment_access_helper
55        <value_type, align> *>(memory)->val;
56    if (sys::isBigEndianHost())
57      return sys::SwapByteOrder(t);
58    return t;
59  }
60
61  template<typename value_type, alignment align>
62  static void write_le(void *memory, value_type value) {
63    if (sys::isBigEndianHost())
64      value = sys::SwapByteOrder(value);
65    reinterpret_cast<detail::alignment_access_helper<value_type, align> *>
66      (memory)->val = value;
67  }
68
69  template<typename value_type, alignment align>
70  static value_type read_be(const void *memory) {
71    value_type t =
72      reinterpret_cast<const detail::alignment_access_helper
73        <value_type, align> *>(memory)->val;
74    if (sys::isLittleEndianHost())
75      return sys::SwapByteOrder(t);
76    return t;
77  }
78
79  template<typename value_type, alignment align>
80  static void write_be(void *memory, value_type value) {
81    if (sys::isLittleEndianHost())
82      value = sys::SwapByteOrder(value);
83    reinterpret_cast<detail::alignment_access_helper<value_type, align> *>
84      (memory)->val = value;
85  }
86}
87
88namespace detail {
89
90template<typename value_type,
91         endianness endian,
92         alignment  align>
93class packed_endian_specific_integral;
94
95template<typename value_type>
96class packed_endian_specific_integral<value_type, little, unaligned> {
97public:
98  operator value_type() const {
99    return endian::read_le<value_type, unaligned>(Value);
100  }
101private:
102  uint8_t Value[sizeof(value_type)];
103};
104
105template<typename value_type>
106class packed_endian_specific_integral<value_type, big, unaligned> {
107public:
108  operator value_type() const {
109    return endian::read_be<value_type, unaligned>(Value);
110  }
111private:
112  uint8_t Value[sizeof(value_type)];
113};
114
115template<typename value_type>
116class packed_endian_specific_integral<value_type, little, aligned> {
117public:
118  operator value_type() const {
119    return endian::read_le<value_type, aligned>(&Value);
120  }
121private:
122  value_type Value;
123};
124
125template<typename value_type>
126class packed_endian_specific_integral<value_type, big, aligned> {
127public:
128  operator value_type() const {
129    return endian::read_be<value_type, aligned>(&Value);
130  }
131private:
132  value_type Value;
133};
134
135} // end namespace detail
136
137typedef detail::packed_endian_specific_integral
138                  <uint8_t, little, unaligned>  ulittle8_t;
139typedef detail::packed_endian_specific_integral
140                  <uint16_t, little, unaligned> ulittle16_t;
141typedef detail::packed_endian_specific_integral
142                  <uint32_t, little, unaligned> ulittle32_t;
143typedef detail::packed_endian_specific_integral
144                  <uint64_t, little, unaligned> ulittle64_t;
145
146typedef detail::packed_endian_specific_integral
147                   <int8_t, little, unaligned>  little8_t;
148typedef detail::packed_endian_specific_integral
149                   <int16_t, little, unaligned> little16_t;
150typedef detail::packed_endian_specific_integral
151                   <int32_t, little, unaligned> little32_t;
152typedef detail::packed_endian_specific_integral
153                   <int64_t, little, unaligned> little64_t;
154
155typedef detail::packed_endian_specific_integral
156                    <uint8_t, little, aligned>  aligned_ulittle8_t;
157typedef detail::packed_endian_specific_integral
158                    <uint16_t, little, aligned> aligned_ulittle16_t;
159typedef detail::packed_endian_specific_integral
160                    <uint32_t, little, aligned> aligned_ulittle32_t;
161typedef detail::packed_endian_specific_integral
162                    <uint64_t, little, aligned> aligned_ulittle64_t;
163
164typedef detail::packed_endian_specific_integral
165                     <int8_t, little, aligned>  aligned_little8_t;
166typedef detail::packed_endian_specific_integral
167                     <int16_t, little, aligned> aligned_little16_t;
168typedef detail::packed_endian_specific_integral
169                     <int32_t, little, aligned> aligned_little32_t;
170typedef detail::packed_endian_specific_integral
171                     <int64_t, little, aligned> aligned_little64_t;
172
173typedef detail::packed_endian_specific_integral
174                  <uint8_t, big, unaligned>     ubig8_t;
175typedef detail::packed_endian_specific_integral
176                  <uint16_t, big, unaligned>    ubig16_t;
177typedef detail::packed_endian_specific_integral
178                  <uint32_t, big, unaligned>    ubig32_t;
179typedef detail::packed_endian_specific_integral
180                  <uint64_t, big, unaligned>    ubig64_t;
181
182typedef detail::packed_endian_specific_integral
183                   <int8_t, big, unaligned>     big8_t;
184typedef detail::packed_endian_specific_integral
185                   <int16_t, big, unaligned>    big16_t;
186typedef detail::packed_endian_specific_integral
187                   <int32_t, big, unaligned>    big32_t;
188typedef detail::packed_endian_specific_integral
189                   <int64_t, big, unaligned>    big64_t;
190
191typedef detail::packed_endian_specific_integral
192                    <uint8_t, big, aligned>     aligned_ubig8_t;
193typedef detail::packed_endian_specific_integral
194                    <uint16_t, big, aligned>    aligned_ubig16_t;
195typedef detail::packed_endian_specific_integral
196                    <uint32_t, big, aligned>    aligned_ubig32_t;
197typedef detail::packed_endian_specific_integral
198                    <uint64_t, big, aligned>    aligned_ubig64_t;
199
200typedef detail::packed_endian_specific_integral
201                     <int8_t, big, aligned>     aligned_big8_t;
202typedef detail::packed_endian_specific_integral
203                     <int16_t, big, aligned>    aligned_big16_t;
204typedef detail::packed_endian_specific_integral
205                     <int32_t, big, aligned>    aligned_big32_t;
206typedef detail::packed_endian_specific_integral
207                     <int64_t, big, aligned>    aligned_big64_t;
208
209} // end namespace llvm
210} // end namespace support
211
212#endif
213