Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
tpl_paged_value_codec.H
Go to the documentation of this file.
1/*
2 Aleph_w
3
4 Data structures & Algorithms
5 version 2.0.0b
6 https://github.com/lrleon/Aleph-w
7
8 This file is part of Aleph-w library
9
10 Copyright (c) 2002-2026 Leandro Rabindranath Leon
11
12 Permission is hereby granted, free of charge, to any person obtaining a copy
13 of this software and associated documentation files (the "Software"), to deal
14 in the Software without restriction, including without limitation the rights
15 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16 copies of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be included in all
20 copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
25 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
26 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 SOFTWARE.
29*/
30
42# ifndef TPL_PAGED_VALUE_CODEC_H
43# define TPL_PAGED_VALUE_CODEC_H
44
45# include <array>
46# include <bit>
47# include <concepts>
48# include <cstddef>
49# include <cstdint>
50# include <cstring>
51# include <limits>
52# include <string>
53# include <type_traits>
54
56
57namespace Aleph
58{
59 namespace detail
60 {
61 template <typename T>
63
64 template <typename Codec, typename Value>
65 concept Fixed_Paged_Value_Codec = requires(const Value & value,
66 unsigned char * out,
67 const unsigned char * in,
68 std::uint32_t crc)
69 {
70 { Codec::storage_id } -> std::convertible_to<std::uint32_t>;
71 { Codec::encoded_size } -> std::convertible_to<size_t>;
72 { Codec::encode(value, out) } -> std::same_as<void>;
73 { Codec::decode(in) } -> std::same_as<Value>;
74 { Codec::add_to_crc(crc, value) } -> std::same_as<std::uint32_t>;
75 };
76
77 [[nodiscard]] constexpr std::uint32_t mix_codec_id(
78 const std::uint32_t seed,
79 const std::uint32_t value) noexcept
80 {
81 return (seed ^ value) * 16777619u + 0x9E3779B9u;
82 }
83
84 template <typename UInt>
85 requires(std::is_unsigned_v<UInt>)
86 inline void encode_unsigned_le(UInt value, unsigned char * out) noexcept
87 {
88 for (size_t i = 0; i < sizeof(UInt); ++i)
89 out[i] = static_cast<unsigned char>((value >> (i * 8)) & 0xFFu);
90 }
91
92 template <typename UInt>
93 requires(std::is_unsigned_v<UInt>)
95 const unsigned char * in) noexcept
96 {
97 UInt value = 0;
98 for (size_t i = 0; i < sizeof(UInt); ++i)
99 value |= static_cast<UInt>(in[i]) << (i * 8);
100 return value;
101 }
102
103 template <typename T>
104 requires(std::is_integral_v<T> and sizeof(T) == 1)
106 {
107 static constexpr std::uint32_t storage_id =
108 0x11000000u | (std::is_signed_v<T> ? 1u : 0u);
109 static constexpr size_t encoded_size = 1;
110
111 static void encode(const T value, unsigned char * out) noexcept
112 {
113 out[0] = static_cast<unsigned char>(value);
114 }
115
116 [[nodiscard]] static T decode(const unsigned char * in) noexcept
117 {
118 if constexpr (std::is_same_v<T, bool>)
119 return in[0] != 0;
120 else
121 return static_cast<T>(in[0]);
122 }
123
124 [[nodiscard]] static std::uint32_t add_to_crc(
125 const std::uint32_t crc,
126 const T value) noexcept
127 {
128 unsigned char byte = 0;
129 encode(value, &byte);
130 return crc32_add_bytes(crc, &byte, 1);
131 }
132 };
133
134 template <typename T>
135 requires(std::is_integral_v<T> and sizeof(T) != 1)
136 struct Paged_Value_Codec<T>
137 {
138 using unsigned_type = std::make_unsigned_t<T>;
139
140 static constexpr std::uint32_t storage_id =
141 0x12000000u | (static_cast<std::uint32_t>(sizeof(T)) << 8)
142 | (std::is_signed_v<T> ? 1u : 0u);
143 static constexpr size_t encoded_size = sizeof(T);
144
145 static void encode(const T value, unsigned char * out) noexcept
146 {
147 unsigned_type bits = 0;
148 std::memcpy(&bits, &value, sizeof(T));
149 encode_unsigned_le(bits, out);
150 }
151
152 [[nodiscard]] static T decode(const unsigned char * in) noexcept
153 {
155 T value{};
156 std::memcpy(&value, &bits, sizeof(T));
157 return value;
158 }
159
160 [[nodiscard]] static std::uint32_t add_to_crc(
161 const std::uint32_t crc,
162 const T value) noexcept
163 {
164 std::array<unsigned char, encoded_size> bytes = {};
165 encode(value, bytes.data());
166 return crc32_add_bytes(crc, bytes.data(), bytes.size());
167 }
168 };
169
170 template <typename T>
171 requires std::is_enum_v<T>
172 struct Paged_Value_Codec<T>
173 {
174 using underlying_type = std::underlying_type_t<T>;
176
177 static constexpr std::uint32_t storage_id =
178 mix_codec_id(0x21000000u, underlying_codec::storage_id);
179 static constexpr size_t encoded_size = underlying_codec::encoded_size;
180
181 static void encode(const T value, unsigned char * out) noexcept
182 {
183 underlying_codec::encode(static_cast<underlying_type>(value), out);
184 }
185
186 [[nodiscard]] static T decode(const unsigned char * in) noexcept
187 {
188 return static_cast<T>(underlying_codec::decode(in));
189 }
190
191 [[nodiscard]] static std::uint32_t add_to_crc(
192 const std::uint32_t crc,
193 const T value) noexcept
194 {
195 return underlying_codec::add_to_crc(
196 crc, static_cast<underlying_type>(value));
197 }
198 };
199
200 template <typename T>
201 requires(std::is_floating_point_v<T> and std::numeric_limits<T>::is_iec559
202 and (sizeof(T) == 4 or sizeof(T) == 8))
203 struct Paged_Value_Codec<T>
204 {
206 std::conditional_t<sizeof(T) == 4, std::uint32_t, std::uint64_t>;
207
208 static constexpr std::uint32_t storage_id =
209 0x31000000u | static_cast<std::uint32_t>(sizeof(T));
210 static constexpr size_t encoded_size = sizeof(T);
211
212 static void encode(const T value, unsigned char * out) noexcept
213 {
214 const auto bits = std::bit_cast<unsigned_type>(value);
215 encode_unsigned_le(bits, out);
216 }
217
218 [[nodiscard]] static T decode(const unsigned char * in) noexcept
219 {
220 const auto bits = decode_unsigned_le<unsigned_type>(in);
221 return std::bit_cast<T>(bits);
222 }
223
224 [[nodiscard]] static std::uint32_t add_to_crc(
225 const std::uint32_t crc,
226 const T value) noexcept
227 {
228 std::array<unsigned char, encoded_size> bytes = {};
229 encode(value, bytes.data());
230 return crc32_add_bytes(crc, bytes.data(), bytes.size());
231 }
232 };
233
234 template <typename T, size_t N>
235 struct Paged_Value_Codec<std::array<T, N>>
236 {
237 using value_type = T;
239
240 static constexpr std::uint32_t storage_id =
241 mix_codec_id(mix_codec_id(0x41000000u, element_codec::storage_id),
242 static_cast<std::uint32_t>(N));
243 static constexpr size_t encoded_size = N * element_codec::encoded_size;
244
245 static void encode(const std::array<T, N> & value,
246 unsigned char * out) noexcept
247 {
248 for (size_t i = 0; i < N; ++i)
249 element_codec::encode(value[i],
250 out + i * element_codec::encoded_size);
251 }
252
253 [[nodiscard]] static std::array<T, N>
254 decode(const unsigned char * in) noexcept
255 {
256 std::array<T, N> value = {};
257 for (size_t i = 0; i < N; ++i)
258 value[i] = element_codec::decode(in + i * element_codec::encoded_size);
259 return value;
260 }
261
262 [[nodiscard]] static std::uint32_t add_to_crc(
263 std::uint32_t crc,
264 const std::array<T, N> & value) noexcept
265 {
266 for (size_t i = 0; i < N; ++i)
267 crc = element_codec::add_to_crc(crc, value[i]);
268 return crc;
269 }
270 };
271
272 template <size_t Capacity, typename SizeType = std::uint32_t>
273 requires(std::is_unsigned_v<SizeType>)
275 {
276 static_assert(Capacity > 0,
277 "Paged_Bounded_String_Codec requires Capacity > 0");
278
279 static constexpr std::uint32_t storage_id =
280 mix_codec_id(mix_codec_id(0x61000000u,
281 static_cast<std::uint32_t>(Capacity)),
282 static_cast<std::uint32_t>(sizeof(SizeType)));
283 static constexpr size_t encoded_size = sizeof(SizeType) + Capacity;
284
285 static void encode(const std::string & value, unsigned char * out)
286 {
287 ah_runtime_error_unless(value.size() <= Capacity)
288 << "Paged_Bounded_String_Codec<" << Capacity
289 << ">::encode(): string size " << value.size()
290 << " exceeds capacity " << Capacity;
291
292 encode_unsigned_le(static_cast<SizeType>(value.size()), out);
293 std::memset(out + sizeof(SizeType), 0, Capacity);
294 if (not value.empty())
295 std::memcpy(out + sizeof(SizeType), value.data(), value.size());
296 }
297
298 [[nodiscard]] static std::string decode(const unsigned char * in)
299 {
302 << "Paged_Bounded_String_Codec<" << Capacity
303 << ">::decode(): corrupted size " << size
304 << " exceeds capacity " << Capacity;
305
306 return std::string(reinterpret_cast<const char *>(in + sizeof(SizeType)),
307 static_cast<size_t>(size));
308 }
309
310 [[nodiscard]] static std::uint32_t add_to_crc(
311 const std::uint32_t crc,
312 const std::string & value)
313 {
314 std::array<unsigned char, encoded_size> bytes = {};
315 encode(value, bytes.data());
316 return crc32_add_bytes(crc, bytes.data(), bytes.size());
317 }
318 };
319 } // namespace detail
320} // namespace Aleph
321
322# endif // TPL_PAGED_VALUE_CODEC_H
#define ah_runtime_error_unless(C)
Throws std::runtime_error if condition does NOT hold.
Definition ah-errors.H:250
#define N
Definition fib.C:294
std::uint32_t crc32_add_bytes(std::uint32_t crc, const void *data, const size_t size) noexcept
constexpr std::uint32_t mix_codec_id(const std::uint32_t seed, const std::uint32_t value) noexcept
UInt decode_unsigned_le(const unsigned char *in) noexcept
void encode_unsigned_le(UInt value, unsigned char *out) noexcept
Main namespace for Aleph-w library functions.
Definition ah-arena.H:89
and
Check uniqueness with explicit hash + equality functors.
size_t size(Node *root) noexcept
Divide_Conquer_DP_Result< Cost > divide_and_conquer_partition_dp(const size_t groups, const size_t n, Transition_Cost_Fn transition_cost, const Cost inf=dp_optimization_detail::default_inf< Cost >())
Optimize partition DP using divide-and-conquer optimization.
std::decay_t< typename HeadC::Item_Type > T
Definition ah-zip.H:105
STL namespace.
static void encode(const std::string &value, unsigned char *out)
static std::string decode(const unsigned char *in)
static std::uint32_t add_to_crc(const std::uint32_t crc, const std::string &value)
static T decode(const unsigned char *in) noexcept
static std::uint32_t add_to_crc(const std::uint32_t crc, const T value) noexcept
std::underlying_type_t< T > underlying_type
static void encode(const T value, unsigned char *out) noexcept
static std::array< T, N > decode(const unsigned char *in) noexcept
static std::uint32_t add_to_crc(std::uint32_t crc, const std::array< T, N > &value) noexcept
static void encode(const std::array< T, N > &value, unsigned char *out) noexcept
ValueArg< size_t > seed
Definition testHash.C:48
Helpers for durable paged-tree files.