1 // "License": Public Domain
2 // I, Mathias Panzenböck, place this file hereby into the public domain. Use it at your own risk for whatever you like.
3 // In case there are jurisdictions that don't support putting things in the public domain you can also consider it to
4 // be "dual licensed" under the BSD, MIT and Apache licenses, if you want to. This code is trivial anyway. Consider it
5 // an example on how to get the endian conversion functions on different platforms.
6 
7 #ifndef PORTABLE_ENDIAN_H__
8 #define PORTABLE_ENDIAN_H__
9 
10 #if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__)
11 
12 #   define __WINDOWS__
13 
14 #endif
15 
16 #if defined(__linux__) || defined(__CYGWIN__)
17 /* Define necessary macros for the header to expose all fields. */
18 #   if !defined(_BSD_SOURCE)
19 #       define _BSD_SOURCE
20 #   endif
21 #   if !defined(__USE_BSD)
22 #       define __USE_BSD
23 #   endif
24 #   if !defined(_DEFAULT_SOURCE)
25 #       define _DEFAULT_SOURCE
26 #   endif
27 #   include <endian.h>
28 #   include <features.h>
29 /* See http://linux.die.net/man/3/endian */
30 #   if defined(htobe16) && defined(htole16) && defined(be16toh) && defined(le16toh) && defined(htobe32) && defined(htole32) && defined(be32toh) && defined(htole32) && defined(htobe64) && defined(htole64) && defined(be64) && defined(le64)
31 /* Do nothing. The macros we need already exist. */
32 #   elif !defined(__GLIBC__) || !defined(__GLIBC_MINOR__) || ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 9)))
33 #       include <arpa/inet.h>
34 #       if defined(__BYTE_ORDER) && (__BYTE_ORDER == __LITTLE_ENDIAN)
35 #           define htobe16(x) htons(x)
36 #           define htole16(x) (x)
37 #           define be16toh(x) ntohs(x)
38 #           define le16toh(x) (x)
39 
40 #           define htobe32(x) htonl(x)
41 #           define htole32(x) (x)
42 #           define be32toh(x) ntohl(x)
43 #           define le32toh(x) (x)
44 
45 #           define htobe64(x) (((uint64_t)htonl(((uint32_t)(((uint64_t)(x)) >> 32)))) | (((uint64_t)htonl(((uint32_t)(x)))) << 32))
46 #           define htole64(x) (x)
47 #           define be64toh(x) (((uint64_t)ntohl(((uint32_t)(((uint64_t)(x)) >> 32)))) | (((uint64_t)ntohl(((uint32_t)(x)))) << 32))
48 #           define le64toh(x) (x)
49 #       elif defined(__BYTE_ORDER) && (__BYTE_ORDER == __BIG_ENDIAN)
50 #           define htobe16(x) (x)
51 #           define htole16(x) (((((uint16_t)(x)) >> 8))|((((uint16_t)(x)) << 8)))
52 #           define be16toh(x) (x)
53 #           define le16toh(x) (((((uint16_t)(x)) >> 8))|((((uint16_t)(x)) << 8)))
54 
55 #           define htobe32(x) (x)
56 #           define htole32(x) (((uint32_t)htole16(((uint16_t)(((uint32_t)(x)) >> 16)))) | (((uint32_t)htole16(((uint16_t)(x)))) << 16))
57 #           define be32toh(x) (x)
58 #           define le32toh(x) (((uint32_t)le16toh(((uint16_t)(((uint32_t)(x)) >> 16)))) | (((uint32_t)le16toh(((uint16_t)(x)))) << 16))
59 
60 #           define htobe64(x) (x)
61 #           define htole64(x) (((uint64_t)htole32(((uint32_t)(((uint64_t)(x)) >> 32)))) | (((uint64_t)htole32(((uint32_t)(x)))) << 32))
62 #           define be64toh(x) (x)
63 #           define le64toh(x) (((uint64_t)le32toh(((uint32_t)(((uint64_t)(x)) >> 32)))) | (((uint64_t)le32toh(((uint32_t)(x)))) << 32))
64 #       else
65 #           error Byte Order not supported or not defined.
66 #       endif
67 #   endif
68 
69 #elif defined(__APPLE__)
70 
71 #   include <libkern/OSByteOrder.h>
72 
73 #   define htobe16(x) OSSwapHostToBigInt16(x)
74 #   define htole16(x) OSSwapHostToLittleInt16(x)
75 #   define be16toh(x) OSSwapBigToHostInt16(x)
76 #   define le16toh(x) OSSwapLittleToHostInt16(x)
77 
78 #   define htobe32(x) OSSwapHostToBigInt32(x)
79 #   define htole32(x) OSSwapHostToLittleInt32(x)
80 #   define be32toh(x) OSSwapBigToHostInt32(x)
81 #   define le32toh(x) OSSwapLittleToHostInt32(x)
82 
83 #   define htobe64(x) OSSwapHostToBigInt64(x)
84 #   define htole64(x) OSSwapHostToLittleInt64(x)
85 #   define be64toh(x) OSSwapBigToHostInt64(x)
86 #   define le64toh(x) OSSwapLittleToHostInt64(x)
87 
88 #   define __BYTE_ORDER    BYTE_ORDER
89 #   define __BIG_ENDIAN    BIG_ENDIAN
90 #   define __LITTLE_ENDIAN LITTLE_ENDIAN
91 #   define __PDP_ENDIAN    PDP_ENDIAN
92 
93 #elif defined(__OpenBSD__)
94 
95 #   include <sys/endian.h>
96 
97 #elif defined(__HAIKU__)
98 
99 #   include <endian.h>
100 
101 #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__)
102 
103 #   include <sys/endian.h>
104 
105 #   if !defined(be16toh)
106     #   define be16toh(x) betoh16(x)
107     #   define le16toh(x) letoh16(x)
108 #   endif
109 
110 #   if !defined(be32toh)
111     #   define be32toh(x) betoh32(x)
112     #   define le32toh(x) letoh32(x)
113 #   endif
114 
115 #   if !defined(be64toh)
116     #   define be64toh(x) betoh64(x)
117     #   define le64toh(x) letoh64(x)
118 #   endif
119 
120 #elif defined(__WINDOWS__)
121 
122 #   if BYTE_ORDER == LITTLE_ENDIAN
123 
124 #       define htobe16(x) _byteswap_ushort(x)
125 #       define htole16(x) (x)
126 #       define be16toh(x) _byteswap_ushort(x)
127 #       define le16toh(x) (x)
128 
129 #       define htobe32(x) _byteswap_ulong(x)
130 #       define htole32(x) (x)
131 #       define be32toh(x) _byteswap_ulong(x)
132 #       define le32toh(x) (x)
133 
134 #       define htobe64(x) _byteswap_uint64(x)
135 #       define be64toh(x) _byteswap_uint64(x)
136 #       define htole64(x) (x)
137 #       define le64toh(x) (x)
138 
139 #   elif BYTE_ORDER == BIG_ENDIAN
140 
141         /* that would be xbox 360 */
142 #       define htobe16(x) (x)
143 #       define htole16(x) __builtin_bswap16(x)
144 #       define be16toh(x) (x)
145 #       define le16toh(x) __builtin_bswap16(x)
146 
147 #       define htobe32(x) (x)
148 #       define htole32(x) __builtin_bswap32(x)
149 #       define be32toh(x) (x)
150 #       define le32toh(x) __builtin_bswap32(x)
151 
152 #       define htobe64(x) (x)
153 #       define htole64(x) __builtin_bswap64(x)
154 #       define be64toh(x) (x)
155 #       define le64toh(x) __builtin_bswap64(x)
156 
157 #   else
158 
159 #       error byte order not supported
160 
161 #   endif
162 
163 #   define __BYTE_ORDER    BYTE_ORDER
164 #   define __BIG_ENDIAN    BIG_ENDIAN
165 #   define __LITTLE_ENDIAN LITTLE_ENDIAN
166 #   define __PDP_ENDIAN    PDP_ENDIAN
167 
168 #elif defined(__sun)
169 
170 #   include <sys/byteorder.h>
171 
172 #   define htobe16(x) BE_16(x)
173 #   define htole16(x) LE_16(x)
174 #   define be16toh(x) BE_16(x)
175 #   define le16toh(x) LE_16(x)
176 
177 #   define htobe32(x) BE_32(x)
178 #   define htole32(x) LE_32(x)
179 #   define be32toh(x) BE_32(x)
180 #   define le32toh(x) LE_32(x)
181 
182 #   define htobe64(x) BE_64(x)
183 #   define htole64(x) LE_64(x)
184 #   define be64toh(x) BE_64(x)
185 #   define le64toh(x) LE_64(x)
186 
187 #elif defined _AIX      /* AIX is always big endian */
188 #       define be64toh(x) (x)
189 #       define be32toh(x) (x)
190 #       define be16toh(x) (x)
191 #       define le32toh(x)                              \
192          ((((x) & 0xff) << 24) |                 \
193            (((x) & 0xff00) << 8) |                \
194            (((x) & 0xff0000) >> 8) |              \
195            (((x) & 0xff000000) >> 24))
196 #       define   le64toh(x)                               \
197          ((((x) & 0x00000000000000ffL) << 56) |   \
198           (((x) & 0x000000000000ff00L) << 40) |   \
199           (((x) & 0x0000000000ff0000L) << 24) |   \
200           (((x) & 0x00000000ff000000L) << 8)  |   \
201           (((x) & 0x000000ff00000000L) >> 8)  |   \
202           (((x) & 0x0000ff0000000000L) >> 24) |   \
203           (((x) & 0x00ff000000000000L) >> 40) |   \
204           (((x) & 0xff00000000000000L) >> 56))
205 #       ifndef htobe64
206 #               define htobe64(x) be64toh(x)
207 #       endif
208 #       ifndef htobe32
209 #               define htobe32(x) be32toh(x)
210 #       endif
211 #       ifndef htobe16
212 #               define htobe16(x) be16toh(x)
213 #       endif
214 
215 
216 #else
217 
218 #   error platform not supported
219 
220 #endif
221 
222 #endif
223