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