C++ Utilities: conversion/binaryconversion.h Source File

C++ Utilities 5.35.0 Useful C++ classes and routines such as argument parser, IO and conversion utilities

Loading...
Searching...
No Matches
binaryconversion.h
Go to the documentation of this file.
1#ifndef CONVERSION_UTILITIES_BINARY_CONVERSION_H
2#define CONVERSION_UTILITIES_BINARY_CONVERSION_H
3
4#include "../global.h"
5#include "../misc/traits.h" // used in binaryconversionprivate.h
6
7#include <cstdint>
8#include <cstring> // used in binaryconversionprivate.h
9
10// use helpers from bits header if available instead of custom code using bit operations
11#if __cplusplus >= 202002L
12#include <bit>
13#endif
14
15// detect byte order according to __BYTE_ORDER__
16#if defined(__BYTE_ORDER__)
17#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
18#define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN false
19#define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN true
20#define CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN
21#elif __BYTE_ORDER__ == __ORDER_PDP_ENDIAN__
22#define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN false
23#define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN false
24#define CONVERSION_UTILITIES_BYTE_ORDER_MIDDLE_ENDIAN
25#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
26#define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN true
27#define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN false
28#define CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN
29#endif
30#endif // defined(__BYTE_ORDER__)
31
32// detect float byte order according to __FLOAT_WORD_ORDER__
33#if defined(__FLOAT_WORD_ORDER__)
34#if __FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__
35#define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_BIG_ENDIAN
36#elif __FLOAT_WORD_ORDER__ == __ORDER_PDP_ENDIAN__
37#define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_MIDDLE_ENDIAN
38#elif __FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__
39#define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_LITTLE_ENDIAN
40#endif
41#endif // defined(__FLOAT_WORD_ORDER__)
42
43// detect (float) byte order according to other macros
44#if !defined(__BYTE_ORDER__) || !defined(__FLOAT_WORD_ORDER__)
45
46// assume little endian from the presence of several macros
47#if defined(__i386) || defined(__i386__) || defined(_M_IX86) || defined(__x86_64) || defined(__x86_64__) || defined(__amd64) || defined(_M_X64) \
48 || defined(_M_ARM64) || defined(__LITTLE_ENDIAN__) || defined(_little_endian__) || defined(_LITTLE_ENDIAN) || defined(_WIN32_WCE) \
49 || defined(WINAPI_FAMILY)
50#if !defined(__BYTE_ORDER__)
51#define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN true
52#define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN false
53#define CONVERSION_UTILITIES_BYTE_ORDER_LITTLE_ENDIAN
54#endif
55#if !defined(__FLOAT_WORD_ORDER__)
56#define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_LITTLE_ENDIAN
57#endif
58
59// assume big endian from the presence of several macros
60#elif defined(__MIPSEB__) || defined(__s390__) || defined(__BIG_ENDIAN__) || defined(_big_endian__) || defined(_BIG_ENDIAN)
61#if !defined(__BYTE_ORDER__)
62#define CONVERSION_UTILITIES_IS_BYTE_ORDER_LITTLE_ENDIAN false
63#define CONVERSION_UTILITIES_IS_BYTE_ORDER_BIG_ENDIAN true
64#define CONVERSION_UTILITIES_BYTE_ORDER_BIG_ENDIAN
65#endif
66#if !defined(__FLOAT_WORD_ORDER__)
67#define CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_BIG_ENDIAN
68#endif
69
70// fail if unable to detect endianness
71#else
72#error "Unable to determine byte order!"
73#endif
74
75#endif // !defined(__BYTE_ORDER__) || !defined(__FLOAT_WORD_ORDER__)
76
77// fail if middle endian detected
78#if defined(CONVERSION_UTILITIES_BYTE_ORDER_MIDDLE_ENDIAN) || defined(CONVERSION_UTILITIES_FLOAT_BYTE_ORDER_MIDDLE_ENDIAN)
79#error "Middle endian byte order is not supported!"
80#endif
81
82namespace CppUtilities {
83
87 CPP_UTILITIES_EXPORT constexpr std::uint16_t toFixed8(float float32value)
88{
89 return static_cast<std::uint16_t>(float32value * 256.0f);
90}
91
92/*!
93 * \brief Returns a 32-bit floating point number converted from the specified 8.8 fixed point representation.
94 */
95 CPP_UTILITIES_EXPORT constexpr float toFloat32(std::uint16_t fixed8value)
96{
97 return static_cast<float>(fixed8value) / 256.0f;
98}
99
103 CPP_UTILITIES_EXPORT constexpr std::uint32_t toFixed16(float float32value)
104{
105 return static_cast<std::uint32_t>(float32value * 65536.0f);
106}
107
110 */
111 CPP_UTILITIES_EXPORT constexpr float toFloat32(std::uint32_t fixed16value)
112{
113 return static_cast<float>(fixed16value) / 65536.0f;
114}
115
121 CPP_UTILITIES_EXPORT constexpr std::uint32_t toSynchsafeInt(std::uint32_t normalInt)
122{
123 return ((normalInt & 0x0000007fu)) | ((normalInt & 0x00003f80u) << 1) | ((normalInt & 0x001fc000u) << 2) | ((normalInt & 0x0fe00000u) << 3);
124}
125
128 * \remarks Synchsafe integers appear in ID3 tags that are attached to an MP3 file.
129 * \sa <a href="http://id3.org/id3v2.4.0-structure">ID3 tag version 2.4.0 - Main Structure</a>
130 */
131 CPP_UTILITIES_EXPORT constexpr std::uint32_t toNormalInt(std::uint32_t synchsafeInt)
132{
133 return ((synchsafeInt & 0x0000007fu)) | ((synchsafeInt & 0x00007f00u) >> 1) | ((synchsafeInt & 0x007f0000u) >> 2)
134 | ((synchsafeInt & 0x7f000000u) >> 3);
135}
136
137// define helpers for byte swapping
138#ifdef __cpp_lib_byteswap // in C++ 23 we can just use the stdlib
139template <class T, Traits::EnableIf<std::is_integral<T>> * = nullptr> CPP_UTILITIES_EXPORT constexpr T swapOrder(T value)
140{
141 return std::byteswap(value);
142}
143
144#else // provide custom code for C++ 20 and older (will also be optimized by GCC and Clang to use bswap)
145
149 CPP_UTILITIES_EXPORT constexpr std::uint16_t swapOrder(std::uint16_t value)
150{
151 return static_cast<std::uint16_t>(((value >> 8) & 0x00FF) | ((value << 8) & 0xFF00));
152}
153
157 CPP_UTILITIES_EXPORT constexpr std::uint32_t swapOrder(std::uint32_t value)
158{
159 return (value >> 24) | ((value & 0x00FF0000) >> 8) | ((value & 0x0000FF00) << 8) | (value << 24);
160}
161
162
165 CPP_UTILITIES_EXPORT constexpr std::uint64_t swapOrder(std::uint64_t value)
166{
167 return (value >> (7 * 8)) | ((value & 0x00FF000000000000) >> (5 * 8)) | ((value & 0x0000FF0000000000) >> (3 * 8))
168 | ((value & 0x000000FF00000000) >> (1 * 8)) | ((value & 0x00000000FF000000) << (1 * 8)) | ((value & 0x0000000000FF0000) << (3 * 8))
169 | ((value & 0x000000000000FF00) << (5 * 8)) | ((value) << (7 * 8));
170}
171
175 CPP_UTILITIES_EXPORT constexpr std::int16_t swapOrder(std::int16_t value)
176{
177 return static_cast<std::int16_t>(((static_cast<std::uint16_t>(value) >> 8) & 0x00FF) | ((static_cast<std::uint16_t>(value) << 8) & 0xFF00));
178}
179
183 CPP_UTILITIES_EXPORT constexpr std::int32_t swapOrder(std::int32_t value)
184{
185 return static_cast<std::int32_t>((static_cast<std::uint32_t>(value) >> 24) | ((static_cast<std::uint32_t>(value) & 0x00FF0000) >> 8)
186 | ((static_cast<std::uint32_t>(value) & 0x0000FF00) << 8) | (static_cast<std::uint32_t>(value) << 24));
187}
188
192 CPP_UTILITIES_EXPORT constexpr std::int64_t swapOrder(std::int64_t value)
193{
194 return static_cast<std::int64_t>((static_cast<std::uint64_t>(value) >> (7 * 8))
195 | ((static_cast<std::uint64_t>(value) & 0x00FF000000000000) >> (5 * 8))
196 | ((static_cast<std::uint64_t>(value) & 0x0000FF0000000000) >> (3 * 8))
197 | ((static_cast<std::uint64_t>(value) & 0x000000FF00000000) >> (1 * 8))
198 | ((static_cast<std::uint64_t>(value) & 0x00000000FF000000) << (1 * 8))
199 | ((static_cast<std::uint64_t>(value) & 0x0000000000FF0000) << (3 * 8))
200 | ((static_cast<std::uint64_t>(value) & 0x000000000000FF00) << (5 * 8)) | ((static_cast<std::uint64_t>(value)) << (7 * 8)));
201}
202#endif
203
204
208 namespace BE {
209
210#define CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL 0
211#include "./binaryconversionprivate.h"
212#undef CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL
213} // namespace BE
214
219 namespace LE {
220
221#define CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL 1
222#include "./binaryconversionprivate.h"
223#undef CONVERSION_UTILITIES_BINARY_CONVERSION_INTERNAL
224} // namespace LE
225
226} // namespace CppUtilities
227
228#endif // CONVERSION_UTILITIES_BINARY_CONVERSION_H
binaryconversionprivate.h
global.h
CPP_UTILITIES_EXPORT
#define CPP_UTILITIES_EXPORT
Marks the symbol to be exported by the c++utilities library.
Definition global.h:14
CppUtilities::BE
Encapsulates binary conversion functions using the big endian byte order.
Definition binaryconversion.h:208
CppUtilities::LE
Encapsulates binary conversion functions using the little endian byte order.
Definition binaryconversion.h:219
CppUtilities
Contains all utilities provided by the c++utilities library.
Definition argumentparser.h:18
CppUtilities::toFloat32
CPP_UTILITIES_EXPORT constexpr float toFloat32(std::uint16_t fixed8value)
Returns a 32-bit floating point number converted from the specified 8.8 fixed point representation.
Definition binaryconversion.h:95
CppUtilities::toNormalInt
CPP_UTILITIES_EXPORT constexpr std::uint32_t toNormalInt(std::uint32_t synchsafeInt)
Returns a normal 32-bit integer converted from a 32-bit synchsafe integer.
Definition binaryconversion.h:131
CppUtilities::swapOrder
CPP_UTILITIES_EXPORT constexpr std::uint16_t swapOrder(std::uint16_t value)
Swaps the byte order of the specified 16-bit unsigned integer.
Definition binaryconversion.h:149
CppUtilities::toFixed16
CPP_UTILITIES_EXPORT constexpr std::uint32_t toFixed16(float float32value)
Returns the 16.16 fixed point representation converted from the specified 32-bit floating point numbe...
Definition binaryconversion.h:103
CppUtilities::toFixed8
CPP_UTILITIES_EXPORT constexpr std::uint16_t toFixed8(float float32value)
Returns the 8.8 fixed point representation converted from the specified 32-bit floating point number.
Definition binaryconversion.h:87
CppUtilities::toSynchsafeInt
CPP_UTILITIES_EXPORT constexpr std::uint32_t toSynchsafeInt(std::uint32_t normalInt)
Returns a 32-bit synchsafe integer converted from a normal 32-bit integer.
Definition binaryconversion.h:121
traits.h