BitStream
endian.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <cstdint>
4 
5 #if defined(__cpp_lib_endian) && __cpp_lib_endian >= 201907L
6 #include <bit>
7 #else // __cpp_lib_endian
8 #ifndef BS_LITTLE_ENDIAN
9 // Detect with GCC 4.6's macro.
10 #if defined(__BYTE_ORDER__)
11 #if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
12 #define BS_LITTLE_ENDIAN true
13 #elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
14 #define BS_LITTLE_ENDIAN false
15 #else
16 #error "Unknown machine byteorder endianness detected. Need to manually define BS_LITTLE_ENDIAN."
17 #endif
18 // Detect with GLIBC's endian.h.
19 #elif defined(__GLIBC__)
20 #include <endian.h>
21 #if (__BYTE_ORDER == __LITTLE_ENDIAN)
22 #define BS_LITTLE_ENDIAN true
23 #elif (__BYTE_ORDER == __BIG_ENDIAN)
24 #define BS_LITTLE_ENDIAN false
25 #else
26 #error "Unknown machine byteorder endianness detected. Need to manually define BS_LITTLE_ENDIAN."
27 #endif
28 // Detect with _LITTLE_ENDIAN and _BIG_ENDIAN macro.
29 #elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
30 #define BS_LITTLE_ENDIAN true
31 #elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
32 #define BS_LITTLE_ENDIAN false
33 // Detect with architecture macros.
34 #elif defined(__sparc) || defined(__sparc__) || defined(_POWER) || defined(__powerpc__) || defined(__ppc__) || defined(__hpux) || defined(__hppa) || defined(_MIPSEB) || defined(_POWER) || defined(__s390__)
35 #define BS_LITTLE_ENDIAN false
36 #elif defined(__i386__) || defined(__alpha__) || defined(__ia64) || defined(__ia64__) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_ALPHA) || defined(__amd64) || defined(__amd64__) || defined(_M_AMD64) || defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || defined(__bfin__)
37 #define BS_LITTLE_ENDIAN true
38 #elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
39 #define BS_LITTLE_ENDIAN true
40 #else
41 #error "Unknown machine byteorder endianness detected. Need to manually define BS_LITTLE_ENDIAN."
42 #endif
43 #endif // BS_LITTLE_ENDIAN
44 #endif // __cpp_lib_endian
45 
46 
47 #if defined(_WIN32)
48 #include <intrin.h>
49 #endif
50 
51 namespace bitstream::utility
52 {
53  inline constexpr bool little_endian()
54  {
55 #ifdef BS_LITTLE_ENDIAN
56 #if BS_LITTLE_ENDIAN
57  return true;
58 #else // BS_LITTLE_ENDIAN
59  return false;
60 #endif // BS_LITTLE_ENDIAN
61 #else // defined(BS_LITTLE_ENDIAN)
62  return std::endian::native == std::endian::little;
63 #endif // defined(BS_LITTLE_ENDIAN)
64  }
65 
66  inline uint32_t endian_swap32(uint32_t value)
67  {
68 #if defined(_WIN32)
69  return _byteswap_ulong(value);
70 #elif defined(__linux__)
71  return __builtin_bswap32(value);
72 #else
73  const uint32_t first = (value << 24) & 0xFF000000;
74  const uint32_t second = (value << 8) & 0x00FF0000;
75  const uint32_t third = (value >> 8) & 0x0000FF00;
76  const uint32_t fourth = (value >> 24) & 0x000000FF;
77 
78  return first | second | third | fourth;
79 #endif // _WIN32 || __linux__
80  }
81 
82  inline uint32_t to_big_endian32(uint32_t value)
83  {
84  if constexpr (little_endian())
85  return endian_swap32(value);
86  else
87  return value;
88  }
89 }
Definition: bits.h:7
uint32_t to_big_endian32(uint32_t value)
Definition: endian.h:82
uint32_t endian_swap32(uint32_t value)
Definition: endian.h:66
constexpr bool little_endian()
Definition: endian.h:53