M5Utility 0.0.12 git rev:13bfbd6
Loading...
Searching...
No Matches
types.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2024 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
25#ifndef M5_UTILITY_TYPES_HPP
26#define M5_UTILITY_TYPES_HPP
27
28#include <cstdint>
29#include <cstddef>
30#include <utility>
31#include <type_traits>
32#include "stl/endianness.hpp"
33#include "stl/byteswap.hpp"
34
35namespace m5 {
36namespace types {
37
44template <typename T, bool DataIsLittle>
45union EndianInt {
46 static_assert(m5::stl::detail::is_integer_or_enum<T>::value, "T must be an integral type");
47
50
51 constexpr EndianInt() : value{0}
52 {
53 }
55 template <bool HostIsLittle = m5::endian::little>
56 explicit EndianInt(const T v)
57 {
59 }
61 template <typename U = T, typename std::enable_if<sizeof(U) == 2, int>::type = 0>
62 constexpr EndianInt(const uint8_t b0, const uint8_t b1) : u8{b0, b1}
63 {
64 }
66 template <typename U = T, typename std::enable_if<sizeof(U) == 4, int>::type = 0>
67 constexpr EndianInt(const uint8_t b0, const uint8_t b1, const uint8_t b2, const uint8_t b3) : u8{b0, b1, b2, b3}
68 {
69 }
71 template <typename U = T, typename std::enable_if<sizeof(U) == 8, int>::type = 0>
72 constexpr EndianInt(const uint8_t b0, const uint8_t b1, const uint8_t b2, const uint8_t b3, const uint8_t b4,
73 const uint8_t b5, const uint8_t b6, const uint8_t b7)
74 : u8{b0, b1, b2, b3, b4, b5, b6, b7}
75 {
76 }
77
78 constexpr EndianInt(const EndianInt&) = default;
79
80 constexpr EndianInt(EndianInt&& o) noexcept = default;
82
85 EndianInt& operator=(const EndianInt&) = default;
86
87 EndianInt& operator=(EndianInt&&) noexcept = default;
88
89 template <bool HostIsLittle = m5::endian::little>
90 EndianInt& operator=(const T v)
91 {
93 return *this;
94 }
95 template <typename H, typename L, typename U = T, typename std::enable_if<sizeof(U) == 2, int>::type = 0>
96 EndianInt& operator=(const std::pair<H, L>& o)
97 {
98 static_assert(std::is_integral<H>::value && std::is_integral<L>::value, "HIGH & LOW Must be integral");
99 u8[0] = static_cast<uint8_t>(o.first);
100 u8[1] = static_cast<uint8_t>(o.second);
101 return *this;
102 }
104
107
108 inline explicit operator bool() const
109 {
110 return value != 0;
111 }
113 inline explicit operator const uint8_t*() const
114 {
115 return data();
116 }
118 inline explicit operator uint8_t*()
119 {
120 return data();
121 }
123 inline explicit operator T() const
124 {
125 return get();
126 }
128
133 template <bool HostIsLittle = m5::endian::little>
134 inline void set(const T v)
135 {
136 if (DataIsLittle == HostIsLittle) {
137 value = v;
138 } else {
139 value = m5::stl::byteswap(v);
140 }
141 }
146 template <bool HostIsLittle = m5::endian::little>
147 inline T get() const
148 {
149 if (DataIsLittle == HostIsLittle) {
150 return value;
151 }
152 return m5::stl::byteswap(value);
153 }
155 inline uint8_t high() const
156 {
157 return u8[0];
158 }
160 inline uint8_t low() const
161 {
162 return u8[sizeof(T) - 1];
163 }
165 inline const uint8_t* data() const
166 {
167 return u8;
168 }
170 inline uint8_t* data()
171 {
172 return u8;
173 }
175 inline size_t size() const
176 {
177 return sizeof(T);
178 }
179
180 T value{};
181 uint8_t u8[sizeof(T)];
182};
183
184// 16-bit type aliases
189
190// 32-bit type aliases
195
196// 64-bit type aliases
201
202#if defined(__SIZEOF_INT128__)
203// 128-bit type aliases (available when __int128 is supported)
204using big_uint128_t = EndianInt<unsigned __int128, false>;
205using little_uint128_t = EndianInt<unsigned __int128, true>;
206using big_int128_t = EndianInt<__int128, false>;
207using little_int128_t = EndianInt<__int128, true>;
208#endif
209
213template <typename T, bool DL1, bool DL2>
214inline bool operator==(const EndianInt<T, DL1>& a, const EndianInt<T, DL2>& b)
215{
216 return a.get() == b.get();
217}
218template <typename T, bool DL1, bool DL2>
219inline bool operator!=(const EndianInt<T, DL1>& a, const EndianInt<T, DL2>& b)
220{
221 return !(a == b);
222}
223template <typename T, bool DL1, bool DL2>
224inline bool operator<(const EndianInt<T, DL1>& a, const EndianInt<T, DL2>& b)
225{
226 return a.get() < b.get();
227}
228template <typename T, bool DL1, bool DL2>
229inline bool operator>(const EndianInt<T, DL1>& a, const EndianInt<T, DL2>& b)
230{
231 return b < a;
232}
233template <typename T, bool DL1, bool DL2>
234inline bool operator<=(const EndianInt<T, DL1>& a, const EndianInt<T, DL2>& b)
235{
236 return !(a > b);
237}
238template <typename T, bool DL1, bool DL2>
239inline bool operator>=(const EndianInt<T, DL1>& a, const EndianInt<T, DL2>& b)
240{
241 return !(a < b);
242}
244
245} // namespace types
246} // namespace m5
247#endif
std::byteswap for less than C++23
Compile-time endian identification.
endianness detection
Top level namespace of M5.
Definition base64.cpp:39
Definition byteswap.hpp:39
Endian-compliant integer type.
Definition types.hpp:45
const uint8_t * data() const
Gets the const pointer.
Definition types.hpp:165
uint8_t low() const
Gets the low byte (u8[sizeof(T)-1])
Definition types.hpp:160
constexpr EndianInt(EndianInt &&o) noexcept=default
default constructor
constexpr EndianInt()
default constructor
Definition types.hpp:51
size_t size() const
Gets size in uint8_t units.
Definition types.hpp:175
void set(const T v)
Set value with specified endianness.
Definition types.hpp:134
uint8_t * data()
Gets the pointer.
Definition types.hpp:170
T value
Raw value.
Definition types.hpp:180
constexpr EndianInt(const uint8_t b0, const uint8_t b1, const uint8_t b2, const uint8_t b3)
Stored in order of bytes (4-byte types)
Definition types.hpp:67
constexpr EndianInt(const uint8_t b0, const uint8_t b1)
Stored in order of bytes (2-byte types)
Definition types.hpp:62
uint8_t u8[sizeof(T)]
Raw value according to uint8_t.
Definition types.hpp:181
uint8_t high() const
Gets the high byte (u8[0])
Definition types.hpp:155
constexpr EndianInt(const EndianInt &)=default
default constructor
EndianInt(const T v)
from T
Definition types.hpp:56
constexpr EndianInt(const uint8_t b0, const uint8_t b1, const uint8_t b2, const uint8_t b3, const uint8_t b4, const uint8_t b5, const uint8_t b6, const uint8_t b7)
Stored in order of bytes (8-byte types)
Definition types.hpp:72
T get() const
Gets value with specified endianness.
Definition types.hpp:147