Binary Serialize
Loading...
Searching...
No Matches
extract_append.hpp
Go to the documentation of this file.
1
29#ifndef EXTRACT_APPEND_HPP_INCLUDED
30#define EXTRACT_APPEND_HPP_INCLUDED
31
33
34#include <concepts> // std::unsigned_integral, std::integral
35#include <algorithm> // std::ranges:copy
36#include <bit> // std::endian, std::bit_cast
37#include <array>
38#include <cstddef> // std::byte, std::size_t
39#include <cstdint> // std::uint32_t, etc
40#include <type_traits> // std::is_same
41
42
43namespace chops {
44
45// Old static assertions, pre-concepts
46/*
47template <typename T>
48constexpr void assert_size() noexcept {
49 static_assert(sizeof(T) == 1u || sizeof(T) == 2u || sizeof(T) == 4u ||
50 sizeof(T) == 8u || sizeof(T) ==16u,
51 "Size for value extraction is not supported.");
52}
53template <typename T>
54constexpr bool is_arithmetic_or_byte() noexcept {
55 return std::is_arithmetic_v<T> || std::is_same_v<std::remove_cv_t<T>, std::byte>;
56}
57
58template <typename T>
59constexpr void assert_arithmetic_or_byte() noexcept {
60 static_assert(is_arithmetic_or_byte<T>(),
61 "Value extraction is only supported for arithmetic or std::byte types.");
62}
63*/
64
65// using C++ 20 concepts
66template <typename T>
67concept integral_or_byte = std::integral<T> || std::is_same_v<std::remove_cv_t<T>, std::byte>;
68
69// old endian detection code
70// inline bool detect_big_endian () noexcept {
71// const std::uint32_t tmp {0xDDCCBBAA};
72// return *(cast_ptr_to<std::byte>(&tmp) + 3) == static_cast<std::byte>(0xAA);
73//}
74// should be computed at global initialization time
75// const bool big_endian = detect_big_endian();
76
106template <std::endian BufEndian, integral_or_byte T>
107constexpr T extract_val(const std::byte* buf) noexcept {
108 auto value_representation = std::bit_cast<std::array<std::byte, sizeof(T)>>(T{});
109 std::ranges::copy (buf, buf + sizeof(T), value_representation.begin());
110 auto tmp_val = std::bit_cast<T>(value_representation);
111 if constexpr (BufEndian != std::endian::native && sizeof(T) != 1u) {
112 return chops::byteswap(tmp_val);
113 }
114 return tmp_val;
115}
116
139template <std::endian BufEndian, integral_or_byte T>
140constexpr std::size_t append_val(std::byte* buf, const T& val) noexcept {
141 T tmp_val {val};
142 if constexpr (BufEndian != std::endian::native && sizeof(T) != 1u) {
143 tmp_val = chops::byteswap(tmp_val);
144 }
145 auto value_representation = std::bit_cast<std::array<std::byte, sizeof(T)>>(tmp_val);
146 std::ranges::copy (value_representation, buf );
147 return sizeof(T);
148}
149
183template<std::unsigned_integral T>
184constexpr std::size_t append_var_int(std::byte* output, T val) {
185
186 std::size_t output_size = 0;
187
188 // While more than 7 bits of data are left, occupy the last output byte
189 // and set the next byte flag
190 while (val > 127) {
191
192 output[output_size] = std::bit_cast<std::byte>(static_cast<std::uint8_t>((static_cast<std::uint8_t> (val & 127)) | 128));
193 //Remove the seven bits we just wrote
194 val >>= 7;
195 ++output_size;
196 }
197 output[output_size++] = std::bit_cast<std::byte>(static_cast<std::uint8_t>(static_cast<std::uint8_t> (val) & 127));
198 return output_size;
199}
216template<std::unsigned_integral T>
217constexpr T extract_var_int(const std::byte* input, std::size_t input_size) {
218 T ret = 0;
219 for (std::size_t i = 0; i < input_size; ++i) {
220 ret |= (std::bit_cast<std::uint8_t>(input[i]) & 127) << (7 * i);
221 //If the next-byte flag is set
222 if(!(std::bit_cast<std::uint8_t>(input[i]) & 128)) {
223 break;
224 }
225 }
226 return ret;
227}
228
229} // end namespace
230
231#endif
232
This is an implementation of the C++ 23 std::byteswap function, for use in pre C++ 23 applications.
constexpr T byteswap(T value) noexcept
Perform an in-place byte swap on an integral type (if size of the type is greater than one).
Definition byteswap.hpp:41
Definition extract_append.hpp:67
constexpr T extract_val(const std::byte *buf) noexcept
Extract a value from a std::byte buffer into a fundamental integral or std::byte type in native endia...
Definition extract_append.hpp:107
constexpr std::size_t append_var_int(std::byte *output, T val)
Encode an unsigned integer into a variable length buffer of bytes using the MSB (most significant bit...
Definition extract_append.hpp:184
constexpr T extract_var_int(const std::byte *input, std::size_t input_size)
Given a buffer of std::bytes that hold a variable sized integer, decode them into an unsigned integer...
Definition extract_append.hpp:217
constexpr std::size_t append_val(std::byte *buf, const T &val) noexcept
Append an integral or std::byte value to a std::byte buffer, swapping into the specified endian order...
Definition extract_append.hpp:140