2 * Copyright (C) 2011 Max Kellermann <max@duempel.org>,
3 * Tobias Bieniek <Tobias.Bieniek@gmx.de>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * - Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
20 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
21 * FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
22 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
28 * OF THE POSSIBILITY OF SUCH DAMAGE.
31 #ifndef XCSOAR_BYTE_ORDER_HPP
32 #define XCSOAR_BYTE_ORDER_HPP
41 #if defined(ANDROID) || (defined(__GLIBC__) && ((__GLIBC__ >= 2 && __GLIBC_MINOR__ >= 9) || __GLIBC__ >= 3))
42 /* the byte swap macros were added in glibc 2.9 */
43 #define HAVE_BYTESWAP_H
47 #endif /* !__linux__ */
49 /* x86 always allows unaligned access */
50 #if defined(__i386__) || defined(__x86_64__) || \
51 /* ARM has it from ARMv6 on */ \
52 defined(__ARM_ARCH_6__) || \
53 defined(__ARM_ARCH_7__) || \
54 defined(__ARM_ARCH_7A__) || \
55 /* _M_ARM is the Microsoft way of checking the ARM generation \
56 (supported by mingw32ce) */ \
57 (defined(_M_ARM) && _M_ARM >= 6)
58 #ifndef FORCE_ALIGNED_READ_WRITE
59 #define CAN_READ_WRITE_UNALIGNED
64 static inline uint16_t
65 ByteSwap16(uint16_t value
)
67 #ifdef HAVE_BYTESWAP_H
68 return bswap_16(value
);
70 return (value
>> 8) | (value
<< 8);
75 static inline uint32_t
76 ByteSwap32(uint32_t value
)
78 #ifdef HAVE_BYTESWAP_H
79 return bswap_32(value
);
81 return (value
>> 24) | ((value
>> 8) & 0x0000ff00) |
82 ((value
<< 8) & 0x00ff0000) | (value
<< 24);
87 static inline uint64_t
88 ByteSwap64(uint64_t value
)
90 #ifdef HAVE_BYTESWAP_H
91 return bswap_64(value
);
93 return uint64_t(ByteSwap32(uint32_t(value
>> 32)))
94 | (uint64_t(ByteSwap32(value
)) << 32);
99 * Converts a 16bit value from big endian to the system's byte order
102 static inline uint16_t
103 FromBE16(uint16_t value
)
105 #ifdef HAVE_BYTESWAP_H
107 return betoh16(value
);
109 return be16toh(value
);
111 #elif defined(__i386__) || defined(__x86_64__) || defined(__ARMEL__)
112 /* generic little-endian */
113 return ByteSwap16(value
);
115 /* generic big-endian */
121 * Converts a 32bit value from big endian to the system's byte order
124 static inline uint32_t
125 FromBE32(uint32_t value
)
127 #ifdef HAVE_BYTESWAP_H
129 return betoh32(value
);
131 return be32toh(value
);
133 #elif defined(__i386__) || defined(__x86_64__) || defined(__ARMEL__)
134 /* generic little-endian */
135 return ByteSwap32(value
);
137 /* generic big-endian */
143 * Converts a 64bit value from big endian to the system's byte order
146 static inline uint64_t
147 FromBE64(uint64_t value
)
149 #ifdef HAVE_BYTESWAP_H
151 return betoh64(value
);
153 return be64toh(value
);
155 #elif defined(__i386__) || defined(__x86_64__) || defined(__ARMEL__)
156 /* generic little-endian */
157 return ByteSwap64(value
);
159 /* generic big-endian */
165 * Converts a 16bit value from little endian to the system's byte order
168 static inline uint16_t
169 FromLE16(uint16_t value
)
171 #ifdef HAVE_BYTESWAP_H
173 return letoh16(value
);
175 return le16toh(value
);
177 #elif defined(__i386__) || defined(__x86_64__) || defined(__ARMEL__)
178 /* generic little-endian */
181 /* generic big-endian */
182 return ByteSwap16(value
);
187 * Converts a 32bit value from little endian to the system's byte order
190 static inline uint32_t
191 FromLE32(uint32_t value
)
193 #ifdef HAVE_BYTESWAP_H
195 return letoh32(value
);
197 return le32toh(value
);
199 #elif defined(__i386__) || defined(__x86_64__) || defined(__ARMEL__)
200 /* generic little-endian */
203 /* generic big-endian */
204 return ByteSwap32(value
);
209 * Converts a 64bit value from little endian to the system's byte order
212 static inline uint64_t
213 FromLE64(uint64_t value
)
215 #ifdef HAVE_BYTESWAP_H
217 return letoh64(value
);
219 return le64toh(value
);
221 #elif defined(__i386__) || defined(__x86_64__) || defined(__ARMEL__)
222 /* generic little-endian */
225 /* generic big-endian */
226 return ByteSwap64(value
);
231 * Converts a 16bit value from the system's byte order to big endian
234 static inline uint16_t
235 ToBE16(uint16_t value
)
237 #ifdef HAVE_BYTESWAP_H
238 return htobe16(value
);
239 #elif defined(__i386__) || defined(__x86_64__) || defined(__ARMEL__)
240 /* generic little-endian */
241 return ByteSwap16(value
);
243 /* generic big-endian */
249 * Converts a 32bit value from the system's byte order to big endian
252 static inline uint32_t
253 ToBE32(uint32_t value
)
255 #ifdef HAVE_BYTESWAP_H
256 return htobe32(value
);
257 #elif defined(__i386__) || defined(__x86_64__) || defined(__ARMEL__)
258 /* generic little-endian */
259 return ByteSwap32(value
);
261 /* generic big-endian */
267 * Converts a 64bit value from the system's byte order to big endian
270 static inline uint64_t
271 ToBE64(uint64_t value
)
273 #ifdef HAVE_BYTESWAP_H
274 return htobe64(value
);
275 #elif defined(__i386__) || defined(__x86_64__) || defined(__ARMEL__)
276 /* generic little-endian */
277 return ByteSwap64(value
);
279 /* generic big-endian */
285 * Converts a 16bit value from the system's byte order to little endian
288 static inline uint16_t
289 ToLE16(uint16_t value
)
291 #ifdef HAVE_BYTESWAP_H
292 return htole16(value
);
293 #elif defined(__i386__) || defined(__x86_64__) || defined(__ARMEL__)
294 /* generic little-endian */
297 /* generic big-endian */
298 return ByteSwap16(value
);
303 * Converts a 32bit value from the system's byte order to little endian
306 static inline uint32_t
307 ToLE32(uint32_t value
)
309 #ifdef HAVE_BYTESWAP_H
310 return htole32(value
);
311 #elif defined(__i386__) || defined(__x86_64__) || defined(__ARMEL__)
312 /* generic little-endian */
315 /* generic big-endian */
316 return ByteSwap32(value
);
321 * Converts a 64bit value from the system's byte order to little endian
324 static inline uint64_t
325 ToLE64(uint64_t value
)
327 #ifdef HAVE_BYTESWAP_H
328 return htole64(value
);
329 #elif defined(__i386__) || defined(__x86_64__) || defined(__ARMEL__)
330 /* generic little-endian */
333 /* generic big-endian */
334 return ByteSwap64(value
);
339 static inline uint16_t
340 ReadUnalignedLE16(const uint16_t *p
)
342 #ifdef CAN_READ_WRITE_UNALIGNED
345 const uint8_t *c
= (const uint8_t *)p
;
346 return c
[0] | (c
[1] << 8);
351 static inline uint16_t
352 ReadUnalignedBE16(const uint16_t *p
)
354 #ifdef CAN_READ_WRITE_UNALIGNED
357 const uint8_t *c
= (const uint8_t *)p
;
358 return c
[1] | (c
[0] << 8);
363 WriteUnalignedLE16(uint16_t *p
, uint16_t value
)
365 #ifdef CAN_READ_WRITE_UNALIGNED
368 uint8_t *c
= (uint8_t *)p
;
375 WriteUnalignedBE16(uint16_t *p
, uint16_t value
)
377 #ifdef CAN_READ_WRITE_UNALIGNED
380 uint8_t *c
= (uint8_t *)p
;
387 static inline uint32_t
388 ReadUnalignedLE32(const uint32_t *p
)
390 #ifdef CAN_READ_WRITE_UNALIGNED
393 const uint8_t *c
= (const uint8_t *)p
;
394 return c
[0] | (c
[1] << 8) | (c
[2] << 16) | (c
[3] << 24);
399 static inline uint32_t
400 ReadUnalignedBE32(const uint32_t *p
)
402 #ifdef CAN_READ_WRITE_UNALIGNED
405 const uint8_t *c
= (const uint8_t *)p
;
406 return c
[3] | (c
[2] << 8) | (c
[1] << 16) | (c
[0] << 24);