jaulib v1.3.6
Jau Support Library (C++, Java, ..)
Loading...
Searching...
No Matches
byte_util.hpp
Go to the documentation of this file.
1/*
2 * Author: Sven Gothel <sgothel@jausoft.com>
3 * Copyright (c) 2020-2024 Gothel Software e.K.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25#ifndef JAU_BYTE_UTIL_HPP_
26#define JAU_BYTE_UTIL_HPP_
27
28#include <cstring>
29#include <string>
30#include <cstdint>
31#include <type_traits>
32
33#include <jau/cpp_lang_util.hpp>
34#include <jau/cpp_pragma.hpp>
36
37#include <jau/int_types.hpp>
38
39namespace jau {
40
41 /** @defgroup ByteUtils Byte Utilities
42 * Byte utility functions and types for endian- and bit conversions,
43 * inclusive alignment handling and general get & put functionality.
44 *
45 * This category is also supporting \ref Integer.
46 *
47 * All \ref endian API entries are of `constexpr` and hence evaluated at compile time.<br>
48 * Therefore, if-branches and expressions are also of `constexpr` and optimized 'away' at compile time.<br>
49 * This includes the `cpu_to_<endian>(..)` and `<endian>_to_cpu(..)` etc utility functions.
50 *
51 * See \ref endian enum class regarding endian `constexpr` compile time determination.
52 *
53 * Aligned memory transfer from and to potentially unaligned memory
54 * is performed via put_uint16(), get_uint16() with all its explicit stdint types,
55 * as well as the generic template functions put_value() and get_value().
56 * The implementation uses \ref packed_t to resolve a potential memory alignment issue *free of costs*,
57 * see \ref packed_t_alignment_cast.
58 *
59 * @{
60 */
61
62 #if defined __has_builtin
63 #if __has_builtin(__builtin_bswap16)
64 #define __has_builtin_bswap16 1
65 #endif
66 #elif defined(__GNUC__) && __GNUC_PREREQ (4, 8)
67 #define __has_builtin_bswap16 1
68 #endif
69 #if defined __has_builtin
70 #if __has_builtin(__builtin_bswap32)
71 #define __has_builtin_bswap32 1
72 #endif
73 #elif defined(__GNUC__) && __GNUC_PREREQ (4, 8)
74 #define __has_builtin_bswap32 1
75 #endif
76 #if defined __has_builtin
77 #if __has_builtin(__builtin_bswap64)
78 #define __has_builtin_bswap64 1
79 #endif
80 #elif defined(__GNUC__) && __GNUC_PREREQ (4, 8)
81 #define __has_builtin_bswap64 1
82 #endif
83
84 // Remember: constexpr specifier used in a function or static data member (since C++17) declaration implies inline.
85
86 constexpr uint16_t bswap(uint16_t const source) noexcept {
87 #if defined __has_builtin_bswap16
88 return __builtin_bswap16(source);
89 #else
90 return (uint16_t) ( ( ( (source) >> 8 ) & 0xff ) |
91 ( ( (source) & 0xff) << 8 ) );
92 #endif
93 }
94
95 constexpr int16_t bswap(int16_t const source) noexcept {
96 #if defined __has_builtin_bswap64
97 return jau::bit_cast<int16_t>( __builtin_bswap16(jau::bit_cast<uint16_t>(source)) );
98 #else
99 return (int16_t) ( ( ( (source) >> 8 ) & 0xff ) |
100 ( ( (source) & 0xff) << 8 ) );
101 #endif
102 }
103
104 constexpr uint32_t bswap(uint32_t const source) noexcept {
105 #if defined __has_builtin_bswap32
106 return __builtin_bswap32(source);
107 #else
108 return ( ( source & 0xff000000U ) >> 24 ) |
109 ( ( source & 0x00ff0000U ) >> 8 ) |
110 ( ( source & 0x0000ff00U ) << 8 ) |
111 ( ( source & 0x000000ffU ) << 24 );
112 #endif
113 }
114
115 constexpr int32_t bswap(int32_t const source) noexcept {
116 #if defined __has_builtin_bswap64
117 return jau::bit_cast<int32_t>( __builtin_bswap32(jau::bit_cast<uint32_t>(source)) );
118 #else
119 return jau::bit_cast<int32_t>( ( ( source & 0xff000000U ) >> 24 ) |
120 ( ( source & 0x00ff0000U ) >> 8 ) |
121 ( ( source & 0x0000ff00U ) << 8 ) |
122 ( ( source & 0x000000ffU ) << 24 ) );
123 #endif
124 }
125
126 constexpr uint64_t bswap(uint64_t const & source) noexcept {
127 #if defined __has_builtin_bswap64
128 return __builtin_bswap64(source);
129 #else
130 return ( ( source & 0xff00000000000000ULL ) >> 56 ) |
131 ( ( source & 0x00ff000000000000ULL ) >> 40 ) |
132 ( ( source & 0x0000ff0000000000ULL ) >> 24 ) |
133 ( ( source & 0x000000ff00000000ULL ) >> 8 ) |
134 ( ( source & 0x00000000ff000000ULL ) << 8 ) |
135 ( ( source & 0x0000000000ff0000ULL ) << 24 ) |
136 ( ( source & 0x000000000000ff00ULL ) << 40 ) |
137 ( ( source & 0x00000000000000ffULL ) << 56 );
138 #endif
139 }
140
141 constexpr int64_t bswap(int64_t const & source) noexcept {
142 #if defined __has_builtin_bswap64
143 return jau::bit_cast<int64_t>( __builtin_bswap64(jau::bit_cast<uint64_t>(source)) );
144 #else
145 return jau::bit_cast<int64_t>( ( ( source & 0xff00000000000000ULL ) >> 56 ) |
146 ( ( source & 0x00ff000000000000ULL ) >> 40 ) |
147 ( ( source & 0x0000ff0000000000ULL ) >> 24 ) |
148 ( ( source & 0x000000ff00000000ULL ) >> 8 ) |
149 ( ( source & 0x00000000ff000000ULL ) << 8 ) |
150 ( ( source & 0x0000000000ff0000ULL ) << 24 ) |
151 ( ( source & 0x000000000000ff00ULL ) << 40 ) |
152 ( ( source & 0x00000000000000ffULL ) << 56 ) );
153 #endif
154 }
155
156 constexpr void bswap(uint8_t * sink, uint8_t const * source, nsize_t len) {
157 source += len - 1;
158 for (; len > 0; len--) {
159 *sink++ = *source--;
160 }
161 }
162
163 constexpr uint128dp_t bswap(uint128dp_t const & source) noexcept {
164 uint128dp_t dest;
165 bswap(dest.data, source.data, 16);
166 return dest;
167 }
168
169 constexpr uint192dp_t bswap(uint192dp_t const & source) noexcept {
170 uint192dp_t dest;
171 bswap(dest.data, source.data, 24);
172 return dest;
173 }
174
175 constexpr uint256dp_t bswap(uint256dp_t const & source) noexcept {
176 uint256dp_t dest;
177 bswap(dest.data, source.data, 32);
178 return dest;
179 }
180
181 inline char* cast_uint8_ptr_to_char(uint8_t* b) noexcept {
182 return reinterpret_cast<char*>(b);
183 }
184 inline const char* cast_uint8_ptr_to_char(const uint8_t* b) noexcept {
185 return reinterpret_cast<const char*>(b);
186 }
187
188 inline const uint8_t* cast_char_ptr_to_uint8(const char* s) noexcept {
189 return reinterpret_cast<const uint8_t*>(s);
190 }
191
192 /**
193 // *************************************************
194 // *************************************************
195 // *************************************************
196 */
197
200
201 namespace impl {
202 constexpr uint32_t get_host_order() noexcept {
203 if constexpr ( jau::has_builtin_bit_cast() ) {
204 constexpr uint8_t b[4] { 0x44, 0x43, 0x42, 0x41 }; // h->l: 41 42 43 44 = 'ABCD' hex ASCII code
206 } else {
207 // The pragma to stop multichar warning == error `-Werror=multichar` doesn't seem to work with GCC <= 10.2
208 // Hence we have to disable this specific warning via: `-Wno-multichar`
209 // until all our compiler support `__builtin_bit_cast(T, a)`
210 return 'ABCD'; // h->l: 41 42 43 44 = 'ABCD' hex ASCII code
211 }
212 }
213 }
214
215 /**
216 * Endian identifier, indicating endianess of all scalar types.
217 *
218 * Inspired by C++20 std::endian
219 *
220 * Corner case platforms currently not supported,
221 * i.e. unified endianess and mixed endianess.
222 *
223 * All endian API entries are of `constexpr` and hence evaluated at compile time.<br>
224 * Therefore, if-branches and expressions are also of `constexpr` and optimized 'away' at compile time.<br>
225 * This includes the `cpu_to_<endian>(..)` and `<endian>_to_cpu(..)` etc utility functions.
226 *
227 * On i386 platforms the host byte order is Least Significant Byte first (LSB) or Little-Endian,
228 * whereas the network byte order, as used on the Internet, is Most Significant Byte first (MSB) or Big-Endian.
229 * See #include <arpa/inet.h>
230 *
231 * Bluetooth is LSB or Little-Endian!
232 *
233 * See \ref lb_endian
234 */
235 enum class endian_t : uint32_t
236 {
237 /** Identifier for little endian. */
238 little = 0x41424344U, // h->l: 41 42 43 44 = 'ABCD' hex ASCII code
239
240 /** Identifier for big endian. */
241 big = 0x44434241U, // h->l: 44 43 42 41 = 'DCBA' hex ASCII code
242
243 /** Identifier for DEC PDP-11, aka `ENDIAN_LITTLE_WORD`. */
244 pdp = 0x43444142U, // h->l: 43 44 41 42 = 'CDAB' hex ASCII code
245
246 /** Identifier for Honeywell 316, aka `ENDIAN_BIG_WORD`. */
247 honeywell = 0x42414443U, // h->l: 42 41 44 43 = 'BADC' hex ASCII code
248
249 /** Undetermined endian */
250 undefined = 0x00000000U,
251
252 /** Identifier for native platform type, one of the above. */
254 };
255
257
258 /** Simplified reduced \ref endian type only covering little- and big-endian. See \ref endian for details. */
259 enum class lb_endian_t : uint32_t
260 {
261 /** Identifier for little endian, equivalent to endian::little. */
262 little = static_cast<uint32_t>( endian_t::little ),
263
264 /** Identifier for big endian, equivalent to endian::big. */
265 big = static_cast<uint32_t>( endian_t::big ),
266
267 /** Identifier for native platform type, one of the above. */
268 native = static_cast<uint32_t>( endian_t::native )
269 };
270
271 /**
272 * Return std::string representation of the given \ref endian.
273 * @param v the \ref endian value
274 * @return the std::string representation
275 */
276 std::string to_string(const endian_t v) noexcept;
277
278 /**
279 * Return std::string representation of the given \ref lb_endian.
280 * @param v the \ref lb_endian value
281 * @return the std::string representation
282 */
283 std::string to_string(const lb_endian_t v) noexcept;
284
285 constexpr lb_endian_t to_lb_endian(const endian_t v) noexcept {
286 switch(v) {
288 case endian_t::big: return lb_endian_t::big;
289 default: {
290 abort(); // never reached
291 }
292 }
293 }
294 constexpr endian_t to_endian(const lb_endian_t v) noexcept {
295 switch(v) {
297 case lb_endian_t::big: return endian_t::big;
298 default: {
299 abort(); // never reached
300 }
301 }
302 }
303
304 /**
305 * Evaluates `true` if the given \ref endian is defined,
306 * i.e. `little`, `big`, `pdp` or `honeywell`.
307 */
308 constexpr bool is_defined_endian(const endian_t &v) noexcept {
309 switch(v) {
310 case endian_t::little:
311 [[fallthrough]];
312 case endian_t::big:
313 [[fallthrough]];
314 case endian_t::pdp:
315 [[fallthrough]];
317 return true;
318 default:
319 return false;
320 }
321 }
322
323 /**
324 * Returns `true` if given `byte_order` equals endian::little, otherwise false.
325 */
326 constexpr bool is_little_endian(const endian_t byte_order) noexcept {
327 return endian_t::little == byte_order;
328 }
329
330 /**
331 * Returns `true` if given `byte_order` equals lb_endian::little, otherwise false.
332 */
333 constexpr bool is_little_endian(const lb_endian_t byte_order) noexcept {
334 return lb_endian_t::little == byte_order;
335 }
336
337 /**
338 * Evaluates `true` if platform is running in little \ref endian mode,
339 * i.e. `jau::endian::little == jau::endian::native`.
340 */
341 constexpr bool is_little_endian() noexcept {
343 }
344
345 /**
346 * Evaluates `true` if platform is running in big \ref endian mode,
347 * i.e. `jau::endian::big == jau::endian::native`.
348 */
349 constexpr bool is_big_endian() noexcept {
351 }
352
353 /**
354 * Evaluates `true` if platform is running in little or big \ref endian mode,
355 * i.e. `jau::endian::little == jau::endian::native || jau::endian::big == jau::endian::native`.
356 */
360
361 /**
362 * A little-endian type trait for convenience ..
363 * <p>
364 * Since all \ref endian definitions are of `constexpr`, code can simply use expressions of these
365 * for compile-time evaluation and optimization. A template `SFINAE` is not required.
366 * </p>
367 * @tparam Dummy_type just to make template `SFINAE` happy
368 */
369 template <typename Dummy_type> struct has_endian_little : std::integral_constant<bool, endian_t::little == endian_t::native> {};
370
371 /**
372 * Value access of little-endian type trait for convenience ..
373 * <p>
374 * Since all \ref endian definitions are of `constexpr`, code can simply use expressions of these
375 * for compile-time evaluation and optimization. A template `SFINAE` is not required.
376 * </p>
377 * @tparam Dummy_type just to make template `SFINAE` happy
378 */
379 template <typename Dummy_type> constexpr bool has_endian_little_v = has_endian_little<Dummy_type>::value;
380
381 /**
382 * A big-endian type trait for convenience ..
383 * <p>
384 * Since all \ref endian definitions are of `constexpr`, code can simply use expressions of these
385 * for compile-time evaluation and optimization. A template `SFINAE` is not required.
386 * </p>
387 * @tparam Dummy_type just to make template `SFINAE` happy
388 */
389 template <typename Dummy_type> struct has_endian_big : std::integral_constant<bool, endian_t::big == endian_t::native> {};
390
391 /**
392 * Value access of big-endian type trait for convenience ..
393 * <p>
394 * Since all \ref endian definitions are of `constexpr`, code can simply use expressions of these
395 * for compile-time evaluation and optimization. A template `SFINAE` is not required.
396 * </p>
397 * @tparam Dummy_type just to make template `SFINAE` happy
398 */
399 template <typename Dummy_type> constexpr bool has_endian_big_v = has_endian_big<Dummy_type>::value;
400
401 /**
402 // *************************************************
403 // *************************************************
404 // *************************************************
405 */
406
407 // one static_assert is sufficient for whole compilation unit
408 static_assert( is_defined_endian(endian_t::native) );
409 static_assert( is_little_or_big_endian() );
410
411 constexpr uint16_t be_to_cpu(uint16_t const n) noexcept {
412 if constexpr ( is_little_endian() ) {
413 return bswap(n);
414 } else if constexpr ( is_big_endian() ) {
415 return n;
416 } else {
417 return 0; // unreachable -> static_assert(..) above
418 }
419 }
420 constexpr uint16_t cpu_to_be(uint16_t const h) noexcept {
421 if constexpr ( is_little_endian() ) {
422 return bswap(h);
423 } else if constexpr ( is_big_endian() ) {
424 return h;
425 } else {
426 return 0; // unreachable -> static_assert(..) above
427 }
428 }
429 constexpr uint16_t le_to_cpu(uint16_t const l) noexcept {
430 if constexpr ( is_little_endian() ) {
431 return l;
432 } else if constexpr ( is_big_endian() ) {
433 return bswap(l);
434 } else {
435 return 0; // unreachable -> static_assert(..) above
436 }
437 }
438 constexpr uint16_t cpu_to_le(uint16_t const h) noexcept {
439 if constexpr ( is_little_endian() ) {
440 return h;
441 } else if constexpr ( is_big_endian() ) {
442 return bswap(h);
443 } else {
444 return 0; // unreachable -> static_assert(..) above
445 }
446 }
447
448 constexpr int16_t be_to_cpu(int16_t const n) noexcept {
449 if constexpr ( is_little_endian() ) {
450 return bswap(n);
451 } else if constexpr ( is_big_endian() ) {
452 return n;
453 } else {
454 return 0; // unreachable -> static_assert(..) above
455 }
456 }
457 constexpr int16_t cpu_to_be(int16_t const h) noexcept {
458 if constexpr ( is_little_endian() ) {
459 return bswap(h);
460 } else if constexpr ( is_big_endian() ) {
461 return h;
462 } else {
463 return 0; // unreachable -> static_assert(..) above
464 }
465 }
466 constexpr int16_t le_to_cpu(int16_t const l) noexcept {
467 if constexpr ( is_little_endian() ) {
468 return l;
469 } else if constexpr ( is_big_endian() ) {
470 return bswap(l);
471 } else {
472 return 0; // unreachable -> static_assert(..) above
473 }
474 }
475 constexpr int16_t cpu_to_le(int16_t const h) noexcept {
476 if constexpr ( is_little_endian() ) {
477 return h;
478 } else if constexpr ( is_big_endian() ) {
479 return bswap(h);
480 } else {
481 return 0; // unreachable -> static_assert(..) above
482 }
483 }
484
485 constexpr uint32_t be_to_cpu(uint32_t const n) noexcept {
486 if constexpr ( is_little_endian() ) {
487 return bswap(n);
488 } else if constexpr ( is_big_endian() ) {
489 return n;
490 } else {
491 return 0; // unreachable -> static_assert(..) above
492 }
493 }
494 constexpr uint32_t cpu_to_be(uint32_t const h) noexcept {
495 if constexpr ( is_little_endian() ) {
496 return bswap(h);
497 } else if constexpr ( is_big_endian() ) {
498 return h;
499 } else {
500 return 0; // unreachable -> static_assert(..) above
501 }
502 }
503 constexpr uint32_t le_to_cpu(uint32_t const l) noexcept {
504 if constexpr ( is_little_endian() ) {
505 return l;
506 } else if constexpr ( is_big_endian() ) {
507 return bswap(l);
508 } else {
509 return 0; // unreachable -> static_assert(..) above
510 }
511 }
512 constexpr uint32_t cpu_to_le(uint32_t const h) noexcept {
513 if constexpr ( is_little_endian() ) {
514 return h;
515 } else if constexpr ( is_big_endian() ) {
516 return bswap(h);
517 } else {
518 return 0; // unreachable -> static_assert(..) above
519 }
520 }
521
522 constexpr int32_t be_to_cpu(int32_t const n) noexcept {
523 if constexpr ( is_little_endian() ) {
524 return bswap(n);
525 } else if constexpr ( is_big_endian() ) {
526 return n;
527 } else {
528 return 0; // unreachable -> static_assert(..) above
529 }
530 }
531 constexpr int32_t cpu_to_be(int32_t const h) noexcept {
532 if constexpr ( is_little_endian() ) {
533 return bswap(h);
534 } else if constexpr ( is_big_endian() ) {
535 return h;
536 } else {
537 return 0; // unreachable -> static_assert(..) above
538 }
539 }
540 constexpr int32_t le_to_cpu(int32_t const l) noexcept {
541 if constexpr ( is_little_endian() ) {
542 return l;
543 } else if constexpr ( is_big_endian() ) {
544 return bswap(l);
545 } else {
546 return 0; // unreachable -> static_assert(..) above
547 }
548 }
549 constexpr int32_t cpu_to_le(int32_t const h) noexcept {
550 if constexpr ( is_little_endian() ) {
551 return h;
552 } else if constexpr ( is_big_endian() ) {
553 return bswap(h);
554 } else {
555 return 0; // unreachable -> static_assert(..) above
556 }
557 }
558
559 constexpr uint64_t be_to_cpu(uint64_t const & n) noexcept {
560 if constexpr ( is_little_endian() ) {
561 return bswap(n);
562 } else if constexpr ( is_big_endian() ) {
563 return n;
564 } else {
565 return 0; // unreachable -> static_assert(..) above
566 }
567 }
568 constexpr uint64_t cpu_to_be(uint64_t const & h) noexcept {
569 if constexpr ( is_little_endian() ) {
570 return bswap(h);
571 } else if constexpr ( is_big_endian() ) {
572 return h;
573 } else {
574 return 0; // unreachable -> static_assert(..) above
575 }
576 }
577 constexpr uint64_t le_to_cpu(uint64_t const & l) noexcept {
578 if constexpr ( is_little_endian() ) {
579 return l;
580 } else if constexpr ( is_big_endian() ) {
581 return bswap(l);
582 } else {
583 return 0; // unreachable -> static_assert(..) above
584 }
585 }
586 constexpr uint64_t cpu_to_le(uint64_t const & h) noexcept {
587 if constexpr ( is_little_endian() ) {
588 return h;
589 } else if constexpr ( is_big_endian() ) {
590 return bswap(h);
591 } else {
592 return 0; // unreachable -> static_assert(..) above
593 }
594 }
595
596 constexpr int64_t be_to_cpu(int64_t const & n) noexcept {
597 if constexpr ( is_little_endian() ) {
598 return bswap(n);
599 } else if constexpr ( is_big_endian() ) {
600 return n;
601 } else {
602 return 0; // unreachable -> static_assert(..) above
603 }
604 }
605 constexpr int64_t cpu_to_be(int64_t const & h) noexcept {
606 if constexpr ( is_little_endian() ) {
607 return bswap(h);
608 } else if constexpr ( is_big_endian() ) {
609 return h;
610 } else {
611 return 0; // unreachable -> static_assert(..) above
612 }
613 }
614 constexpr int64_t le_to_cpu(int64_t const & l) noexcept {
615 if constexpr ( is_little_endian() ) {
616 return l;
617 } else if constexpr ( is_big_endian() ) {
618 return bswap(l);
619 } else {
620 return 0; // unreachable -> static_assert(..) above
621 }
622 }
623 constexpr int64_t cpu_to_le(int64_t const & h) noexcept {
624 if constexpr ( is_little_endian() ) {
625 return h;
626 } else if constexpr ( is_big_endian() ) {
627 return bswap(h);
628 } else {
629 return 0; // unreachable -> static_assert(..) above
630 }
631 }
632
633 constexpr uint128dp_t be_to_cpu(uint128dp_t const & n) noexcept {
634 if constexpr ( is_little_endian() ) {
635 return bswap(n);
636 } else if constexpr ( is_big_endian() ) {
637 return n;
638 } else {
639 return {}; // unreachable -> static_assert(..) above
640 }
641 }
642 constexpr uint128dp_t cpu_to_be(uint128dp_t const & h) noexcept {
643 if constexpr ( is_little_endian() ) {
644 return bswap(h);
645 } else if constexpr ( is_big_endian() ) {
646 return h;
647 } else {
648 return {}; // unreachable -> static_assert(..) above
649 }
650 }
651 constexpr uint128dp_t le_to_cpu(uint128dp_t const & l) noexcept {
652 if constexpr ( is_little_endian() ) {
653 return l;
654 } else if constexpr ( is_big_endian() ) {
655 return bswap(l);
656 } else {
657 return {}; // unreachable -> static_assert(..) above
658 }
659 }
660 constexpr uint128dp_t cpu_to_le(uint128dp_t const & h) noexcept {
661 if constexpr ( is_little_endian() ) {
662 return h;
663 } else if constexpr ( is_big_endian() ) {
664 return bswap(h);
665 } else {
666 return {}; // unreachable -> static_assert(..) above
667 }
668 }
669
670 constexpr uint192dp_t be_to_cpu(uint192dp_t const & n) noexcept {
671 if constexpr ( is_little_endian() ) {
672 return bswap(n);
673 } else if constexpr ( is_big_endian() ) {
674 return n;
675 } else {
676 return {}; // unreachable -> static_assert(..) above
677 }
678 }
679 constexpr uint192dp_t cpu_to_be(uint192dp_t const & h) noexcept {
680 if constexpr ( is_little_endian() ) {
681 return bswap(h);
682 } else if constexpr ( is_big_endian() ) {
683 return h;
684 } else {
685 return {}; // unreachable -> static_assert(..) above
686 }
687 }
688 constexpr uint192dp_t le_to_cpu(uint192dp_t const & l) noexcept {
689 if constexpr ( is_little_endian() ) {
690 return l;
691 } else if constexpr ( is_big_endian() ) {
692 return bswap(l);
693 } else {
694 return {}; // unreachable -> static_assert(..) above
695 }
696 }
697 constexpr uint192dp_t cpu_to_le(uint192dp_t const & h) noexcept {
698 if constexpr ( is_little_endian() ) {
699 return h;
700 } else if constexpr ( is_big_endian() ) {
701 return bswap(h);
702 } else {
703 return {}; // unreachable -> static_assert(..) above
704 }
705 }
706
707 constexpr uint256dp_t be_to_cpu(uint256dp_t const & n) noexcept {
708 if constexpr ( is_little_endian() ) {
709 return bswap(n);
710 } else if constexpr ( is_big_endian() ) {
711 return n;
712 } else {
713 return {}; // unreachable -> static_assert(..) above
714 }
715 }
716 constexpr uint256dp_t cpu_to_be(uint256dp_t const & h) noexcept {
717 if constexpr ( is_little_endian() ) {
718 return bswap(h);
719 } else if constexpr ( is_big_endian() ) {
720 return h;
721 } else {
722 return {}; // unreachable -> static_assert(..) above
723 }
724 }
725 constexpr uint256dp_t le_to_cpu(uint256dp_t const & l) noexcept {
726 if constexpr ( is_little_endian() ) {
727 return l;
728 } else if constexpr ( is_big_endian() ) {
729 return bswap(l);
730 } else {
731 return {}; // unreachable -> static_assert(..) above
732 }
733 }
734 constexpr uint256dp_t cpu_to_le(uint256dp_t const & h) noexcept {
735 if constexpr ( is_little_endian() ) {
736 return h;
737 } else if constexpr ( is_big_endian() ) {
738 return bswap(h);
739 } else {
740 return {}; // unreachable -> static_assert(..) above
741 }
742
743 }
744
745 /**
746 // *************************************************
747 // *************************************************
748 // *************************************************
749 */
750
751 constexpr void put_uint8(uint8_t * buffer, const uint8_t v) noexcept
752 {
753 *pointer_cast<uint8_t *>( buffer ) = v;
754 }
755 constexpr uint8_t get_uint8(uint8_t const * buffer) noexcept
756 {
757 return *pointer_cast<uint8_t const *>( buffer );
758 }
759 constexpr int8_t get_int8(uint8_t const * buffer) noexcept
760 {
761 return *pointer_cast<int8_t const *>( buffer );
762 }
763
764 /**
765 * Return packed_t::store after converting it to from either lb_endian::little or lb_endian::big depending on given `byte_order`
766 * to lb_endian::native.
767 * @tparam T
768 * @param source
769 * @param byte_order
770 */
771 template<typename T>
772 constexpr T get_packed_value(const packed_t<T>* source, const lb_endian_t byte_order) noexcept {
773 return is_little_endian(byte_order) ? le_to_cpu(source->store) : be_to_cpu(source->store);
774 }
775
776 /**
777 * Put the given uint16_t value into the given byte address
778 * using \ref packed_t to resolve a potential memory alignment issue *free of costs*.
779 *
780 * @see \ref packed_t_alignment_cast
781 */
782 constexpr void put_uint16(uint8_t * buffer, const uint16_t v) noexcept
783 {
784 pointer_cast<packed_t<uint16_t>*>( buffer )->store = v;
785 }
786 /**
787 * Put the given uint16_t value into the given byte address
788 * using \ref packed_t to resolve a potential memory alignment issue *free of costs*.
789 *
790 * The value is converted from lb_endian::native to either lb_endian::little or lb_endian::big depending on given `byte_order`
791 * before it is stored in memory.
792 *
793 * @see \ref packed_t_alignment_cast
794 */
795 constexpr void put_uint16(uint8_t * buffer, const uint16_t v, const lb_endian_t byte_order) noexcept
796 {
797 pointer_cast<packed_t<uint16_t>*>( buffer )->store = is_little_endian(byte_order) ? cpu_to_le(v) : cpu_to_be(v);
798 }
799 /**
800 * Returns a uint16_t value from the given byte address
801 * using \ref packed_t to resolve a potential memory alignment issue *free of costs*.
802 *
803 * @see \ref packed_t_alignment_cast
804 */
805 constexpr uint16_t get_uint16(uint8_t const * buffer) noexcept
806 {
807 return pointer_cast<const packed_t<uint16_t>*>( buffer )->store;
808 }
809 /**
810 * Returns a uint16_t value from the given byte address
811 * using \ref packed_t to resolve a potential memory alignment issue *free of costs*.
812 *
813 * The value is converted from either lb_endian::little or lb_endian::big depending on given `byte_order`
814 * to lb_endian::native before it is returned to the caller.
815 *
816 * @see \ref packed_t_alignment_cast
817 */
818 constexpr uint16_t get_uint16(uint8_t const * buffer, const lb_endian_t byte_order) noexcept
819 {
820 return get_packed_value(pointer_cast<const packed_t<uint16_t>*>( buffer ), byte_order);
821 }
822
823 /**
824 * Put the given int16_t value into the given byte address
825 * using \ref packed_t to resolve a potential memory alignment issue *free of costs*.
826 *
827 * @see \ref packed_t_alignment_cast
828 */
829 constexpr void put_int16(uint8_t * buffer, const int16_t v) noexcept
830 {
831 pointer_cast<packed_t<int16_t>*>( buffer )->store = v;
832 }
833 /**
834 * Put the given uint16_t value into the given byte address
835 * using \ref packed_t to resolve a potential memory alignment issue *free of costs*.
836 *
837 * The value is converted from lb_endian::native to either lb_endian::little or lb_endian::big depending on given `byte_order`
838 * before it is stored in memory.
839 *
840 * @see \ref packed_t_alignment_cast
841 */
842 constexpr void put_int16(uint8_t * buffer, const int16_t v, const lb_endian_t byte_order) noexcept
843 {
844 pointer_cast<packed_t<int16_t>*>( buffer )->store = is_little_endian(byte_order) ? cpu_to_le(v) : cpu_to_be(v);
845 }
846 /**
847 * Returns a int16_t value from the given byte address
848 * using \ref packed_t to resolve a potential memory alignment issue *free of costs*.
849 *
850 * @see \ref packed_t_alignment_cast
851 */
852 constexpr int16_t get_int16(uint8_t const * buffer) noexcept
853 {
854 return pointer_cast<const packed_t<int16_t>*>( buffer )->store;
855 }
856 /**
857 * Returns a int16_t value from the given byte address
858 * using \ref packed_t to resolve a potential memory alignment issue *free of costs*.
859 *
860 * The value is converted from either lb_endian::little or lb_endian::big depending on given `byte_order`
861 * to lb_endian::native before it is returned to the caller.
862 *
863 * @see \ref packed_t_alignment_cast
864 */
865 constexpr int16_t get_int16(uint8_t const * buffer, const lb_endian_t byte_order) noexcept
866 {
867 return get_packed_value(pointer_cast<const packed_t<int16_t>*>( buffer ), byte_order);
868 }
869
870 /**
871 * See put_uint16() for reference.
872 * @see \ref packed_t_alignment_cast
873 */
874 constexpr void put_uint32(uint8_t * buffer, const uint32_t v) noexcept
875 {
876 pointer_cast<packed_t<uint32_t>*>( buffer )->store = v;
877 }
878 /**
879 * See put_uint16() for reference.
880 * @see \ref packed_t_alignment_cast
881 */
882 constexpr void put_uint32(uint8_t * buffer, const uint32_t v, const lb_endian_t byte_order) noexcept
883 {
884 pointer_cast<packed_t<uint32_t>*>( buffer )->store = is_little_endian(byte_order) ? cpu_to_le(v) : cpu_to_be(v);
885 }
886 /**
887 * See get_uint16() for reference.
888 * @see \ref packed_t_alignment_cast
889 */
890 constexpr uint32_t get_uint32(uint8_t const * buffer) noexcept
891 {
892 return pointer_cast<const packed_t<uint32_t>*>( buffer )->store;
893 }
894 /**
895 * See get_uint16() for reference.
896 * @see \ref packed_t_alignment_cast
897 */
898 constexpr uint32_t get_uint32(uint8_t const * buffer, const lb_endian_t byte_order) noexcept
899 {
900 return get_packed_value(pointer_cast<const packed_t<uint32_t>*>( buffer ), byte_order);
901 }
902
903 /**
904 * See put_int16() for reference.
905 * @see \ref packed_t_alignment_cast
906 */
907 constexpr void put_int32(uint8_t * buffer, const int32_t v) noexcept
908 {
909 pointer_cast<packed_t<int32_t>*>( buffer )->store = v;
910 }
911 /**
912 * See put_int16() for reference.
913 * @see \ref packed_t_alignment_cast
914 */
915 constexpr void put_int32(uint8_t * buffer, const int32_t v, const lb_endian_t byte_order) noexcept
916 {
917 pointer_cast<packed_t<int32_t>*>( buffer )->store = is_little_endian(byte_order) ? cpu_to_le(v) : cpu_to_be(v);
918 }
919 /**
920 * See get_int16() for reference.
921 * @see \ref packed_t_alignment_cast
922 */
923 constexpr int32_t get_int32(uint8_t const * buffer) noexcept
924 {
925 return pointer_cast<const packed_t<int32_t>*>( buffer )->store;
926 }
927 /**
928 * See get_int16() for reference.
929 * @see \ref packed_t_alignment_cast
930 */
931 constexpr int32_t get_int32(uint8_t const * buffer, const lb_endian_t byte_order) noexcept
932 {
933 return get_packed_value(pointer_cast<const packed_t<int32_t>*>( buffer ), byte_order);
934 }
935
936 /**
937 * See put_uint16() for reference.
938 * @see \ref packed_t_alignment_cast
939 */
940 constexpr void put_uint64(uint8_t * buffer, const uint64_t & v) noexcept
941 {
942 pointer_cast<packed_t<uint64_t>*>( buffer )->store = v;
943 }
944 /**
945 * See put_uint16() for reference.
946 * @see \ref packed_t_alignment_cast
947 */
948 constexpr void put_uint64(uint8_t * buffer, const uint64_t & v, const lb_endian_t byte_order) noexcept
949 {
950 pointer_cast<packed_t<uint64_t>*>( buffer )->store = is_little_endian(byte_order) ? cpu_to_le(v) : cpu_to_be(v);
951 }
952 /**
953 * See get_uint16() for reference.
954 * @see \ref packed_t_alignment_cast
955 */
956 constexpr uint64_t get_uint64(uint8_t const * buffer) noexcept
957 {
958 return pointer_cast<const packed_t<uint64_t>*>( buffer )->store;
959 }
960 /**
961 * See get_uint16() for reference.
962 * @see \ref packed_t_alignment_cast
963 */
964 constexpr uint64_t get_uint64(uint8_t const * buffer, const lb_endian_t byte_order) noexcept
965 {
966 return get_packed_value(pointer_cast<const packed_t<uint64_t>*>( buffer ), byte_order);
967 }
968
969 /**
970 * See put_int16() for reference.
971 * @see \ref packed_t_alignment_cast
972 */
973 constexpr void put_int64(uint8_t * buffer, const int64_t & v) noexcept
974 {
975 pointer_cast<packed_t<int64_t>*>( buffer )->store = v;
976 }
977 /**
978 * See put_int16() for reference.
979 * @see \ref packed_t_alignment_cast
980 */
981 constexpr void put_int64(uint8_t * buffer, const int64_t & v, const lb_endian_t byte_order) noexcept
982 {
983 pointer_cast<packed_t<int64_t>*>( buffer )->store = is_little_endian(byte_order) ? cpu_to_le(v) : cpu_to_be(v);
984 }
985 /**
986 * See get_int16() for reference.
987 * @see \ref packed_t_alignment_cast
988 */
989 constexpr int64_t get_int64(uint8_t const * buffer) noexcept
990 {
991 return pointer_cast<const packed_t<int64_t>*>( buffer )->store;
992 }
993 /**
994 * See get_int16() for reference.
995 * @see \ref packed_t_alignment_cast
996 */
997 constexpr int64_t get_int64(uint8_t const * buffer, const lb_endian_t byte_order) noexcept
998 {
999 return get_packed_value(pointer_cast<const packed_t<int64_t>*>( buffer ), byte_order);
1000 }
1001
1002 /**
1003 * See put_uint16() for reference.
1004 * @see \ref packed_t_alignment_cast
1005 */
1006 constexpr void put_uint128(uint8_t * buffer, const uint128dp_t & v) noexcept
1007 {
1008 pointer_cast<packed_t<uint128dp_t>*>( buffer )->store = v;
1009 }
1010 /**
1011 * See put_uint16() for reference.
1012 * @see \ref packed_t_alignment_cast
1013 */
1014 constexpr void put_uint128(uint8_t * buffer, const uint128dp_t & v, const lb_endian_t byte_order) noexcept
1015 {
1016 pointer_cast<packed_t<uint128dp_t>*>( buffer )->store = is_little_endian(byte_order) ? cpu_to_le(v) : cpu_to_be(v);
1017 }
1018 /**
1019 * See get_uint16() for reference.
1020 * @see \ref packed_t_alignment_cast
1021 */
1022 constexpr uint128dp_t get_uint128(uint8_t const * buffer) noexcept
1023 {
1024 return pointer_cast<const packed_t<uint128dp_t>*>( buffer )->store;
1025 }
1026 /**
1027 * See get_uint16() for reference.
1028 * @see \ref packed_t_alignment_cast
1029 */
1030 constexpr uint128dp_t get_uint128(uint8_t const * buffer, const lb_endian_t byte_order) noexcept
1031 {
1032 return get_packed_value(pointer_cast<const packed_t<uint128dp_t>*>( buffer ), byte_order);
1033 }
1034
1035 /**
1036 * See put_uint16() for reference.
1037 * @see \ref packed_t_alignment_cast
1038 */
1039 constexpr void put_uint192(uint8_t * buffer, const uint192dp_t & v) noexcept
1040 {
1041 pointer_cast<packed_t<uint192dp_t>*>( buffer )->store = v;
1042 }
1043 /**
1044 * See put_uint16() for reference.
1045 * @see \ref packed_t_alignment_cast
1046 */
1047 constexpr void put_uint192(uint8_t * buffer, const uint192dp_t & v, const lb_endian_t byte_order) noexcept
1048 {
1049 pointer_cast<packed_t<uint192dp_t>*>( buffer )->store = is_little_endian(byte_order) ? cpu_to_le(v) : cpu_to_be(v);
1050 }
1051 /**
1052 * See get_uint16() for reference.
1053 * @see \ref packed_t_alignment_cast
1054 */
1055 constexpr uint192dp_t get_uint192(uint8_t const * buffer) noexcept
1056 {
1057 return pointer_cast<const packed_t<uint192dp_t>*>( buffer )->store;
1058 }
1059 /**
1060 * See get_uint16() for reference.
1061 * @see \ref packed_t_alignment_cast
1062 */
1063 constexpr uint192dp_t get_uint192(uint8_t const * buffer, const lb_endian_t byte_order) noexcept
1064 {
1065 return get_packed_value(pointer_cast<const packed_t<uint192dp_t>*>( buffer ), byte_order);
1066 }
1067
1068 /**
1069 * See put_uint16() for reference.
1070 * @see \ref packed_t_alignment_cast
1071 */
1072 constexpr void put_uint256(uint8_t * buffer, const uint256dp_t & v) noexcept
1073 {
1074 pointer_cast<packed_t<uint256dp_t>*>( buffer )->store = v;
1075 }
1076 /**
1077 * See put_uint16() for reference.
1078 * @see \ref packed_t_alignment_cast
1079 */
1080 constexpr void put_uint256(uint8_t * buffer, const uint256dp_t & v, const lb_endian_t byte_order) noexcept
1081 {
1082 pointer_cast<packed_t<uint256dp_t>*>( buffer )->store = is_little_endian(byte_order) ? cpu_to_le(v) : cpu_to_be(v);
1083 }
1084 /**
1085 * See get_uint16() for reference.
1086 * @see \ref packed_t_alignment_cast
1087 */
1088 constexpr uint256dp_t get_uint256(uint8_t const * buffer) noexcept
1089 {
1090 return pointer_cast<const packed_t<uint256dp_t>*>( buffer )->store;
1091 }
1092 /**
1093 * See get_uint16() for reference.
1094 * @see \ref packed_t_alignment_cast
1095 */
1096 constexpr uint256dp_t get_uint256(uint8_t const * buffer, const lb_endian_t byte_order) noexcept
1097 {
1098 return get_packed_value(pointer_cast<const packed_t<uint256dp_t>*>( buffer ), byte_order);
1099 }
1100
1101 /**
1102 // *************************************************
1103 // *************************************************
1104 // *************************************************
1105 */
1106
1107 /**
1108 * Put the given T value into the given byte address
1109 * using \ref packed_t to resolve a potential memory alignment issue *free of costs*.
1110 *
1111 * @tparam T
1112 * @param buffer
1113 * @param v
1114 * @see \ref packed_t_alignment_cast
1115 */
1116 template<typename T>
1117 constexpr
1118 typename std::enable_if_t<
1119 std::is_standard_layout_v<T>,
1120 void>
1121 put_value(uint8_t * buffer, const T& v) noexcept
1122 {
1123 // reinterpret_cast<packed_t<T>*>( buffer )->store = v;
1124 pointer_cast<packed_t<T>*>( buffer )->store = v;
1125 }
1126
1127 /**
1128 * Put the given T value into the given byte address
1129 * using \ref packed_t to resolve a potential memory alignment issue *free of costs*.
1130 *
1131 * The value is converted from lb_endian::native to either lb_endian::little or lb_endian::big depending on given `byte_order`
1132 * before it is stored in memory.
1133 *
1134 * @tparam T
1135 * @param buffer
1136 * @param v
1137 * @param byte_order
1138 * @see \ref packed_t_alignment_cast
1139 */
1140 template<typename T>
1141 constexpr
1142 typename std::enable_if_t<
1143 std::is_standard_layout_v<T>,
1144 void>
1145 put_value(uint8_t * buffer, const T& v, const lb_endian_t byte_order) noexcept
1146 {
1147 pointer_cast<packed_t<T>*>( buffer )->store = is_little_endian(byte_order) ? cpu_to_le(v) : cpu_to_be(v);
1148 }
1149
1150 /**
1151 * Returns a T value from the given byte address
1152 * using \ref packed_t to resolve a potential memory alignment issue *free of costs*.
1153 *
1154 * @tparam T
1155 * @param buffer
1156 * @return
1157 * @see \ref packed_t_alignment_cast
1158 */
1159 template<typename T>
1160 constexpr
1161 typename std::enable_if_t<
1162 std::is_standard_layout_v<T>,
1163 T>
1164 get_value(uint8_t const * buffer) noexcept
1165 {
1166 return pointer_cast<const packed_t<T>*>( buffer )->store;
1167 }
1168
1169 /**
1170 * Returns a T value from the given byte address
1171 * using \ref packed_t to resolve a potential memory alignment issue *free of costs*.
1172 *
1173 * The value is converted from either lb_endian::little or lb_endian::big depending on given `byte_order`
1174 * to lb_endian::native before it is returned to the caller.
1175 *
1176 * @tparam T
1177 * @param buffer
1178 * @param byte_order
1179 * @return
1180 * @see \ref packed_t_alignment_cast
1181 */
1182 template<typename T>
1183 constexpr
1184 typename std::enable_if_t<
1185 std::is_standard_layout_v<T>,
1186 T>
1187 get_value(uint8_t const * buffer, const lb_endian_t byte_order) noexcept
1188 {
1189 return get_packed_value(pointer_cast<const packed_t<T>*>( buffer ), byte_order);
1190 }
1191
1192 /**@}*/
1193
1194} // namespace jau
1195
1196/** \example test_basictypeconv.cpp
1197 * This C++ unit test validates the jau::bswap and get/set value implementation
1198 */
1199
1200#endif /* JAU_BYTE_UTIL_HPP_ */
constexpr uint192dp_t get_uint192(uint8_t const *buffer) noexcept
See get_uint16() for reference.
constexpr bool has_endian_big_v
Value access of big-endian type trait for convenience .
constexpr uint128dp_t get_uint128(uint8_t const *buffer) noexcept
See get_uint16() for reference.
constexpr int64_t get_int64(uint8_t const *buffer) noexcept
See get_int16() for reference.
constexpr T get_packed_value(const packed_t< T > *source, const lb_endian_t byte_order) noexcept
Return packed_t::store after converting it to from either lb_endian::little or lb_endian::big dependi...
constexpr bool is_little_endian() noexcept
Evaluates true if platform is running in little endian mode, i.e.
constexpr bool is_big_endian() noexcept
Evaluates true if platform is running in big endian mode, i.e.
constexpr std::enable_if_t< std::is_standard_layout_v< T >, T > get_value(uint8_t const *buffer) noexcept
Returns a T value from the given byte address using packed_t to resolve a potential memory alignment ...
constexpr void put_uint256(uint8_t *buffer, const uint256dp_t &v) noexcept
See put_uint16() for reference.
constexpr bool is_defined_endian(const endian_t &v) noexcept
Evaluates true if the given endian is defined, i.e.
constexpr uint16_t get_uint16(uint8_t const *buffer) noexcept
Returns a uint16_t value from the given byte address using packed_t to resolve a potential memory ali...
constexpr uint16_t bswap(uint16_t const source) noexcept
Definition byte_util.hpp:86
constexpr bool is_little_or_big_endian() noexcept
Evaluates true if platform is running in little or big endian mode, i.e.
constexpr uint16_t cpu_to_be(uint16_t const h) noexcept
constexpr endian_t to_endian(const lb_endian_t v) noexcept
constexpr uint32_t get_uint32(uint8_t const *buffer) noexcept
See get_uint16() for reference.
char * cast_uint8_ptr_to_char(uint8_t *b) noexcept
constexpr void put_uint32(uint8_t *buffer, const uint32_t v) noexcept
See put_uint16() for reference.
constexpr int16_t get_int16(uint8_t const *buffer) noexcept
Returns a int16_t value from the given byte address using packed_t to resolve a potential memory alig...
endian_t
Endian identifier, indicating endianess of all scalar types.
constexpr int32_t get_int32(uint8_t const *buffer) noexcept
See get_int16() for reference.
constexpr uint256dp_t get_uint256(uint8_t const *buffer) noexcept
See get_uint16() for reference.
constexpr void put_uint192(uint8_t *buffer, const uint192dp_t &v) noexcept
See put_uint16() for reference.
constexpr bool has_endian_little_v
Value access of little-endian type trait for convenience .
constexpr void put_int16(uint8_t *buffer, const int16_t v) noexcept
Put the given int16_t value into the given byte address using packed_t to resolve a potential memory ...
constexpr uint16_t le_to_cpu(uint16_t const l) noexcept
constexpr void put_uint8(uint8_t *buffer, const uint8_t v) noexcept
lb_endian_t
Simplified reduced endian type only covering little- and big-endian.
std::string to_string(const endian_t v) noexcept
Return std::string representation of the given endian.
constexpr void put_uint64(uint8_t *buffer, const uint64_t &v) noexcept
See put_uint16() for reference.
constexpr void put_uint16(uint8_t *buffer, const uint16_t v) noexcept
Put the given uint16_t value into the given byte address using packed_t to resolve a potential memory...
constexpr uint16_t be_to_cpu(uint16_t const n) noexcept
constexpr void put_uint128(uint8_t *buffer, const uint128dp_t &v) noexcept
See put_uint16() for reference.
constexpr std::enable_if_t< std::is_standard_layout_v< T >, void > put_value(uint8_t *buffer, const T &v) noexcept
Put the given T value into the given byte address using packed_t to resolve a potential memory alignm...
constexpr lb_endian_t to_lb_endian(const endian_t v) noexcept
constexpr void put_int64(uint8_t *buffer, const int64_t &v) noexcept
See put_int16() for reference.
constexpr uint16_t cpu_to_le(uint16_t const h) noexcept
constexpr void put_int32(uint8_t *buffer, const int32_t v) noexcept
See put_int16() for reference.
constexpr uint64_t get_uint64(uint8_t const *buffer) noexcept
See get_uint16() for reference.
constexpr int8_t get_int8(uint8_t const *buffer) noexcept
constexpr uint8_t get_uint8(uint8_t const *buffer) noexcept
const uint8_t * cast_char_ptr_to_uint8(const char *s) noexcept
@ pdp
Identifier for DEC PDP-11, aka ENDIAN_LITTLE_WORD.
@ undefined
Undetermined endian.
@ native
Identifier for native platform type, one of the above.
@ little
Identifier for little endian.
@ honeywell
Identifier for Honeywell 316, aka ENDIAN_BIG_WORD.
@ big
Identifier for big endian.
@ little
Identifier for little endian, equivalent to endian::little.
@ big
Identifier for big endian, equivalent to endian::big.
constexpr std::enable_if_t< sizeof(Dest)==sizeof(Source) &&std::is_trivially_copyable_v< Dest > &&std::is_trivially_copyable_v< Source >, Dest > bit_cast(const Source &src) noexcept
C++20 bit_cast<>(arg) implementation for C++17.
#define PRAGMA_DISABLE_WARNING_PUSH
consteval_cxx20 bool has_builtin_bit_cast() noexcept
Query whether __builtin_bit_cast(Dest_type, arg) is available via __has_builtin(__builtin_bit_cast).
constexpr std::enable_if_t< sizeof(Dest)==sizeof(Source) &&std::is_pointer_v< Source > &&std::is_pointer_v< Dest >, Dest > pointer_cast(const Source &src) noexcept
A constexpr pointer cast implementation for C++17, inspired by C++20 bit_cast<>(arg).
#define PRAGMA_DISABLE_WARNING_MULTICHAR
#define PRAGMA_DISABLE_WARNING_POP
uint_fast32_t nsize_t
Natural 'size_t' alternative using uint_fast32_t as its natural sized type.
Definition int_types.hpp:55
constexpr uint32_t get_host_order() noexcept
__pack(...): Produces MSVC, clang and gcc compatible lead-in and -out macros.
Definition backtrace.hpp:32
A big-endian type trait for convenience .
A little-endian type trait for convenience .
Support aligned memory transfer from and to potentially unaligned memory.
A 128-bit packed uint8_t data array.
uint8_t data[16]
A 196-bit packed uint8_t data array.
uint8_t data[24]
A 256-bit packed uint8_t data array.
uint8_t data[32]