Branch data Line data Source code
1 : : /* CC0 (Public domain) - see LICENSE file for details */
2 : : #ifndef CCAN_ENDIAN_H
3 : : #define CCAN_ENDIAN_H
4 : : #include <stdint.h>
5 : : #include "config.h"
6 : :
7 : : /**
8 : : * BSWAP_16 - reverse bytes in a constant uint16_t value.
9 : : * @val: constant value whose bytes to swap.
10 : : *
11 : : * Designed to be usable in constant-requiring initializers.
12 : : *
13 : : * Example:
14 : : * struct mystruct {
15 : : * char buf[BSWAP_16(0x1234)];
16 : : * };
17 : : */
18 : : #define BSWAP_16(val) \
19 : : ((((uint16_t)(val) & 0x00ff) << 8) \
20 : : | (((uint16_t)(val) & 0xff00) >> 8))
21 : :
22 : : /**
23 : : * BSWAP_32 - reverse bytes in a constant uint32_t value.
24 : : * @val: constant value whose bytes to swap.
25 : : *
26 : : * Designed to be usable in constant-requiring initializers.
27 : : *
28 : : * Example:
29 : : * struct mystruct {
30 : : * char buf[BSWAP_32(0xff000000)];
31 : : * };
32 : : */
33 : : #define BSWAP_32(val) \
34 : : ((((uint32_t)(val) & 0x000000ff) << 24) \
35 : : | (((uint32_t)(val) & 0x0000ff00) << 8) \
36 : : | (((uint32_t)(val) & 0x00ff0000) >> 8) \
37 : : | (((uint32_t)(val) & 0xff000000) >> 24))
38 : :
39 : : /**
40 : : * BSWAP_64 - reverse bytes in a constant uint64_t value.
41 : : * @val: constantvalue whose bytes to swap.
42 : : *
43 : : * Designed to be usable in constant-requiring initializers.
44 : : *
45 : : * Example:
46 : : * struct mystruct {
47 : : * char buf[BSWAP_64(0xff00000000000000ULL)];
48 : : * };
49 : : */
50 : : #define BSWAP_64(val) \
51 : : ((((uint64_t)(val) & 0x00000000000000ffULL) << 56) \
52 : : | (((uint64_t)(val) & 0x000000000000ff00ULL) << 40) \
53 : : | (((uint64_t)(val) & 0x0000000000ff0000ULL) << 24) \
54 : : | (((uint64_t)(val) & 0x00000000ff000000ULL) << 8) \
55 : : | (((uint64_t)(val) & 0x000000ff00000000ULL) >> 8) \
56 : : | (((uint64_t)(val) & 0x0000ff0000000000ULL) >> 24) \
57 : : | (((uint64_t)(val) & 0x00ff000000000000ULL) >> 40) \
58 : : | (((uint64_t)(val) & 0xff00000000000000ULL) >> 56))
59 : :
60 : : #if HAVE_BYTESWAP_H
61 : : #include <byteswap.h>
62 : : #else
63 : : /**
64 : : * bswap_16 - reverse bytes in a uint16_t value.
65 : : * @val: value whose bytes to swap.
66 : : *
67 : : * Example:
68 : : * // Output contains "1024 is 4 as two bytes reversed"
69 : : * printf("1024 is %u as two bytes reversed\n", bswap_16(1024));
70 : : */
71 : : static inline uint16_t bswap_16(uint16_t val)
72 : : {
73 : : return BSWAP_16(val);
74 : : }
75 : :
76 : : /**
77 : : * bswap_32 - reverse bytes in a uint32_t value.
78 : : * @val: value whose bytes to swap.
79 : : *
80 : : * Example:
81 : : * // Output contains "1024 is 262144 as four bytes reversed"
82 : : * printf("1024 is %u as four bytes reversed\n", bswap_32(1024));
83 : : */
84 : : static inline uint32_t bswap_32(uint32_t val)
85 : : {
86 : : return BSWAP_32(val);
87 : : }
88 : : #endif /* !HAVE_BYTESWAP_H */
89 : :
90 : : #if !HAVE_BSWAP_64
91 : : /**
92 : : * bswap_64 - reverse bytes in a uint64_t value.
93 : : * @val: value whose bytes to swap.
94 : : *
95 : : * Example:
96 : : * // Output contains "1024 is 1125899906842624 as eight bytes reversed"
97 : : * printf("1024 is %llu as eight bytes reversed\n",
98 : : * (unsigned long long)bswap_64(1024));
99 : : */
100 : : static inline uint64_t bswap_64(uint64_t val)
101 : : {
102 : : return BSWAP_64(val);
103 : : }
104 : : #endif
105 : :
106 : : /* Needed for Glibc like endiness check */
107 : : #define __LITTLE_ENDIAN 1234
108 : : #define __BIG_ENDIAN 4321
109 : :
110 : : /* Sanity check the defines. We don't handle weird endianness. */
111 : : #if !HAVE_LITTLE_ENDIAN && !HAVE_BIG_ENDIAN
112 : : #error "Unknown endian"
113 : : #elif HAVE_LITTLE_ENDIAN && HAVE_BIG_ENDIAN
114 : : #error "Can't compile for both big and little endian."
115 : : #elif HAVE_LITTLE_ENDIAN
116 : : #ifndef __BYTE_ORDER
117 : : #define __BYTE_ORDER __LITTLE_ENDIAN
118 : : #elif __BYTE_ORDER != __LITTLE_ENDIAN
119 : : #error "__BYTE_ORDER already defined, but not equal to __LITTLE_ENDIAN"
120 : : #endif
121 : : #elif HAVE_BIG_ENDIAN
122 : : #ifndef __BYTE_ORDER
123 : : #define __BYTE_ORDER __BIG_ENDIAN
124 : : #elif __BYTE_ORDER != __BIG_ENDIAN
125 : : #error "__BYTE_ORDER already defined, but not equal to __BIG_ENDIAN"
126 : : #endif
127 : : #endif
128 : :
129 : :
130 : : #ifdef __CHECKER__
131 : : /* sparse needs forcing to remove bitwise attribute from ccan/short_types */
132 : : #define ENDIAN_CAST __attribute__((force))
133 : : #define ENDIAN_TYPE __attribute__((bitwise))
134 : : #else
135 : : #define ENDIAN_CAST
136 : : #define ENDIAN_TYPE
137 : : #endif
138 : :
139 : : typedef uint64_t ENDIAN_TYPE leint64_t;
140 : : typedef uint64_t ENDIAN_TYPE beint64_t;
141 : : typedef uint32_t ENDIAN_TYPE leint32_t;
142 : : typedef uint32_t ENDIAN_TYPE beint32_t;
143 : : typedef uint16_t ENDIAN_TYPE leint16_t;
144 : : typedef uint16_t ENDIAN_TYPE beint16_t;
145 : :
146 : : #if HAVE_LITTLE_ENDIAN
147 : : /**
148 : : * CPU_TO_LE64 - convert a constant uint64_t value to little-endian
149 : : * @native: constant to convert
150 : : */
151 : : #define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)(native))
152 : :
153 : : /**
154 : : * CPU_TO_LE32 - convert a constant uint32_t value to little-endian
155 : : * @native: constant to convert
156 : : */
157 : : #define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)(native))
158 : :
159 : : /**
160 : : * CPU_TO_LE16 - convert a constant uint16_t value to little-endian
161 : : * @native: constant to convert
162 : : */
163 : : #define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)(native))
164 : :
165 : : /**
166 : : * LE64_TO_CPU - convert a little-endian uint64_t constant
167 : : * @le_val: little-endian constant to convert
168 : : */
169 : : #define LE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val))
170 : :
171 : : /**
172 : : * LE32_TO_CPU - convert a little-endian uint32_t constant
173 : : * @le_val: little-endian constant to convert
174 : : */
175 : : #define LE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val))
176 : :
177 : : /**
178 : : * LE16_TO_CPU - convert a little-endian uint16_t constant
179 : : * @le_val: little-endian constant to convert
180 : : */
181 : : #define LE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val))
182 : :
183 : : #else /* ... HAVE_BIG_ENDIAN */
184 : : #define CPU_TO_LE64(native) ((ENDIAN_CAST leint64_t)BSWAP_64(native))
185 : : #define CPU_TO_LE32(native) ((ENDIAN_CAST leint32_t)BSWAP_32(native))
186 : : #define CPU_TO_LE16(native) ((ENDIAN_CAST leint16_t)BSWAP_16(native))
187 : : #define LE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val)
188 : : #define LE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val)
189 : : #define LE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val)
190 : : #endif /* HAVE_BIG_ENDIAN */
191 : :
192 : : #if HAVE_BIG_ENDIAN
193 : : /**
194 : : * CPU_TO_BE64 - convert a constant uint64_t value to big-endian
195 : : * @native: constant to convert
196 : : */
197 : : #define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)(native))
198 : :
199 : : /**
200 : : * CPU_TO_BE32 - convert a constant uint32_t value to big-endian
201 : : * @native: constant to convert
202 : : */
203 : : #define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)(native))
204 : :
205 : : /**
206 : : * CPU_TO_BE16 - convert a constant uint16_t value to big-endian
207 : : * @native: constant to convert
208 : : */
209 : : #define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)(native))
210 : :
211 : : /**
212 : : * BE64_TO_CPU - convert a big-endian uint64_t constant
213 : : * @le_val: big-endian constant to convert
214 : : */
215 : : #define BE64_TO_CPU(le_val) ((ENDIAN_CAST uint64_t)(le_val))
216 : :
217 : : /**
218 : : * BE32_TO_CPU - convert a big-endian uint32_t constant
219 : : * @le_val: big-endian constant to convert
220 : : */
221 : : #define BE32_TO_CPU(le_val) ((ENDIAN_CAST uint32_t)(le_val))
222 : :
223 : : /**
224 : : * BE16_TO_CPU - convert a big-endian uint16_t constant
225 : : * @le_val: big-endian constant to convert
226 : : */
227 : : #define BE16_TO_CPU(le_val) ((ENDIAN_CAST uint16_t)(le_val))
228 : :
229 : : #else /* ... HAVE_LITTLE_ENDIAN */
230 : : #define CPU_TO_BE64(native) ((ENDIAN_CAST beint64_t)BSWAP_64(native))
231 : : #define CPU_TO_BE32(native) ((ENDIAN_CAST beint32_t)BSWAP_32(native))
232 : : #define CPU_TO_BE16(native) ((ENDIAN_CAST beint16_t)BSWAP_16(native))
233 : : #define BE64_TO_CPU(le_val) BSWAP_64((ENDIAN_CAST uint64_t)le_val)
234 : : #define BE32_TO_CPU(le_val) BSWAP_32((ENDIAN_CAST uint32_t)le_val)
235 : : #define BE16_TO_CPU(le_val) BSWAP_16((ENDIAN_CAST uint16_t)le_val)
236 : : #endif /* HAVE_LITTE_ENDIAN */
237 : :
238 : :
239 : : /**
240 : : * cpu_to_le64 - convert a uint64_t value to little-endian
241 : : * @native: value to convert
242 : : */
243 : : static inline leint64_t cpu_to_le64(uint64_t native)
244 : : {
245 : : return CPU_TO_LE64(native);
246 : : }
247 : :
248 : : /**
249 : : * cpu_to_le32 - convert a uint32_t value to little-endian
250 : : * @native: value to convert
251 : : */
252 : : static inline leint32_t cpu_to_le32(uint32_t native)
253 : : {
254 : : return CPU_TO_LE32(native);
255 : : }
256 : :
257 : : /**
258 : : * cpu_to_le16 - convert a uint16_t value to little-endian
259 : : * @native: value to convert
260 : : */
261 : : static inline leint16_t cpu_to_le16(uint16_t native)
262 : : {
263 : : return CPU_TO_LE16(native);
264 : : }
265 : :
266 : : /**
267 : : * le64_to_cpu - convert a little-endian uint64_t value
268 : : * @le_val: little-endian value to convert
269 : : */
270 : : static inline uint64_t le64_to_cpu(leint64_t le_val)
271 : : {
272 : : return LE64_TO_CPU(le_val);
273 : : }
274 : :
275 : : /**
276 : : * le32_to_cpu - convert a little-endian uint32_t value
277 : : * @le_val: little-endian value to convert
278 : : */
279 : : static inline uint32_t le32_to_cpu(leint32_t le_val)
280 : : {
281 : : return LE32_TO_CPU(le_val);
282 : : }
283 : :
284 : : /**
285 : : * le16_to_cpu - convert a little-endian uint16_t value
286 : : * @le_val: little-endian value to convert
287 : : */
288 : : static inline uint16_t le16_to_cpu(leint16_t le_val)
289 : : {
290 : : return LE16_TO_CPU(le_val);
291 : : }
292 : :
293 : : /**
294 : : * cpu_to_be64 - convert a uint64_t value to big endian.
295 : : * @native: value to convert
296 : : */
297 : 0 : static inline beint64_t cpu_to_be64(uint64_t native)
298 : : {
299 : 0 : return CPU_TO_BE64(native);
300 : : }
301 : :
302 : : /**
303 : : * cpu_to_be32 - convert a uint32_t value to big endian.
304 : : * @native: value to convert
305 : : */
306 : 40 : static inline beint32_t cpu_to_be32(uint32_t native)
307 : : {
308 : 40 : return CPU_TO_BE32(native);
309 : : }
310 : :
311 : : /**
312 : : * cpu_to_be16 - convert a uint16_t value to big endian.
313 : : * @native: value to convert
314 : : */
315 : 34 : static inline beint16_t cpu_to_be16(uint16_t native)
316 : : {
317 : 34 : return CPU_TO_BE16(native);
318 : : }
319 : :
320 : : /**
321 : : * be64_to_cpu - convert a big-endian uint64_t value
322 : : * @be_val: big-endian value to convert
323 : : */
324 : 2268 : static inline uint64_t be64_to_cpu(beint64_t be_val)
325 : : {
326 : 2268 : return BE64_TO_CPU(be_val);
327 : : }
328 : :
329 : : /**
330 : : * be32_to_cpu - convert a big-endian uint32_t value
331 : : * @be_val: big-endian value to convert
332 : : */
333 : 0 : static inline uint32_t be32_to_cpu(beint32_t be_val)
334 : : {
335 : 0 : return BE32_TO_CPU(be_val);
336 : : }
337 : :
338 : : /**
339 : : * be16_to_cpu - convert a big-endian uint16_t value
340 : : * @be_val: big-endian value to convert
341 : : */
342 : 0 : static inline uint16_t be16_to_cpu(beint16_t be_val)
343 : : {
344 : 0 : return BE16_TO_CPU(be_val);
345 : : }
346 : :
347 : : /* Whichever they include first, they get these definitions. */
348 : : #ifdef CCAN_SHORT_TYPES_H
349 : : /**
350 : : * be64/be32/be16 - 64/32/16 bit big-endian representation.
351 : : */
352 : : typedef beint64_t be64;
353 : : typedef beint32_t be32;
354 : : typedef beint16_t be16;
355 : :
356 : : /**
357 : : * le64/le32/le16 - 64/32/16 bit little-endian representation.
358 : : */
359 : : typedef leint64_t le64;
360 : : typedef leint32_t le32;
361 : : typedef leint16_t le16;
362 : : #endif
363 : : #endif /* CCAN_ENDIAN_H */
|