• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Bytes swap functions, reverse order of bytes:
2 
3    - _Py_bswap16(uint16_t)
4    - _Py_bswap32(uint32_t)
5    - _Py_bswap64(uint64_t)
6 */
7 
8 #ifndef Py_INTERNAL_BSWAP_H
9 #define Py_INTERNAL_BSWAP_H
10 #ifdef __cplusplus
11 extern "C" {
12 #endif
13 
14 #ifndef Py_BUILD_CORE
15 #  error "this header requires Py_BUILD_CORE define"
16 #endif
17 
18 #if defined(__GNUC__) \
19       && ((__GNUC__ >= 5) || (__GNUC__ == 4) && (__GNUC_MINOR__ >= 8))
20    /* __builtin_bswap16() is available since GCC 4.8,
21       __builtin_bswap32() is available since GCC 4.3,
22       __builtin_bswap64() is available since GCC 4.3. */
23 #  define _PY_HAVE_BUILTIN_BSWAP
24 #endif
25 
26 #ifdef _MSC_VER
27    /* Get _byteswap_ushort(), _byteswap_ulong(), _byteswap_uint64() */
28 #  include <intrin.h>
29 #endif
30 
31 static inline uint16_t
_Py_bswap16(uint16_t word)32 _Py_bswap16(uint16_t word)
33 {
34 #if defined(_PY_HAVE_BUILTIN_BSWAP) || _Py__has_builtin(__builtin_bswap16)
35     return __builtin_bswap16(word);
36 #elif defined(_MSC_VER)
37     Py_BUILD_ASSERT(sizeof(word) == sizeof(unsigned short));
38     return _byteswap_ushort(word);
39 #else
40     // Portable implementation which doesn't rely on circular bit shift
41     return ( ((word & UINT16_C(0x00FF)) << 8)
42            | ((word & UINT16_C(0xFF00)) >> 8));
43 #endif
44 }
45 
46 static inline uint32_t
_Py_bswap32(uint32_t word)47 _Py_bswap32(uint32_t word)
48 {
49 #if defined(_PY_HAVE_BUILTIN_BSWAP) || _Py__has_builtin(__builtin_bswap32)
50     return __builtin_bswap32(word);
51 #elif defined(_MSC_VER)
52     Py_BUILD_ASSERT(sizeof(word) == sizeof(unsigned long));
53     return _byteswap_ulong(word);
54 #else
55     // Portable implementation which doesn't rely on circular bit shift
56     return ( ((word & UINT32_C(0x000000FF)) << 24)
57            | ((word & UINT32_C(0x0000FF00)) <<  8)
58            | ((word & UINT32_C(0x00FF0000)) >>  8)
59            | ((word & UINT32_C(0xFF000000)) >> 24));
60 #endif
61 }
62 
63 static inline uint64_t
_Py_bswap64(uint64_t word)64 _Py_bswap64(uint64_t word)
65 {
66 #if defined(_PY_HAVE_BUILTIN_BSWAP) || _Py__has_builtin(__builtin_bswap64)
67     return __builtin_bswap64(word);
68 #elif defined(_MSC_VER)
69     return _byteswap_uint64(word);
70 #else
71     // Portable implementation which doesn't rely on circular bit shift
72     return ( ((word & UINT64_C(0x00000000000000FF)) << 56)
73            | ((word & UINT64_C(0x000000000000FF00)) << 40)
74            | ((word & UINT64_C(0x0000000000FF0000)) << 24)
75            | ((word & UINT64_C(0x00000000FF000000)) <<  8)
76            | ((word & UINT64_C(0x000000FF00000000)) >>  8)
77            | ((word & UINT64_C(0x0000FF0000000000)) >> 24)
78            | ((word & UINT64_C(0x00FF000000000000)) >> 40)
79            | ((word & UINT64_C(0xFF00000000000000)) >> 56));
80 #endif
81 }
82 
83 
84 #ifdef __cplusplus
85 }
86 #endif
87 #endif /* !Py_INTERNAL_BSWAP_H */
88 
89