ReXGlue SDK
Toggle main menu visibility
Loading...
Searching...
No Matches
types.h
Go to the documentation of this file.
1
13
14
#pragma once
15
16
#include <atomic>
17
#include <bit>
18
#include <compare>
19
#include <concepts>
20
#include <cstddef>
21
#include <cstdint>
22
#include <cstring>
23
#include <string_view>
24
#include <type_traits>
25
26
#include <
rex/assert.h
>
27
#include <
rex/platform.h
>
28
29
static_assert
((std::endian::native == std::endian::big) ||
30
(std::endian::native == std::endian::little));
31
32
namespace
rex
{
33
34
using
u8 = uint8_t;
35
using
u16 = uint16_t;
36
using
u32 = uint32_t;
37
using
u64 = uint64_t;
38
39
using
i8 = int8_t;
40
using
i16 = int16_t;
41
using
i32 = int32_t;
42
using
i64 = int64_t;
43
44
using
f32 = float;
45
using
f64 = double;
46
47
static_assert
(
sizeof
(f32) == 4,
"f32 must be 4 bytes"
);
48
static_assert
(
sizeof
(f64) == 8,
"f64 must be 8 bytes"
);
49
51
template
<
class
T>
52
constexpr
T
byte_swap
(T value)
noexcept
{
53
static_assert
(
sizeof
(T) == 8 ||
sizeof
(T) == 4 ||
sizeof
(T) == 2 ||
sizeof
(T) == 1,
54
"byte_swap(T value): Type T has illegal size"
);
55
if
constexpr
(
sizeof
(T) == 1) {
56
return
value;
57
}
else
{
58
using
UintT =
59
std::conditional_t<
sizeof
(T) == 8, u64, std::conditional_t<
sizeof
(T) == 4, u32, u16>>;
60
return
std::bit_cast<T>(std::byteswap(std::bit_cast<UintT>(value)));
61
}
62
}
63
65
template
<
typename
T, std::endian E>
66
struct
EndianValue {
67
using
value_type = T;
68
69
EndianValue() =
default
;
70
71
EndianValue(
const
T& src) {
Set
(src); }
72
73
EndianValue(
const
EndianValue&) =
default
;
74
EndianValue& operator=(
const
EndianValue&) =
default
;
75
79
operator
T()
const
{
return
Get
(); }
80
82
void
Set
(
const
T& src) {
83
if
constexpr
(std::endian::native == E) {
84
value
= src;
85
}
else
{
86
value
=
rex::byte_swap
(src);
87
}
88
}
89
93
T
Get
()
const
{
94
if
constexpr
(std::endian::native == E) {
95
return
value
;
96
}
97
return
rex::byte_swap
(
value
);
98
}
99
105
T
Load
(std::memory_order order)
const
{
106
static_assert
(std::atomic_ref<T>::is_always_lock_free);
107
REX_ASSERT
(std::bit_cast<uintptr_t>(&
value
) % std::atomic_ref<T>::required_alignment == 0);
108
const
T raw = std::atomic_ref<T>(
const_cast<
T&
>
(
value
)).load(order);
109
if
constexpr
(std::endian::native == E) {
110
return
raw;
111
}
112
return
rex::byte_swap
(raw);
113
}
114
116
void
Store
(T src, std::memory_order order) {
117
static_assert
(std::atomic_ref<T>::is_always_lock_free);
118
REX_ASSERT
(std::bit_cast<uintptr_t>(&
value
) % std::atomic_ref<T>::required_alignment == 0);
119
if
constexpr
(std::endian::native != E) {
120
src =
rex::byte_swap
(src);
121
}
122
std::atomic_ref<T>(
value
).store(src, order);
123
}
124
132
bool
CompareExchange
(T& expected, T desired, std::memory_order order) {
133
static_assert
(std::atomic_ref<T>::is_always_lock_free);
134
REX_ASSERT
(std::bit_cast<uintptr_t>(&
value
) % std::atomic_ref<T>::required_alignment == 0);
135
T raw_expected = expected;
136
if
constexpr
(std::endian::native != E) {
137
raw_expected =
rex::byte_swap
(expected);
138
desired =
rex::byte_swap
(desired);
139
}
140
if
(std::atomic_ref<T>(
value
).compare_exchange_strong(raw_expected, desired, order)) {
141
return
true
;
142
}
143
if
constexpr
(std::endian::native != E) {
144
expected =
rex::byte_swap
(raw_expected);
145
}
else
{
146
expected = raw_expected;
147
}
148
return
false
;
149
}
150
151
EndianValue<T, E>
& operator+=(
int
a) {
152
*
this
= *
this
+ a;
153
return
*
this
;
154
}
155
156
EndianValue<T, E>& operator-=(
int
a) {
157
*
this
= *
this
- a;
158
return
*
this
;
159
}
160
161
EndianValue<T, E>& operator++() {
162
*
this
+= 1;
163
return
*
this
;
164
}
165
166
EndianValue<T, E> operator++(
int
) {
167
*
this
+= 1;
168
return
(*
this
- 1);
169
}
170
171
EndianValue<T, E>& operator--() {
172
*
this
-= 1;
173
return
*
this
;
174
}
175
176
EndianValue<T, E> operator--(
int
) {
177
*
this
-= 1;
178
return
(*
this
+ 1);
179
}
180
181
T
value
;
182
};
183
184
template
<
typename
T>
185
using
BE =
EndianValue<T, std::endian::big>
;
186
187
template
<
typename
T>
188
using
LE =
EndianValue<T, std::endian::little>
;
189
190
template
<
typename
T>
191
struct
IsBEType
: std::false_type {};
192
193
template
<
typename
T>
194
struct
IsBEType
<
rex
::BE<T>> : std::true_type {};
195
196
template
<
typename
T>
197
inline
constexpr
bool
is_be_type_v =
IsBEType<T>::value
;
198
199
using
GuestAddrT = u32;
200
using
host_addr_t = uintptr_t;
201
203
using
be_u8
= u8;
204
using
be_u16 = BE<u16>;
205
using
be_u32 = BE<u32>;
206
using
be_u64 = BE<u64>;
207
209
using
be_i8
= i8;
210
using
be_i16 = BE<i16>;
211
using
be_i32 = BE<i32>;
212
using
be_i64 = BE<i64>;
213
214
using
be_f32 = BE<f32>;
215
using
be_f64 = BE<f64>;
216
217
}
// namespace rex
218
219
using
u8 = rex::u8;
220
using
i8 = rex::i8;
221
using
u16 = rex::u16;
222
using
i16 = rex::i16;
223
using
u32 = rex::u32;
224
using
i32 = rex::i32;
225
using
u64 = rex::u64;
226
using
i64 = rex::i64;
227
using
f32 = rex::f32;
228
using
f64 = rex::f64;
229
230
using
be_u16 = rex::be_u16;
231
using
be_u32 = rex::be_u32;
232
using
be_u64 = rex::be_u64;
233
using
be_i16 = rex::be_i16;
234
using
be_i32 = rex::be_i32;
235
using
be_i64 = rex::be_i64;
236
using
be_f32 = rex::be_f32;
237
using
be_f64 = rex::be_f64;
238
239
namespace
rex
{
240
242
constexpr
size_t
operator
""
_KiB(
unsigned
long
long
int
x) {
243
return
1024ULL * x;
244
}
245
247
constexpr
size_t
operator
""
_MiB(
unsigned
long
long
int
x) {
248
return
1024_KiB * x;
249
}
250
252
constexpr
size_t
operator
""
_GiB(
unsigned
long
long
int
x) {
253
return
1024_MiB * x;
254
}
255
257
constexpr
size_t
operator
""
_TiB(
unsigned
long
long
int
x) {
258
return
1024_GiB * x;
259
}
260
262
constexpr
size_t
operator
""
_PiB(
unsigned
long
long
int
x) {
263
return
1024_TiB * x;
264
}
265
266
}
// namespace rex
assert.h
REX_ASSERT
#define REX_ASSERT(cond,...)
Definition
assert.h:84
rex
Definition
app.h:36
rex::be_i8
i8 be_i8
Definition
types.h:209
rex::byte_swap
constexpr T byte_swap(T value) noexcept
Definition
types.h:52
rex::be_u8
u8 be_u8
Definition
types.h:203
platform.h
Platform flags, packing macros and export markers.
rex::EndianValue
Definition
types.h:66
rex::EndianValue< T, std::endian::big >< u16 >::Get
T Get() const
Definition
types.h:93
rex::EndianValue::Set
void Set(const T &src)
Definition
types.h:82
rex::EndianValue< T, std::endian::big >::Store
void Store(T src, std::memory_order order)
Definition
types.h:116
rex::EndianValue< T, std::endian::big >< u16 >::value
T value
Definition
types.h:181
rex::EndianValue< T, std::endian::big >::Load
T Load(std::memory_order order) const
Definition
types.h:105
rex::EndianValue< T, std::endian::big >::CompareExchange
bool CompareExchange(T &expected, T desired, std::memory_order order)
Definition
types.h:132
rex::IsBEType
Definition
types.h:191
rex
types.h
Generated by
1.18.0