CommonLib
Toggle main menu visibility
Loading...
Searching...
No Matches
mem.inl
Go to the documentation of this file.
1
#
include
<
algorithm
>
2
#
include
<
array
>
3
#
include
<
string
>
4
#
include
<
type_traits
>
5
#
include
<
vector
>
6
7
#
if
defined
(
_MSC_VER
)
8
#
include
<
stdlib
.
h
>
9
#
endif
10
11
#
include
"ut/expr/expr.h"
12
#
include
"ut/expr/string_expr.h"
13
#
include
"ut/preprocessor.h"
14
15
namespace
hedgedev::csl::
mem
16
{
17
template
<
typename
T> requires (
std
::
is_integral_v
<
T
>)
18
inline
constexpr
T
align
(
T
in_address
,
T
in_alignment
)
19
{
20
return
(in_address + (in_alignment - 1)) & ~(in_alignment - 1);
21
}
22
23
inline
void
*
align
(
void
* in_address, uintptr_t in_alignment)
24
{
25
return
reinterpret_cast
<
void
*>(align<uintptr_t>(uintptr_t(in_address), in_alignment));
26
}
27
28
template
<
typename
T>
29
inline
T
read
(
void
* in_address)
30
{
31
return
*
reinterpret_cast
<T*>(in_address);
32
}
33
34
template
<
typename
T, size_t count>
35
inline
std::array<T, count>
read
(
void
* in_address)
36
{
37
std::array<T, count> result{};
38
39
for
(size_t i = 0; i < count; i++)
40
result[i] =
reinterpret_cast
<T*>(in_address)[i];
41
42
return
result;
43
}
44
45
template
<
typename
T>
46
inline
constexpr
T
byteswap
(T in_value)
47
{
48
if
constexpr
(
sizeof
(T) == 1)
49
{
50
return
in_value;
51
}
52
else
if
(std::is_constant_evaluated())
53
{
54
auto
bytes = std::bit_cast<std::array<uint8_t,
sizeof
(T)>>(in_value);
55
56
std::reverse(bytes.begin(), bytes.end());
57
58
return
std::bit_cast<T>(bytes);
59
}
60
else
if
constexpr
(
sizeof
(T) == 2 ||
sizeof
(T) == 4 ||
sizeof
(T) == 8)
61
{
62
ut::expr::inferred_size_t<
sizeof
(T)> buffer{};
63
64
memcpy(&buffer, &in_value,
sizeof
(T));
65
66
if
constexpr
(
sizeof
(T) == 2)
67
{
68
#
if
defined
(
_MSC_VER
)
69
buffer = _byteswap_ushort(buffer);
70
#
else
71
buffer = __builtin_bswap16(buffer);
72
#
endif
73
}
74
else
if
constexpr
(
sizeof
(T) == 4)
75
{
76
#
if
defined
(
_MSC_VER
)
77
buffer = _byteswap_ulong(buffer);
78
#
else
79
buffer = __builtin_bswap32(buffer);
80
#
endif
81
}
82
else
if
constexpr
(
sizeof
(T) == 8)
83
{
84
#
if
defined
(
_MSC_VER
)
85
buffer = _byteswap_uint64(buffer);
86
#
else
87
buffer = __builtin_bswap64(buffer);
88
#
endif
89
}
90
91
memcpy(&in_value, &buffer,
sizeof
(T));
92
}
93
else
94
{
95
auto
bytes =
reinterpret_cast
<uint8_t*>(&in_value);
96
97
std::reverse(bytes, bytes +
sizeof
(T));
98
}
99
100
return
in_value;
101
}
102
103
template
<
typename
T>
104
inline
constexpr
void
byteswap_inplace
(T& io_value)
105
{
106
io_value = byteswap(io_value);
107
}
108
109
template
<
typename
T>
110
inline
bool
write
(
void
* in_address,
const
T& in_data, size_t in_count)
111
{
112
if
(!in_address)
113
return
false
;
114
115
const
auto
length =
sizeof
(in_data) * in_count;
116
117
uint32_t old_protect_flags{};
118
119
ASSERT_RETURN_FALSE
(protect(in_address, length, get_protect_flags(page_protection::rw), &old_protect_flags));
120
121
for
(size_t i = 0; i < in_count; i++)
122
reinterpret_cast
<T*>(in_address)[i] = in_data;
123
124
ASSERT_RETURN_FALSE
(protect(in_address, length, old_protect_flags));
125
126
return
true
;
127
}
128
129
template
<
typename
T>
130
inline
bool
write
(
void
* in_address,
const
std::vector<T>& in_data)
131
{
132
if
(!in_address)
133
return
false
;
134
135
const
auto
length =
sizeof
(T) * in_data.size();
136
137
uint32_t old_protect_flags{};
138
139
ASSERT_RETURN_FALSE
(protect(in_address, length, get_protect_flags(page_protection::rw), &old_protect_flags));
140
ASSERT_RETURN_FALSE
(memcpy_s(in_address, length, in_data.data(), length) == 0);
141
ASSERT_RETURN_FALSE
(protect(in_address, length, old_protect_flags));
142
143
return
true
;
144
}
145
146
template
<ut::expr::any_string T>
147
inline
bool
write_string
(
void
* in_address,
const
T& in_str)
148
{
149
if
(!in_address)
150
return
false
;
151
152
return
write_string_fixed_length(in_address, in_str, ut::expr::inferred_string_view_t<T>(in_str).size());
153
}
154
155
template
<ut::expr::any_string T>
156
inline
bool
write_string_fixed_length
(
void
* in_address,
const
T& in_str, size_t in_length)
157
{
158
if
(!in_address)
159
return
false
;
160
161
using
str_char_t = ut::expr::get_char_type_t<T>;
162
163
auto
str_sv = ut::expr::inferred_string_view_t<T>(in_str);
164
165
auto
src_length = in_length;
166
auto
dst_length = src_length;
167
168
if
(!dst_length)
169
{
170
// Started at null terminator, abort.
171
if
(!*
reinterpret_cast
<str_char_t*>(in_address))
172
return
false
;
173
174
dst_length = ut::expr::inferred_string_view_t<T>(
reinterpret_cast
<str_char_t*>(in_address)).size() *
sizeof
(str_char_t);
175
176
if
(!dst_length)
177
return
false
;
178
179
src_length = str_sv.size() *
sizeof
(str_char_t);
180
181
if
(!src_length)
182
return
false
;
183
184
// Use the smallest length to fit
185
// within existing string boundaries.
186
src_length = std::min(src_length, dst_length);
187
}
188
189
uint32_t old_protect_flags{};
190
191
ASSERT_RETURN_FALSE
(protect(in_address, dst_length, get_protect_flags(page_protection::rw), &old_protect_flags));
192
ASSERT_RETURN_FALSE
(memcpy_s(in_address, dst_length, str_sv.data(), src_length) == 0);
193
memset(
reinterpret_cast
<
char
*>(uintptr_t(in_address) + src_length), 0,
sizeof
(str_char_t));
194
ASSERT_RETURN_FALSE
(protect(in_address, dst_length, old_protect_flags));
195
196
return
true
;
197
}
198
}
hedgedev::csl::mem
Definition
mem.h:169
hedgedev::csl::mem::write_string_fixed_length
bool write_string_fixed_length(void *in_address, const T &in_str, size_t in_length=0)
Definition
mem.inl:156
hedgedev::csl::mem::write
bool write(void *in_address, const std::vector< T > &in_data)
Definition
mem.inl:130
hedgedev::csl::mem::write_string
bool write_string(void *in_address, const T &in_str)
Definition
mem.inl:147
hedgedev::csl::mem::write
bool write(void *in_address, const T &in_data, size_t in_count=1)
Definition
mem.inl:110
hedgedev::csl::mem::byteswap
constexpr T byteswap(T in_value)
Definition
mem.inl:46
hedgedev::csl::mem::align
constexpr T align(T in_address, T in_alignment)
Definition
mem.inl:18
hedgedev::csl::mem::read
std::array< T, count > read(void *in_address)
Definition
mem.inl:35
hedgedev::csl::mem::align
void * align(void *in_address, uintptr_t in_alignment)
Definition
mem.inl:23
hedgedev::csl::mem::read
T read(void *in_address)
Definition
mem.inl:29
hedgedev::csl::mem::byteswap_inplace
constexpr void byteswap_inplace(T &io_value)
Definition
mem.inl:104
ASSERT_RETURN_FALSE
#define ASSERT_RETURN_FALSE(CONDITION)
Definition
preprocessor.h:33
include
mem
mem.inl
Generated by
1.18.0