1 | /* |
2 | Simple DirectMedia Layer |
3 | Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org> |
4 | |
5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the authors be held liable for any damages |
7 | arising from the use of this software. |
8 | |
9 | Permission is granted to anyone to use this software for any purpose, |
10 | including commercial applications, and to alter it and redistribute it |
11 | freely, subject to the following restrictions: |
12 | |
13 | 1. The origin of this software must not be misrepresented; you must not |
14 | claim that you wrote the original software. If you use this software |
15 | in a product, an acknowledgment in the product documentation would be |
16 | appreciated but is not required. |
17 | 2. Altered source versions must be plainly marked as such, and must not be |
18 | misrepresented as being the original software. |
19 | 3. This notice may not be removed or altered from any source distribution. |
20 | */ |
21 | |
22 | /** |
23 | * # CategoryEndian |
24 | * |
25 | * Functions converting endian-specific values to different byte orders. |
26 | * |
27 | * These functions either unconditionally swap byte order (SDL_Swap16, |
28 | * SDL_Swap32, SDL_Swap64, SDL_SwapFloat), or they swap to/from the system's |
29 | * native byte order (SDL_Swap16LE, SDL_Swap16BE, SDL_Swap32LE, SDL_Swap32BE, |
30 | * SDL_Swap32LE, SDL_Swap32BE, SDL_SwapFloatLE, SDL_SwapFloatBE). In the |
31 | * latter case, the functionality is provided by macros that become no-ops if |
32 | * a swap isn't necessary: on an x86 (littleendian) processor, SDL_Swap32LE |
33 | * does nothing, but SDL_Swap32BE reverses the bytes of the data. On a PowerPC |
34 | * processor (bigendian), the macros behavior is reversed. |
35 | * |
36 | * The swap routines are inline functions, and attempt to use compiler |
37 | * intrinsics, inline assembly, and other magic to make byteswapping |
38 | * efficient. |
39 | */ |
40 | |
41 | #ifndef SDL_endian_h_ |
42 | #define SDL_endian_h_ |
43 | |
44 | #include <SDL3/SDL_stdinc.h> |
45 | |
46 | #if defined(_MSC_VER) && (_MSC_VER >= 1400) |
47 | /* As of Clang 11, '_m_prefetchw' is conflicting with the winnt.h's version, |
48 | so we define the needed '_m_prefetch' here as a pseudo-header, until the issue is fixed. */ |
49 | #ifdef __clang__ |
50 | #ifndef __PRFCHWINTRIN_H |
51 | #define __PRFCHWINTRIN_H |
52 | static __inline__ void __attribute__((__always_inline__, __nodebug__)) |
53 | _m_prefetch(void *__P) |
54 | { |
55 | __builtin_prefetch(__P, 0, 3 /* _MM_HINT_T0 */); |
56 | } |
57 | #endif /* __PRFCHWINTRIN_H */ |
58 | #endif /* __clang__ */ |
59 | |
60 | #include <intrin.h> |
61 | #endif |
62 | |
63 | /** |
64 | * \name The two types of endianness |
65 | */ |
66 | /* @{ */ |
67 | |
68 | |
69 | /** |
70 | * A value to represent littleendian byteorder. |
71 | * |
72 | * This is used with the preprocessor macro SDL_BYTEORDER, to determine a |
73 | * platform's byte ordering: |
74 | * |
75 | * ```c |
76 | * #if SDL_BYTEORDER == SDL_LIL_ENDIAN |
77 | * SDL_Log("This system is littleendian."); |
78 | * #endif |
79 | * ``` |
80 | * |
81 | * \since This macro is available since SDL 3.2.0. |
82 | * |
83 | * \sa SDL_BYTEORDER |
84 | * \sa SDL_BIG_ENDIAN |
85 | */ |
86 | #define SDL_LIL_ENDIAN 1234 |
87 | |
88 | /** |
89 | * A value to represent bigendian byteorder. |
90 | * |
91 | * This is used with the preprocessor macro SDL_BYTEORDER, to determine a |
92 | * platform's byte ordering: |
93 | * |
94 | * ```c |
95 | * #if SDL_BYTEORDER == SDL_BIG_ENDIAN |
96 | * SDL_Log("This system is bigendian."); |
97 | * #endif |
98 | * ``` |
99 | * |
100 | * \since This macro is available since SDL 3.2.0. |
101 | * |
102 | * \sa SDL_BYTEORDER |
103 | * \sa SDL_LIL_ENDIAN |
104 | */ |
105 | #define SDL_BIG_ENDIAN 4321 |
106 | |
107 | /* @} */ |
108 | |
109 | #ifndef SDL_BYTEORDER |
110 | #ifdef SDL_WIKI_DOCUMENTATION_SECTION |
111 | |
112 | /** |
113 | * A macro that reports the target system's byte order. |
114 | * |
115 | * This is set to either SDL_LIL_ENDIAN or SDL_BIG_ENDIAN (and maybe other |
116 | * values in the future, if something else becomes popular). This can be |
117 | * tested with the preprocessor, so decisions can be made at compile time. |
118 | * |
119 | * ```c |
120 | * #if SDL_BYTEORDER == SDL_BIG_ENDIAN |
121 | * SDL_Log("This system is bigendian."); |
122 | * #endif |
123 | * ``` |
124 | * |
125 | * \since This macro is available since SDL 3.2.0. |
126 | * |
127 | * \sa SDL_LIL_ENDIAN |
128 | * \sa SDL_BIG_ENDIAN |
129 | */ |
130 | #define SDL_BYTEORDER SDL_LIL_ENDIAN___or_maybe___SDL_BIG_ENDIAN |
131 | #elif defined(SDL_PLATFORM_LINUX) |
132 | #include <endian.h> |
133 | #define SDL_BYTEORDER __BYTE_ORDER |
134 | #elif defined(SDL_PLATFORM_SOLARIS) |
135 | #include <sys/byteorder.h> |
136 | #if defined(_LITTLE_ENDIAN) |
137 | #define SDL_BYTEORDER SDL_LIL_ENDIAN |
138 | #elif defined(_BIG_ENDIAN) |
139 | #define SDL_BYTEORDER SDL_BIG_ENDIAN |
140 | #else |
141 | #error Unsupported endianness |
142 | #endif |
143 | #elif defined(SDL_PLATFORM_OPENBSD) || defined(__DragonFly__) |
144 | #include <endian.h> |
145 | #define SDL_BYTEORDER BYTE_ORDER |
146 | #elif defined(SDL_PLATFORM_FREEBSD) || defined(SDL_PLATFORM_NETBSD) |
147 | #include <sys/endian.h> |
148 | #define SDL_BYTEORDER BYTE_ORDER |
149 | /* predefs from newer gcc and clang versions: */ |
150 | #elif defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) && defined(__BYTE_ORDER__) |
151 | #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) |
152 | #define SDL_BYTEORDER SDL_LIL_ENDIAN |
153 | #elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) |
154 | #define SDL_BYTEORDER SDL_BIG_ENDIAN |
155 | #else |
156 | #error Unsupported endianness |
157 | #endif /**/ |
158 | #else |
159 | #if defined(__hppa__) || \ |
160 | defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \ |
161 | (defined(__MIPS__) && defined(__MIPSEB__)) || \ |
162 | defined(__ppc__) || defined(__POWERPC__) || defined(__powerpc__) || defined(__PPC__) || \ |
163 | defined(__sparc__) || defined(__sparc) |
164 | #define SDL_BYTEORDER SDL_BIG_ENDIAN |
165 | #else |
166 | #define SDL_BYTEORDER SDL_LIL_ENDIAN |
167 | #endif |
168 | #endif /* SDL_PLATFORM_LINUX */ |
169 | #endif /* !SDL_BYTEORDER */ |
170 | |
171 | #ifndef SDL_FLOATWORDORDER |
172 | #ifdef SDL_WIKI_DOCUMENTATION_SECTION |
173 | |
174 | /** |
175 | * A macro that reports the target system's floating point word order. |
176 | * |
177 | * This is set to either SDL_LIL_ENDIAN or SDL_BIG_ENDIAN (and maybe other |
178 | * values in the future, if something else becomes popular). This can be |
179 | * tested with the preprocessor, so decisions can be made at compile time. |
180 | * |
181 | * ```c |
182 | * #if SDL_FLOATWORDORDER == SDL_BIG_ENDIAN |
183 | * SDL_Log("This system's floats are bigendian."); |
184 | * #endif |
185 | * ``` |
186 | * |
187 | * \since This macro is available since SDL 3.2.0. |
188 | * |
189 | * \sa SDL_LIL_ENDIAN |
190 | * \sa SDL_BIG_ENDIAN |
191 | */ |
192 | #define SDL_FLOATWORDORDER SDL_LIL_ENDIAN___or_maybe___SDL_BIG_ENDIAN |
193 | /* predefs from newer gcc versions: */ |
194 | #elif defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) && defined(__FLOAT_WORD_ORDER__) |
195 | #if (__FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__) |
196 | #define SDL_FLOATWORDORDER SDL_LIL_ENDIAN |
197 | #elif (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__) |
198 | #define SDL_FLOATWORDORDER SDL_BIG_ENDIAN |
199 | #else |
200 | #error Unsupported endianness |
201 | #endif /**/ |
202 | #elif defined(__MAVERICK__) |
203 | /* For Maverick, float words are always little-endian. */ |
204 | #define SDL_FLOATWORDORDER SDL_LIL_ENDIAN |
205 | #elif (defined(__arm__) || defined(__thumb__)) && !defined(__VFP_FP__) && !defined(__ARM_EABI__) |
206 | /* For FPA, float words are always big-endian. */ |
207 | #define SDL_FLOATWORDORDER SDL_BIG_ENDIAN |
208 | #else |
209 | /* By default, assume that floats words follow the memory system mode. */ |
210 | #define SDL_FLOATWORDORDER SDL_BYTEORDER |
211 | #endif /* __FLOAT_WORD_ORDER__ */ |
212 | #endif /* !SDL_FLOATWORDORDER */ |
213 | |
214 | |
215 | #include <SDL3/SDL_begin_code.h> |
216 | /* Set up for C function definitions, even when using C++ */ |
217 | #ifdef __cplusplus |
218 | extern "C" { |
219 | #endif |
220 | |
221 | /* various modern compilers may have builtin swap */ |
222 | #if defined(__GNUC__) || defined(__clang__) |
223 | # define HAS_BUILTIN_BSWAP16 (SDL_HAS_BUILTIN(__builtin_bswap16)) || \ |
224 | (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8)) |
225 | # define HAS_BUILTIN_BSWAP32 (SDL_HAS_BUILTIN(__builtin_bswap32)) || \ |
226 | (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) |
227 | # define HAS_BUILTIN_BSWAP64 (SDL_HAS_BUILTIN(__builtin_bswap64)) || \ |
228 | (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) |
229 | |
230 | /* this one is broken */ |
231 | # define HAS_BROKEN_BSWAP (__GNUC__ == 2 && __GNUC_MINOR__ <= 95) |
232 | #else |
233 | # define HAS_BUILTIN_BSWAP16 0 |
234 | # define HAS_BUILTIN_BSWAP32 0 |
235 | # define HAS_BUILTIN_BSWAP64 0 |
236 | # define HAS_BROKEN_BSWAP 0 |
237 | #endif |
238 | |
239 | /* Byte swap 16-bit integer. */ |
240 | #ifndef SDL_WIKI_DOCUMENTATION_SECTION |
241 | #if HAS_BUILTIN_BSWAP16 |
242 | #define SDL_Swap16(x) __builtin_bswap16(x) |
243 | #elif (defined(_MSC_VER) && (_MSC_VER >= 1400)) && !defined(__ICL) |
244 | #pragma intrinsic(_byteswap_ushort) |
245 | #define SDL_Swap16(x) _byteswap_ushort(x) |
246 | #elif defined(__i386__) && !HAS_BROKEN_BSWAP |
247 | SDL_FORCE_INLINE Uint16 SDL_Swap16(Uint16 x) |
248 | { |
249 | __asm__("xchgb %b0,%h0" : "=q" (x):"0" (x)); |
250 | return x; |
251 | } |
252 | #elif defined(__x86_64__) |
253 | SDL_FORCE_INLINE Uint16 SDL_Swap16(Uint16 x) |
254 | { |
255 | __asm__("xchgb %b0,%h0" : "=Q" (x):"0" (x)); |
256 | return x; |
257 | } |
258 | #elif (defined(__powerpc__) || defined(__ppc__)) |
259 | SDL_FORCE_INLINE Uint16 SDL_Swap16(Uint16 x) |
260 | { |
261 | int result; |
262 | |
263 | __asm__("rlwimi %0,%2,8,16,23" : "=&r" (result):"0" (x >> 8), "r" (x)); |
264 | return (Uint16)result; |
265 | } |
266 | #elif (defined(__m68k__) && !defined(__mcoldfire__)) |
267 | SDL_FORCE_INLINE Uint16 SDL_Swap16(Uint16 x) |
268 | { |
269 | __asm__("rorw #8,%0" : "=d" (x): "0" (x):"cc" ); |
270 | return x; |
271 | } |
272 | #elif defined(__WATCOMC__) && defined(__386__) |
273 | extern __inline Uint16 SDL_Swap16(Uint16); |
274 | #pragma aux SDL_Swap16 = \ |
275 | "xchg al, ah" \ |
276 | parm [ax] \ |
277 | modify [ax]; |
278 | #else |
279 | SDL_FORCE_INLINE Uint16 SDL_Swap16(Uint16 x) |
280 | { |
281 | return SDL_static_cast(Uint16, ((x << 8) | (x >> 8))); |
282 | } |
283 | #endif |
284 | #endif |
285 | |
286 | /* Byte swap 32-bit integer. */ |
287 | #ifndef SDL_WIKI_DOCUMENTATION_SECTION |
288 | #if HAS_BUILTIN_BSWAP32 |
289 | #define SDL_Swap32(x) __builtin_bswap32(x) |
290 | #elif (defined(_MSC_VER) && (_MSC_VER >= 1400)) && !defined(__ICL) |
291 | #pragma intrinsic(_byteswap_ulong) |
292 | #define SDL_Swap32(x) _byteswap_ulong(x) |
293 | #elif defined(__i386__) && !HAS_BROKEN_BSWAP |
294 | SDL_FORCE_INLINE Uint32 SDL_Swap32(Uint32 x) |
295 | { |
296 | __asm__("bswap %0" : "=r" (x):"0" (x)); |
297 | return x; |
298 | } |
299 | #elif defined(__x86_64__) |
300 | SDL_FORCE_INLINE Uint32 SDL_Swap32(Uint32 x) |
301 | { |
302 | __asm__("bswapl %0" : "=r" (x):"0" (x)); |
303 | return x; |
304 | } |
305 | #elif (defined(__powerpc__) || defined(__ppc__)) |
306 | SDL_FORCE_INLINE Uint32 SDL_Swap32(Uint32 x) |
307 | { |
308 | Uint32 result; |
309 | |
310 | __asm__("rlwimi %0,%2,24,16,23" : "=&r" (result): "0" (x>>24), "r" (x)); |
311 | __asm__("rlwimi %0,%2,8,8,15" : "=&r" (result): "0" (result), "r" (x)); |
312 | __asm__("rlwimi %0,%2,24,0,7" : "=&r" (result): "0" (result), "r" (x)); |
313 | return result; |
314 | } |
315 | #elif (defined(__m68k__) && !defined(__mcoldfire__)) |
316 | SDL_FORCE_INLINE Uint32 SDL_Swap32(Uint32 x) |
317 | { |
318 | __asm__("rorw #8,%0\n\tswap %0\n\trorw #8,%0" : "=d" (x): "0" (x):"cc" ); |
319 | return x; |
320 | } |
321 | #elif defined(__WATCOMC__) && defined(__386__) |
322 | extern __inline Uint32 SDL_Swap32(Uint32); |
323 | #pragma aux SDL_Swap32 = \ |
324 | "bswap eax" \ |
325 | parm [eax] \ |
326 | modify [eax]; |
327 | #else |
328 | SDL_FORCE_INLINE Uint32 SDL_Swap32(Uint32 x) |
329 | { |
330 | return SDL_static_cast(Uint32, ((x << 24) | ((x << 8) & 0x00FF0000) | |
331 | ((x >> 8) & 0x0000FF00) | (x >> 24))); |
332 | } |
333 | #endif |
334 | #endif |
335 | |
336 | /* Byte swap 64-bit integer. */ |
337 | #ifndef SDL_WIKI_DOCUMENTATION_SECTION |
338 | #if HAS_BUILTIN_BSWAP64 |
339 | #define SDL_Swap64(x) __builtin_bswap64(x) |
340 | #elif (defined(_MSC_VER) && (_MSC_VER >= 1400)) && !defined(__ICL) |
341 | #pragma intrinsic(_byteswap_uint64) |
342 | #define SDL_Swap64(x) _byteswap_uint64(x) |
343 | #elif defined(__i386__) && !HAS_BROKEN_BSWAP |
344 | SDL_FORCE_INLINE Uint64 SDL_Swap64(Uint64 x) |
345 | { |
346 | union { |
347 | struct { |
348 | Uint32 a, b; |
349 | } s; |
350 | Uint64 u; |
351 | } v; |
352 | v.u = x; |
353 | __asm__("bswapl %0 ; bswapl %1 ; xchgl %0,%1" |
354 | : "=r" (v.s.a), "=r" (v.s.b) |
355 | : "0" (v.s.a), "1" (v.s.b)); |
356 | return v.u; |
357 | } |
358 | #elif defined(__x86_64__) |
359 | SDL_FORCE_INLINE Uint64 SDL_Swap64(Uint64 x) |
360 | { |
361 | __asm__("bswapq %0" : "=r" (x):"0" (x)); |
362 | return x; |
363 | } |
364 | #elif defined(__WATCOMC__) && defined(__386__) |
365 | extern __inline Uint64 SDL_Swap64(Uint64); |
366 | #pragma aux SDL_Swap64 = \ |
367 | "bswap eax" \ |
368 | "bswap edx" \ |
369 | "xchg eax,edx" \ |
370 | parm [eax edx] \ |
371 | modify [eax edx]; |
372 | #else |
373 | SDL_FORCE_INLINE Uint64 SDL_Swap64(Uint64 x) |
374 | { |
375 | Uint32 hi, lo; |
376 | |
377 | /* Separate into high and low 32-bit values and swap them */ |
378 | lo = SDL_static_cast(Uint32, x & 0xFFFFFFFF); |
379 | x >>= 32; |
380 | hi = SDL_static_cast(Uint32, x & 0xFFFFFFFF); |
381 | x = SDL_Swap32(lo); |
382 | x <<= 32; |
383 | x |= SDL_Swap32(hi); |
384 | return (x); |
385 | } |
386 | #endif |
387 | #endif |
388 | |
389 | /** |
390 | * Byte-swap a floating point number. |
391 | * |
392 | * This will always byte-swap the value, whether it's currently in the native |
393 | * byteorder of the system or not. You should use SDL_SwapFloatLE or |
394 | * SDL_SwapFloatBE instead, in most cases. |
395 | * |
396 | * Note that this is a forced-inline function in a header, and not a public |
397 | * API function available in the SDL library (which is to say, the code is |
398 | * embedded in the calling program and the linker and dynamic loader will not |
399 | * be able to find this function inside SDL itself). |
400 | * |
401 | * \param x the value to byte-swap. |
402 | * \returns x, with its bytes in the opposite endian order. |
403 | * |
404 | * \threadsafety It is safe to call this function from any thread. |
405 | * |
406 | * \since This function is available since SDL 3.2.0. |
407 | */ |
408 | SDL_FORCE_INLINE float SDL_SwapFloat(float x) |
409 | { |
410 | union { |
411 | float f; |
412 | Uint32 ui32; |
413 | } swapper; |
414 | swapper.f = x; |
415 | swapper.ui32 = SDL_Swap32(swapper.ui32); |
416 | return swapper.f; |
417 | } |
418 | |
419 | /* remove extra macros */ |
420 | #undef HAS_BROKEN_BSWAP |
421 | #undef HAS_BUILTIN_BSWAP16 |
422 | #undef HAS_BUILTIN_BSWAP32 |
423 | #undef HAS_BUILTIN_BSWAP64 |
424 | |
425 | |
426 | #ifdef SDL_WIKI_DOCUMENTATION_SECTION |
427 | |
428 | /** |
429 | * Byte-swap an unsigned 16-bit number. |
430 | * |
431 | * This will always byte-swap the value, whether it's currently in the native |
432 | * byteorder of the system or not. You should use SDL_Swap16LE or SDL_Swap16BE |
433 | * instead, in most cases. |
434 | * |
435 | * Note that this is a forced-inline function in a header, and not a public |
436 | * API function available in the SDL library (which is to say, the code is |
437 | * embedded in the calling program and the linker and dynamic loader will not |
438 | * be able to find this function inside SDL itself). |
439 | * |
440 | * \param x the value to byte-swap. |
441 | * \returns `x`, with its bytes in the opposite endian order. |
442 | * |
443 | * \threadsafety It is safe to call this function from any thread. |
444 | * |
445 | * \since This function is available since SDL 3.2.0. |
446 | */ |
447 | SDL_FORCE_INLINE Uint16 SDL_Swap16(Uint16 x) { return x_but_byteswapped; } |
448 | |
449 | /** |
450 | * Byte-swap an unsigned 32-bit number. |
451 | * |
452 | * This will always byte-swap the value, whether it's currently in the native |
453 | * byteorder of the system or not. You should use SDL_Swap32LE or SDL_Swap32BE |
454 | * instead, in most cases. |
455 | * |
456 | * Note that this is a forced-inline function in a header, and not a public |
457 | * API function available in the SDL library (which is to say, the code is |
458 | * embedded in the calling program and the linker and dynamic loader will not |
459 | * be able to find this function inside SDL itself). |
460 | * |
461 | * \param x the value to byte-swap. |
462 | * \returns `x`, with its bytes in the opposite endian order. |
463 | * |
464 | * \threadsafety It is safe to call this function from any thread. |
465 | * |
466 | * \since This function is available since SDL 3.2.0. |
467 | */ |
468 | SDL_FORCE_INLINE Uint32 SDL_Swap32(Uint32 x) { return x_but_byteswapped; } |
469 | |
470 | /** |
471 | * Byte-swap an unsigned 64-bit number. |
472 | * |
473 | * This will always byte-swap the value, whether it's currently in the native |
474 | * byteorder of the system or not. You should use SDL_Swap64LE or SDL_Swap64BE |
475 | * instead, in most cases. |
476 | * |
477 | * Note that this is a forced-inline function in a header, and not a public |
478 | * API function available in the SDL library (which is to say, the code is |
479 | * embedded in the calling program and the linker and dynamic loader will not |
480 | * be able to find this function inside SDL itself). |
481 | * |
482 | * \param x the value to byte-swap. |
483 | * \returns `x`, with its bytes in the opposite endian order. |
484 | * |
485 | * \threadsafety It is safe to call this function from any thread. |
486 | * |
487 | * \since This function is available since SDL 3.2.0. |
488 | */ |
489 | SDL_FORCE_INLINE Uint32 SDL_Swap64(Uint64 x) { return x_but_byteswapped; } |
490 | |
491 | /** |
492 | * Swap a 16-bit value from littleendian to native byte order. |
493 | * |
494 | * If this is running on a littleendian system, `x` is returned unchanged. |
495 | * |
496 | * This macro never references `x` more than once, avoiding side effects. |
497 | * |
498 | * \param x the value to swap, in littleendian byte order. |
499 | * \returns `x` in native byte order. |
500 | * |
501 | * \threadsafety It is safe to call this macro from any thread. |
502 | * |
503 | * \since This macro is available since SDL 3.2.0. |
504 | */ |
505 | #define SDL_Swap16LE(x) SwapOnlyIfNecessary(x) |
506 | |
507 | /** |
508 | * Swap a 32-bit value from littleendian to native byte order. |
509 | * |
510 | * If this is running on a littleendian system, `x` is returned unchanged. |
511 | * |
512 | * This macro never references `x` more than once, avoiding side effects. |
513 | * |
514 | * \param x the value to swap, in littleendian byte order. |
515 | * \returns `x` in native byte order. |
516 | * |
517 | * \threadsafety It is safe to call this macro from any thread. |
518 | * |
519 | * \since This macro is available since SDL 3.2.0. |
520 | */ |
521 | #define SDL_Swap32LE(x) SwapOnlyIfNecessary(x) |
522 | |
523 | /** |
524 | * Swap a 64-bit value from littleendian to native byte order. |
525 | * |
526 | * If this is running on a littleendian system, `x` is returned unchanged. |
527 | * |
528 | * This macro never references `x` more than once, avoiding side effects. |
529 | * |
530 | * \param x the value to swap, in littleendian byte order. |
531 | * \returns `x` in native byte order. |
532 | * |
533 | * \threadsafety It is safe to call this macro from any thread. |
534 | * |
535 | * \since This macro is available since SDL 3.2.0. |
536 | */ |
537 | #define SDL_Swap64LE(x) SwapOnlyIfNecessary(x) |
538 | |
539 | /** |
540 | * Swap a floating point value from littleendian to native byte order. |
541 | * |
542 | * If this is running on a littleendian system, `x` is returned unchanged. |
543 | * |
544 | * This macro never references `x` more than once, avoiding side effects. |
545 | * |
546 | * \param x the value to swap, in littleendian byte order. |
547 | * \returns `x` in native byte order. |
548 | * |
549 | * \threadsafety It is safe to call this macro from any thread. |
550 | * |
551 | * \since This macro is available since SDL 3.2.0. |
552 | */ |
553 | #define SDL_SwapFloatLE(x) SwapOnlyIfNecessary(x) |
554 | |
555 | /** |
556 | * Swap a 16-bit value from bigendian to native byte order. |
557 | * |
558 | * If this is running on a bigendian system, `x` is returned unchanged. |
559 | * |
560 | * This macro never references `x` more than once, avoiding side effects. |
561 | * |
562 | * \param x the value to swap, in bigendian byte order. |
563 | * \returns `x` in native byte order. |
564 | * |
565 | * \threadsafety It is safe to call this macro from any thread. |
566 | * |
567 | * \since This macro is available since SDL 3.2.0. |
568 | */ |
569 | #define SDL_Swap16BE(x) SwapOnlyIfNecessary(x) |
570 | |
571 | /** |
572 | * Swap a 32-bit value from bigendian to native byte order. |
573 | * |
574 | * If this is running on a bigendian system, `x` is returned unchanged. |
575 | * |
576 | * This macro never references `x` more than once, avoiding side effects. |
577 | * |
578 | * \param x the value to swap, in bigendian byte order. |
579 | * \returns `x` in native byte order. |
580 | * |
581 | * \threadsafety It is safe to call this macro from any thread. |
582 | * |
583 | * \since This macro is available since SDL 3.2.0. |
584 | */ |
585 | #define SDL_Swap32BE(x) SwapOnlyIfNecessary(x) |
586 | |
587 | /** |
588 | * Swap a 64-bit value from bigendian to native byte order. |
589 | * |
590 | * If this is running on a bigendian system, `x` is returned unchanged. |
591 | * |
592 | * This macro never references `x` more than once, avoiding side effects. |
593 | * |
594 | * \param x the value to swap, in bigendian byte order. |
595 | * \returns `x` in native byte order. |
596 | * |
597 | * \threadsafety It is safe to call this macro from any thread. |
598 | * |
599 | * \since This macro is available since SDL 3.2.0. |
600 | */ |
601 | #define SDL_Swap64BE(x) SwapOnlyIfNecessary(x) |
602 | |
603 | /** |
604 | * Swap a floating point value from bigendian to native byte order. |
605 | * |
606 | * If this is running on a bigendian system, `x` is returned unchanged. |
607 | * |
608 | * This macro never references `x` more than once, avoiding side effects. |
609 | * |
610 | * \param x the value to swap, in bigendian byte order. |
611 | * \returns `x` in native byte order. |
612 | * |
613 | * \threadsafety It is safe to call this macro from any thread. |
614 | * |
615 | * \since This macro is available since SDL 3.2.0. |
616 | */ |
617 | #define SDL_SwapFloatBE(x) SwapOnlyIfNecessary(x) |
618 | |
619 | #elif SDL_BYTEORDER == SDL_LIL_ENDIAN |
620 | #define SDL_Swap16LE(x) (x) |
621 | #define SDL_Swap32LE(x) (x) |
622 | #define SDL_Swap64LE(x) (x) |
623 | #define SDL_SwapFloatLE(x) (x) |
624 | #define SDL_Swap16BE(x) SDL_Swap16(x) |
625 | #define SDL_Swap32BE(x) SDL_Swap32(x) |
626 | #define SDL_Swap64BE(x) SDL_Swap64(x) |
627 | #define SDL_SwapFloatBE(x) SDL_SwapFloat(x) |
628 | #else |
629 | #define SDL_Swap16LE(x) SDL_Swap16(x) |
630 | #define SDL_Swap32LE(x) SDL_Swap32(x) |
631 | #define SDL_Swap64LE(x) SDL_Swap64(x) |
632 | #define SDL_SwapFloatLE(x) SDL_SwapFloat(x) |
633 | #define SDL_Swap16BE(x) (x) |
634 | #define SDL_Swap32BE(x) (x) |
635 | #define SDL_Swap64BE(x) (x) |
636 | #define SDL_SwapFloatBE(x) (x) |
637 | #endif |
638 | |
639 | /* Ends C function definitions when using C++ */ |
640 | #ifdef __cplusplus |
641 | } |
642 | #endif |
643 | #include <SDL3/SDL_close_code.h> |
644 | |
645 | #endif /* SDL_endian_h_ */ |
646 | |