Endian.h revision 251662
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#include "llvm/Support/type_traits.h"
21
22namespace llvm {
23namespace support {
24enum endianness {big, little, native};
25
26// These are named values for common alignments.
27enum {aligned = 0, unaligned = 1};
28
29namespace detail {
30  /// \brief ::value is either alignment, or alignof(T) if alignment is 0.
31  template<class T, int alignment>
32  struct PickAlignment {
33    enum {value = alignment == 0 ? AlignOf<T>::Alignment : alignment};
34  };
35} // end namespace detail
36
37namespace endian {
38template<typename value_type, endianness endian>
39inline value_type byte_swap(value_type value) {
40  if (endian != native && sys::IsBigEndianHost != (endian == big))
41    return sys::SwapByteOrder(value);
42  return value;
43}
44
45template<typename value_type,
46         endianness endian,
47         std::size_t alignment>
48inline value_type read(const void *memory) {
49  value_type ret;
50
51  memcpy(&ret,
52         LLVM_ASSUME_ALIGNED(memory,
53           (detail::PickAlignment<value_type, alignment>::value)),
54         sizeof(value_type));
55  return byte_swap<value_type, endian>(ret);
56}
57
58template<typename value_type,
59         endianness endian,
60         std::size_t alignment>
61inline void write(void *memory, value_type value) {
62  value = byte_swap<value_type, endian>(value);
63  memcpy(LLVM_ASSUME_ALIGNED(memory,
64           (detail::PickAlignment<value_type, alignment>::value)),
65         &value,
66         sizeof(value_type));
67}
68} // end namespace endian
69
70namespace detail {
71template<typename value_type,
72         endianness endian,
73         std::size_t alignment>
74struct packed_endian_specific_integral {
75  operator value_type() const {
76    return endian::read<value_type, endian, alignment>(
77      (const void*)Value.buffer);
78  }
79
80  void operator=(value_type newValue) {
81    endian::write<value_type, endian, alignment>(
82      (void*)Value.buffer, newValue);
83  }
84
85private:
86  AlignedCharArray<PickAlignment<value_type, alignment>::value,
87                   sizeof(value_type)> Value;
88};
89} // end namespace detail
90
91typedef detail::packed_endian_specific_integral
92                  <uint8_t, little, unaligned>  ulittle8_t;
93typedef detail::packed_endian_specific_integral
94                  <uint16_t, little, unaligned> ulittle16_t;
95typedef detail::packed_endian_specific_integral
96                  <uint32_t, little, unaligned> ulittle32_t;
97typedef detail::packed_endian_specific_integral
98                  <uint64_t, little, unaligned> ulittle64_t;
99
100typedef detail::packed_endian_specific_integral
101                   <int8_t, little, unaligned>  little8_t;
102typedef detail::packed_endian_specific_integral
103                   <int16_t, little, unaligned> little16_t;
104typedef detail::packed_endian_specific_integral
105                   <int32_t, little, unaligned> little32_t;
106typedef detail::packed_endian_specific_integral
107                   <int64_t, little, unaligned> little64_t;
108
109typedef detail::packed_endian_specific_integral
110                    <uint8_t, little, aligned>  aligned_ulittle8_t;
111typedef detail::packed_endian_specific_integral
112                    <uint16_t, little, aligned> aligned_ulittle16_t;
113typedef detail::packed_endian_specific_integral
114                    <uint32_t, little, aligned> aligned_ulittle32_t;
115typedef detail::packed_endian_specific_integral
116                    <uint64_t, little, aligned> aligned_ulittle64_t;
117
118typedef detail::packed_endian_specific_integral
119                     <int8_t, little, aligned>  aligned_little8_t;
120typedef detail::packed_endian_specific_integral
121                     <int16_t, little, aligned> aligned_little16_t;
122typedef detail::packed_endian_specific_integral
123                     <int32_t, little, aligned> aligned_little32_t;
124typedef detail::packed_endian_specific_integral
125                     <int64_t, little, aligned> aligned_little64_t;
126
127typedef detail::packed_endian_specific_integral
128                  <uint8_t, big, unaligned>     ubig8_t;
129typedef detail::packed_endian_specific_integral
130                  <uint16_t, big, unaligned>    ubig16_t;
131typedef detail::packed_endian_specific_integral
132                  <uint32_t, big, unaligned>    ubig32_t;
133typedef detail::packed_endian_specific_integral
134                  <uint64_t, big, unaligned>    ubig64_t;
135
136typedef detail::packed_endian_specific_integral
137                   <int8_t, big, unaligned>     big8_t;
138typedef detail::packed_endian_specific_integral
139                   <int16_t, big, unaligned>    big16_t;
140typedef detail::packed_endian_specific_integral
141                   <int32_t, big, unaligned>    big32_t;
142typedef detail::packed_endian_specific_integral
143                   <int64_t, big, unaligned>    big64_t;
144
145typedef detail::packed_endian_specific_integral
146                    <uint8_t, big, aligned>     aligned_ubig8_t;
147typedef detail::packed_endian_specific_integral
148                    <uint16_t, big, aligned>    aligned_ubig16_t;
149typedef detail::packed_endian_specific_integral
150                    <uint32_t, big, aligned>    aligned_ubig32_t;
151typedef detail::packed_endian_specific_integral
152                    <uint64_t, big, aligned>    aligned_ubig64_t;
153
154typedef detail::packed_endian_specific_integral
155                     <int8_t, big, aligned>     aligned_big8_t;
156typedef detail::packed_endian_specific_integral
157                     <int16_t, big, aligned>    aligned_big16_t;
158typedef detail::packed_endian_specific_integral
159                     <int32_t, big, aligned>    aligned_big32_t;
160typedef detail::packed_endian_specific_integral
161                     <int64_t, big, aligned>    aligned_big64_t;
162
163typedef detail::packed_endian_specific_integral
164                  <uint16_t, native, unaligned> unaligned_uint16_t;
165typedef detail::packed_endian_specific_integral
166                  <uint32_t, native, unaligned> unaligned_uint32_t;
167typedef detail::packed_endian_specific_integral
168                  <uint64_t, native, unaligned> unaligned_uint64_t;
169
170typedef detail::packed_endian_specific_integral
171                   <int16_t, native, unaligned> unaligned_int16_t;
172typedef detail::packed_endian_specific_integral
173                   <int32_t, native, unaligned> unaligned_int32_t;
174typedef detail::packed_endian_specific_integral
175                   <int64_t, native, unaligned> unaligned_int64_t;
176} // end namespace llvm
177} // end namespace support
178
179#endif
180