mitteLib
Loading...
Searching...
No Matches
byte_order.hpp
Go to the documentation of this file.
1//
2// Created by spak on 2/25/21.
3//
4
5#ifndef MLAB_BYTE_ORDER_HPP
6#define MLAB_BYTE_ORDER_HPP
7
8#include <cstdint>
9#include <tuple>
10#include <type_traits>
11
12namespace mlab {
13
14 enum struct byte_order {
17 };
18
19 namespace impl {
20 template <unsigned Bits>
21 auto get_uint_exact();
22
23 template <unsigned Bits>
24 auto get_uint_least();
25 }// namespace impl
26
27 template <unsigned Bits>
29
30 template <unsigned Bits>
32
33 template <unsigned Bits>
34 using int_least_t [[maybe_unused]] = std::make_signed_t<uint_least_t<Bits>>;
35
36 template <byte_order Order, unsigned Bits, class Num>
37 std::array<std::uint8_t, Bits / 8> encode(Num n);
38
39 template <byte_order Order, unsigned Bits, class Num>
40 Num decode(std::array<std::uint8_t, Bits / 8> const &b);
41
45#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
46 static constexpr byte_order local_byte_order = byte_order::msb_first;
47#elif defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
48 static constexpr byte_order local_byte_order = byte_order::lsb_first;
49#endif
50
56 template <class Num, std::size_t NBytes>
57 [[nodiscard]] constexpr Num lsb_unsigned_decode(std::array<std::uint8_t, NBytes> b);
58
59 template <class Num, std::size_t NBytes, std::size_t I = NBytes - 1>
60 [[nodiscard]] constexpr Num msb_unsigned_decode(std::array<std::uint8_t, NBytes> b);
61
62 template <class Num, std::size_t NBytes>
63 [[nodiscard]] constexpr std::array<std::uint8_t, NBytes> lsb_unsigned_encode(Num n);
64
65 template <class Num, std::size_t NBytes>
66 [[nodiscard]] constexpr std::array<std::uint8_t, NBytes> msb_unsigned_encode(Num n);
71}// namespace mlab
72
73namespace mlab {
74
75 namespace impl {
76 template <unsigned Bits>
78 if constexpr (Bits == 8) {
79 return std::uint8_t{};
80 } else if constexpr (Bits == 16) {
81 return std::uint16_t{};
82 } else if constexpr (Bits == 32) {
83 return std::uint32_t{};
84 } else if constexpr (Bits == 64) {
85 return std::uint64_t{};
86 } else {
87 static_assert(Bits % 8 == 0 and Bits > 0 and Bits <= 64);
88 }
89 }
90
91 template <unsigned Bits>
93 if constexpr (Bits <= 8) {
94 return std::uint8_t{};
95 } else if constexpr (Bits <= 16) {
96 return std::uint16_t{};
97 } else if constexpr (Bits <= 32) {
98 return std::uint32_t{};
99 } else if constexpr (Bits <= 64) {
100 return std::uint64_t{};
101 } else {
102 static_assert(Bits > 0 and Bits <= 64);
103 }
104 }
105 }// namespace impl
106
107 template <class Num, std::size_t NBytes>
108 constexpr Num lsb_unsigned_decode(std::array<std::uint8_t, NBytes> b) {
109 static_assert(std::is_integral_v<Num> and std::is_unsigned_v<Num> and sizeof(Num) >= NBytes, "Use a sufficiently large unsigned integer.");
110 Num n{};
111 for (std::size_t i = 0; i < NBytes; ++i) {
112 n |= Num(b[i]) << (i * 8);
113 }
114 return n;
115 }
116
117 template <class Num, std::size_t NBytes>
118 constexpr Num msb_unsigned_decode(std::array<std::uint8_t, NBytes> b) {
119 static_assert(std::is_integral_v<Num> and std::is_unsigned_v<Num> and sizeof(Num) >= NBytes, "Use a sufficiently large unsigned integer.");
120 Num n{};
121 for (std::size_t i = 0; i < NBytes; ++i) {
122 n <<= 8;
123 n |= Num(b[i]);
124 }
125 return n;
126 }
127
128 template <class Num, std::size_t NBytes>
129 constexpr std::array<std::uint8_t, NBytes> lsb_unsigned_encode(Num n) {
130 static_assert(std::is_integral_v<Num> and std::is_unsigned_v<Num> and sizeof(Num) >= NBytes, "Use a sufficiently large unsigned integer.");
131 std::array<std::uint8_t, NBytes> a{};
132 for (std::size_t i = 0; i < NBytes; ++i, n >>= 8) {
133 a[i] = std::uint8_t(n & 0xff);
134 }
135 return a;
136 }
137
138 template <class Num, std::size_t NBytes>
139 constexpr std::array<std::uint8_t, NBytes> msb_unsigned_encode(Num n) {
140 static_assert(std::is_integral_v<Num> and std::is_unsigned_v<Num> and sizeof(Num) >= NBytes, "Use a sufficiently large unsigned integer.");
141 std::array<std::uint8_t, NBytes> a{};
142 for (std::size_t i = 0; i < NBytes; ++i, n >>= 8) {
143 a[NBytes - i - 1] = std::uint8_t(n & 0xff);
144 }
145 return a;
146 }
147
148 template <byte_order Order, unsigned Bits, class Num>
149 std::array<std::uint8_t, Bits / 8> encode(Num n) {
150 static_assert(sizeof(Num) >= Bits / 8, "Use a sufficiently large number.");
151 static_assert(std::is_integral_v<Num> or std::is_floating_point_v<Num>);
152 if constexpr (std::is_floating_point_v<Num>) {
153 using UNum = uint_exact_t<sizeof(Num) * 8>;
154 return encode<Order, Bits, UNum>(*reinterpret_cast<UNum const *>(&n));
155 } else if constexpr (std::is_signed_v<Num>) {
156 using UNum = std::make_unsigned_t<Num>;
157 return encode<Order, Bits, UNum>(*reinterpret_cast<UNum const *>(&n));
158 } else {
159 if constexpr (Order == byte_order::lsb_first) {
160 return lsb_unsigned_encode<Num, Bits / 8>(n);
161 } else {
162 return msb_unsigned_encode<Num, Bits / 8>(n);
163 }
164 }
165 }
166
167 template <byte_order Order, unsigned Bits, class Num>
168 Num decode(std::array<std::uint8_t, Bits / 8> const &b) {
169 static_assert(sizeof(Num) >= Bits / 8, "Use a sufficiently large number.");
170 static_assert(std::is_integral_v<Num> or std::is_floating_point_v<Num>);
171 Num n{};
172 if constexpr (std::is_floating_point_v<Num>) {
173 using UNum = uint_exact_t<sizeof(Num) * 8>;
174 *reinterpret_cast<UNum *>(&n) = decode<Order, Bits, UNum>(b);
175 } else if constexpr (std::is_signed_v<Num>) {
176 using UNum = std::make_unsigned_t<Num>;
177 *reinterpret_cast<UNum *>(&n) = decode<Order, Bits, UNum>(b);
178 } else {
179 if constexpr (Order == byte_order::lsb_first) {
180 return lsb_unsigned_decode<Num, Bits / 8>(b);
181 } else {
182 return msb_unsigned_decode<Num, Bits / 8>(b);
183 }
184 }
185 return n;
186 }
187
188}// namespace mlab
189
190#endif//MLAB_BYTE_ORDER_HPP
constexpr std::array< std::uint8_t, NBytes > msb_unsigned_encode(Num n)
Definition byte_order.hpp:139
constexpr Num msb_unsigned_decode(std::array< std::uint8_t, NBytes > b)
constexpr Num lsb_unsigned_decode(std::array< std::uint8_t, NBytes > b)
Definition byte_order.hpp:108
constexpr std::array< std::uint8_t, NBytes > lsb_unsigned_encode(Num n)
Definition byte_order.hpp:129
auto get_uint_least()
Definition byte_order.hpp:92
auto get_uint_exact()
Definition byte_order.hpp:77
Definition log.cpp:8
decltype(impl::get_uint_exact< Bits >()) uint_exact_t
Definition byte_order.hpp:31
byte_order
Definition byte_order.hpp:14
std::array< std::uint8_t, Bits/8 > encode(Num n)
Definition byte_order.hpp:149
decltype(impl::get_uint_least< Bits >()) uint_least_t
Definition byte_order.hpp:28
Num decode(std::array< std::uint8_t, Bits/8 > const &b)
Definition byte_order.hpp:168