set base sdk to 10.9
[wdl/wdl-ol.git] / WDL / wdlendian.h
blobb6a3770cbc4903074ae23bca153ff962f6a53156
1 /*
2 WDL - wdlendian.h
3 (c) Theo Niessink 2011
4 <http://www.taletn.com/>
6 This software is provided 'as-is', without any express or implied
7 warranty. In no event will the authors be held liable for any damages
8 arising from the use of this software.
10 Permission is granted to anyone to use this software for any purpose,
11 including commercial applications, and to alter it and redistribute it
12 freely, subject to the following restrictions:
14 1. The origin of this software must not be misrepresented; you must not
15 claim that you wrote the original software. If you use this software
16 in a product, an acknowledgment in the product documentation would be
17 appreciated but is not required.
18 2. Altered source versions must be plainly marked as such, and must not be
19 misrepresented as being the original software.
20 3. This notice may not be removed or altered from any source distribution.
23 This file provides macros and functions for converting integer and
24 floating point data types from native (host) endian to little or big
25 endian format, and vice versa.
30 #ifndef _WDL_ENDIAN_H_
31 #define _WDL_ENDIAN_H_
34 #include "wdltypes.h"
36 typedef union { float f; unsigned int int32; } WDL_EndianFloat;
37 typedef union { double f; WDL_UINT64 int64; } WDL_EndianDouble;
39 #ifdef __cplusplus
40 #define WDL_ENDIAN_INLINE inline
41 #elif defined(_MSC_VER)
42 #define WDL_ENDIAN_INLINE __inline
43 #else
44 #define WDL_ENDIAN_INLINE
45 #endif
48 // Windows
49 #ifdef _WIN32
50 #define WDL_LITTLE_ENDIAN
52 // Mac OS X
53 #elif defined(__APPLE__)
54 #if __LITTLE_ENDIAN__ // Intel
55 #define WDL_LITTLE_ENDIAN
56 #elif __BIG_ENDIAN__ // PowerPC
57 #define WDL_BIG_ENDIAN
58 #else
59 #error Unknown endian
60 #endif
62 // GNU C (v4.6 or later?)
63 #elif __GNUC__ && defined(__BYTE_ORDER__)
64 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
65 #define WDL_LITTLE_ENDIAN
66 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
67 #define WDL_BIG_ENDIAN
68 #else
69 #error Unsupported endian
70 #endif
71 #if __FLOAT_WORD_ORDER__ != __BYTE_ORDER__
72 #error Unsupported float endian
73 #endif
75 // GNU C, Intel C++
76 #elif defined(__i386) || defined(__i386__) || defined(i386)
77 #define WDL_LITTLE_ENDIAN
79 // Intel C++
80 #elif defined(__x86_64) || defined(__x86_64__)
81 #define WDL_LITTLE_ENDIAN
83 #else
84 #error Unknown endian
85 #endif
88 // Microsoft C
89 #ifdef _MSC_VER
90 #include <intrin.h>
91 #define WDL_bswap16(x) _byteswap_ushort(x)
92 #define WDL_bswap32(x) _byteswap_ulong(x)
93 #define WDL_bswap64(x) _byteswap_uint64(x)
95 #elif defined(__APPLE__)
96 #include "TargetConditionals.h"
97 #if defined(TARGET_OS_IPHONE) | defined(TARGET_IPHONE_SIMULATOR)
98 #include <libkern/OSByteOrder.h>
100 // iOS
101 #define WDL_bswap16(x) OSSwapInt16(x)
102 #define WDL_bswap32(x) OSSwapInt32(x)
103 #define WDL_bswap64(x) OSSwapInt64(x)
105 // Mac OS X (v10.0 and later)
106 #elif defined(TARGET_OS_MAC)
107 #include <CoreServices/CoreServices.h>
109 #define WDL_bswap16(x) Endian16_Swap(x)
110 #define WDL_bswap32(x) Endian32_Swap(x)
111 #define WDL_bswap64(x) Endian64_Swap(x) // (Thread-safe on) v10.3 and later (?)
112 #endif
115 // GNU C
116 #elif __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)
117 #define WDL_bswap32(x) __builtin_bswap32(x)
118 #define WDL_bswap64(x) __builtin_bswap64(x)
120 // Linux
121 #elif defined(__linux) || defined(__linux__) || defined(linux)
122 #include <endian.h>
123 #define WDL_bswap16(x) bswap16(x)
124 #define WDL_bswap32(x) bswap32(x)
125 #define WDL_bswap64(x) bswap64(x)
127 #endif // WDL_bswapXX
129 // If none of the supported intrinsics were found, then revert to generic C
130 // byte swap functions.
131 #ifndef WDL_bswap16
132 static WDL_ENDIAN_INLINE unsigned short WDL_bswap16(const unsigned short int16)
134 return int16 >> 8 |
135 int16 << 8;
137 #endif
139 #ifndef WDL_bswap32
140 static WDL_ENDIAN_INLINE unsigned int WDL_bswap32(const unsigned int int32)
142 return int32 >> 24 |
143 int32 >> 8 & 0x0000FF00 |
144 int32 << 8 & 0x00FF0000 |
145 int32 << 24;
147 #endif
149 #ifndef WDL_bswap64
150 static WDL_ENDIAN_INLINE WDL_UINT64 WDL_bswap64(const WDL_UINT64 int64)
152 return int64 >> 56 |
153 int64 >> 40 & 0x000000000000FF00ULL |
154 int64 >> 24 & 0x0000000000FF0000ULL |
155 int64 >> 8 & 0x00000000FF000000ULL |
156 int64 << 8 & 0x000000FF00000000ULL |
157 int64 << 24 & 0x0000FF0000000000ULL |
158 int64 << 40 & 0x00FF000000000000ULL |
159 int64 << 56;
161 #endif
164 // Int types
166 #if defined(WDL_LITTLE_ENDIAN)
168 #define WDL_bswap16_if_le(x) WDL_bswap16(x)
169 #define WDL_bswap32_if_le(x) WDL_bswap32(x)
170 #define WDL_bswap64_if_le(x) WDL_bswap64(x)
171 #define WDL_bswap16_if_be(x) ((unsigned short)(x))
172 #define WDL_bswap32_if_be(x) ((unsigned int)(x))
173 #define WDL_bswap64_if_be(x) ((WDL_UINT64)(x))
175 // Wrappers that convert a variable in-place, or generate no code if
176 // conversion is not necessary. Beware to only feed variables to these
177 // macros, so no fancy things like WDL_BSWAP32_IF_LE(x + y) or
178 // WDL_BSWAP32_IF_LE(x++). Note that these macros only change the type
179 // to unsigned if conversion is actually necessary.
180 #define WDL_BSWAP16_IF_LE(x) (x = WDL_bswap16(x))
181 #define WDL_BSWAP32_IF_LE(x) (x = WDL_bswap32(x))
182 #define WDL_BSWAP64_IF_LE(x) (x = WDL_bswap64(x))
183 #define WDL_BSWAP16_IF_BE(x) ((void)0)
184 #define WDL_BSWAP32_IF_BE(x) ((void)0)
185 #define WDL_BSWAP64_IF_BE(x) ((void)0)
187 #else // #elif defined(WDL_BIG_ENDIAN)
189 #define WDL_bswap16_if_be(x) WDL_bswap16(x)
190 #define WDL_bswap32_if_be(x) WDL_bswap32(x)
191 #define WDL_bswap64_if_be(x) WDL_bswap64(x)
192 #define WDL_bswap16_if_le(x) ((unsigned short)(x))
193 #define WDL_bswap32_if_le(x) ((unsigned int)(x))
194 #define WDL_bswap64_if_le(x) ((WDL_UINT64)(x))
196 // In-place wrappers (see notes above)
197 #define WDL_BSWAP16_IF_BE(x) (x = WDL_bswap16(x))
198 #define WDL_BSWAP32_IF_BE(x) (x = WDL_bswap32(x))
199 #define WDL_BSWAP64_IF_BE(x) (x = WDL_bswap64(x))
200 #define WDL_BSWAP16_IF_LE(x) ((void)0)
201 #define WDL_BSWAP32_IF_LE(x) ((void)0)
202 #define WDL_BSWAP64_IF_LE(x) ((void)0)
204 #endif // WDL_bswapXX_if_YY
207 // C++ auto-typed wrappers
209 #ifdef __cplusplus
211 static WDL_ENDIAN_INLINE unsigned short WDL_bswap_if_le(unsigned short int16) { return WDL_bswap16_if_le(int16); }
212 static WDL_ENDIAN_INLINE signed short WDL_bswap_if_le(signed short int16) { return WDL_bswap16_if_le(int16); }
213 static WDL_ENDIAN_INLINE unsigned int WDL_bswap_if_le(unsigned int int32) { return WDL_bswap32_if_le(int32); }
214 static WDL_ENDIAN_INLINE signed int WDL_bswap_if_le(signed int int32) { return WDL_bswap32_if_le(int32); }
215 static WDL_ENDIAN_INLINE WDL_UINT64 WDL_bswap_if_le(WDL_UINT64 int64) { return WDL_bswap64_if_le(int64); }
216 static WDL_ENDIAN_INLINE WDL_INT64 WDL_bswap_if_le(WDL_INT64 int64) { return WDL_bswap64_if_le(int64); }
218 static WDL_ENDIAN_INLINE unsigned short WDL_bswap_if_be(unsigned short int16) { return WDL_bswap16_if_be(int16); }
219 static WDL_ENDIAN_INLINE signed short WDL_bswap_if_be(signed short int16) { return WDL_bswap16_if_be(int16); }
220 static WDL_ENDIAN_INLINE unsigned int WDL_bswap_if_be(unsigned int int32) { return WDL_bswap32_if_be(int32); }
221 static WDL_ENDIAN_INLINE signed int WDL_bswap_if_be(signed int int32) { return WDL_bswap32_if_be(int32); }
222 static WDL_ENDIAN_INLINE WDL_UINT64 WDL_bswap_if_be(WDL_UINT64 int64) { return WDL_bswap64_if_be(int64); }
223 static WDL_ENDIAN_INLINE WDL_INT64 WDL_bswap_if_be(WDL_INT64 int64) { return WDL_bswap64_if_be(int64); }
225 // Auto-typed in-place wrappers (see notes above)
226 #ifdef WDL_LITTLE_ENDIAN
227 #define WDL_BSWAP_IF_LE(x) (x = WDL_bswap_if_le(x))
228 #define WDL_BSWAP_IF_BE(x) ((void)0)
229 #else // #elif defined(WDL_BIG_ENDIAN)
230 #define WDL_BSWAP_IF_BE(x) (x = WDL_bswap_if_be(x))
231 #define WDL_BSWAP_IF_LE(x) ((void)0)
232 #endif
235 // Map floating point types to int types.
237 #if defined(WDL_LITTLE_ENDIAN)
238 #define __WDL_bswapf_if_a WDL_bswapf_if_le
239 #define __WDL_bswapf_if_b WDL_bswapf_if_be
240 #else // #elif defined(WDL_BIG_ENDIAN)
241 #define __WDL_bswapf_if_a WDL_bswapf_if_be
242 #define __WDL_bswapf_if_b WDL_bswapf_if_le
243 #endif
245 static WDL_ENDIAN_INLINE unsigned int __WDL_bswapf_if_a(const float f) { return WDL_bswap32(*(const unsigned int*)&f); }
246 static WDL_ENDIAN_INLINE WDL_UINT64 __WDL_bswapf_if_a(const double f) { return WDL_bswap64(*(const WDL_UINT64 *)&f); }
248 static WDL_ENDIAN_INLINE float __WDL_bswapf_if_a(const unsigned int int32)
250 const unsigned int i = WDL_bswap32(int32);
251 return *(const float*)&i;
254 static WDL_ENDIAN_INLINE double __WDL_bswapf_if_a(const WDL_UINT64 int64)
256 const WDL_UINT64 i = WDL_bswap64(int64);
257 return *(const double*)&i;
260 static WDL_ENDIAN_INLINE unsigned int __WDL_bswapf_if_b(const float f) { return *(const unsigned int*)&f; }
261 static WDL_ENDIAN_INLINE WDL_UINT64 __WDL_bswapf_if_b(const double f) { return *(const WDL_UINT64 *)&f; }
262 static WDL_ENDIAN_INLINE float __WDL_bswapf_if_b(const unsigned int int32) { return *(const float *)&int32; }
263 static WDL_ENDIAN_INLINE double __WDL_bswapf_if_b(const WDL_UINT64 int64) { return *(const double *)&int64; }
265 #undef __WDL_bswapf_if_a
266 #undef __WDL_bswapf_if_b
268 #endif // __cplusplus
271 #endif // _WDL_ENDIAN_H_