ipaddress 1.1.0
Loading...
Searching...
No Matches
endian.hpp
Go to the documentation of this file.
1/**
2 * @file endian.hpp
3 * @brief Defines macros to determine byte order
4 * @author Vladimir Shaleev
5 * @copyright MIT License
6 *
7 * This header file contains macros and utility functions to determine
8 * and work with the byte order (endianness) of the system. It provides
9 * a set of preprocessor directives that establish the byte order based
10 * on various conditions, such as user definitions, C++20 standard features,
11 * or platform-specific macros.
12 *
13 * The file defines `IPADDRESS_LITTLE_ENDIAN` and `IPADDRESS_BIG_ENDIAN`
14 * as constants for comparison and sets `IPADDRESS_ENDIAN` accordingly.
15 * It also includes functions to check the system's endianness and to
16 * swap bytes in an integer, which are useful for network programming
17 * and handling data with different endianness.
18 *
19 * The determination of endianness is done with a priority order:
20 * 1. C++20's `std::endian`.
21 * 2. User-defined `IPADDRESS_ENDIAN`.
22 * 3. Platform/compiler-provided macros.
23 *
24 * If the endianness cannot be determined, a compilation error is raised
25 * prompting the user to define `IPADDRESS_ENDIAN`.
26 */
27
28#ifndef IPADDRESS_ENDIAN_HPP
29#define IPADDRESS_ENDIAN_HPP
30
31#include "config.hpp"
32
33#if (IPADDRESS_CPP_VERSION >= 20) && defined(__has_include)
34# if __has_include(<bit>)
35# define IPADDRESS_HAS_STD_ENDIAN
36# ifndef IPADDRESS_MODULE
37# include <bit>
38# endif
39# endif
40#endif
41
42#define IPADDRESS_LITTLE_ENDIAN 0
43#define IPADDRESS_BIG_ENDIAN 1
44
45#ifndef IPADDRESS_ENDIAN
46// GCC 4.6
47# ifdef __BYTE_ORDER__
48# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
49# define IPADDRESS_ENDIAN IPADDRESS_LITTLE_ENDIAN
50# elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
51# define IPADDRESS_ENDIAN IPADDRESS_BIG_ENDIAN
52# else
53# error Unknown endianness detected. Needs to define IPADDRESS_ENDIAN
54# endif
55// GLIBC
56# elif defined(__GLIBC__) && !defined(IPADDRESS_MODULE)
57# include <endian.h>
58# if (__BYTE_ORDER == __LITTLE_ENDIAN)
59# define IPADDRESS_ENDIAN IPADDRESS_LITTLE_ENDIAN
60# elif (__BYTE_ORDER == __BIG_ENDIAN)
61# define IPADDRESS_ENDIAN IPADDRESS_BIG_ENDIAN
62# else
63# error Unknown endianness detected. Needs to define IPADDRESS_ENDIAN
64# endif
65// _LITTLE_ENDIAN and _BIG_ENDIAN
66# elif defined(_LITTLE_ENDIAN) && !defined(_BIG_ENDIAN)
67# define IPADDRESS_ENDIAN IPADDRESS_LITTLE_ENDIAN
68# elif defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)
69# define IPADDRESS_ENDIAN IPADDRESS_BIG_ENDIAN
70// For architecture
71# elif defined(__hppa) ||
72 defined(__hpux) ||
73 defined(__powerpc__) ||
74 defined(__ppc__) ||
75 defined(__s390__)
76 defined(__sparc__) ||
77 defined(__sparc) ||
78 defined(_MIPSEB) ||
79 defined(_POWER)
80# define IPADDRESS_ENDIAN IPADDRESS_BIG_ENDIAN
81# elif defined(__alpha__) ||
82 defined(__amd64__) ||
83 defined(__amd64) ||
84 defined(__bfin__) ||
85 defined(__i386__) ||
86 defined(__ia64__) ||
87 defined(__ia64) ||
88 defined(__x86_64__) ||
89 defined(__x86_64) ||
90 defined(_M_ALPHA) ||
91 defined(_M_AMD64) ||
92 defined(_M_IA64) ||
93 defined(_M_IX86) ||
94 defined(_M_X64)
95# define IPADDRESS_ENDIAN IPADDRESS_LITTLE_ENDIAN
96# elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
97# define IPADDRESS_ENDIAN IPADDRESS_LITTLE_ENDIAN
98# elif !defined(IPADDRESS_HAS_STD_ENDIAN)
99# error Unknown endianness detected. Needs to define IPADDRESS_ENDIAN
100# endif
101#endif
102
103namespace IPADDRESS_NAMESPACE {
104
105/**
106 * Checks if the system is little-endian.
107 *
108 * @return `true` if the system is little-endian, `false` otherwise.
109 */
111#if defined(IPADDRESS_HAS_STD_ENDIAN)
112 return std::endian::native == std::endian::little;
113#elif defined(IPADDRESS_ENDIAN)
114 return !IPADDRESS_ENDIAN;
115#else
116# error Unknown endianness detected. Needs to define IPADDRESS_ENDIAN
117#endif
118}
119
120/**
121 * Swaps the bytes of a 32-bit unsigned integer.
122 *
123 * @param[in] value The integer value to swap bytes of.
124 * @return The value with its bytes swapped.
125 */
127 value = ((value << 8) & 0xFF00FF00) | ((value >> 8) & 0x00FF00FF);
128 value = (value << 16) | (value >> 16);
129 return value;
130}
131
132} // namespace IPADDRESS_NAMESPACE
133
134#endif // IPADDRESS_ENDIAN_HPP
#define IPADDRESS_EXPORT
Definition config.hpp:42
#define IPADDRESS_NODISCARD
Definition config.hpp:98
#define IPADDRESS_FORCE_INLINE
Definition config.hpp:112
#define IPADDRESS_NAMESPACE
Definition config.hpp:38
#define IPADDRESS_NOEXCEPT
Definition config.hpp:89
#define IPADDRESS_LITTLE_ENDIAN
Definition endian.hpp:42
constexpr inline bool is_little_endian() noexcept
Checks if the system is little-endian.
Definition endian.hpp:110
constexpr inline uint32_t swap_bytes(uint32_t value) noexcept
Swaps the bytes of a 32-bit unsigned integer.
Definition endian.hpp:126