10 #ifndef ENDIAN_BUFFER_HPP
11 #define ENDIAN_BUFFER_HPP
14 #include <string_view>
15 #include "../core/span_type.hpp"
16 #include "../core/bitmath_func.hpp"
17 #include "../core/overflowsafe_type.hpp"
27 template <
typename Tcont =
typename std::vector<
byte>,
typename Titer =
typename std::back_insert_iterator<Tcont>>
36 EndianBufferWriter &operator <<(
const std::string &data) {
return *
this << std::string_view{ data }; }
37 EndianBufferWriter &operator <<(
const char *data) {
return *
this << std::string_view{ data }; }
39 EndianBufferWriter &operator <<(
bool data) {
return *this << static_cast<byte>(data ? 1 : 0); }
44 template <
typename... Targs>
47 this->
WriteTuple(data, std::index_sequence_for<Targs...>{});
51 template <
class T, std::enable_if_t<std::disjunction_v<std::negation<std::is_
class<T>>, std::is_base_of<StrongTypedefBase, T>>,
int> = 0>
54 if constexpr (std::is_enum_v<T>) {
55 this->
Write(
static_cast<std::underlying_type_t<const T>
>(data));
56 }
else if constexpr (std::is_base_of_v<StrongTypedefBase, T>) {
57 this->
Write(data.value);
64 template <
typename Tvalue,
typename Tbuf = std::vector<
byte>>
65 static Tbuf FromValue(
const Tvalue &data)
75 template<
class Ttuple,
size_t... Tindices>
76 void WriteTuple(
const Ttuple &values, std::index_sequence<Tindices...>) {
77 ((*this << std::get<Tindices>(values)), ...);
81 void Write(std::string_view value)
83 for (
auto c : value) {
86 this->buffer++ =
'\0';
93 static_assert(
sizeof(T) <= 8,
"Value can't be larger than 8 bytes");
95 if constexpr (
sizeof(T) > 1) {
96 this->buffer++ =
GB(value, 0, 8);
97 this->buffer++ =
GB(value, 8, 8);
98 if constexpr (
sizeof(T) > 2) {
99 this->buffer++ =
GB(value, 16, 8);
100 this->buffer++ =
GB(value, 24, 8);
102 if constexpr (
sizeof(T) > 4) {
103 this->buffer++ =
GB(value, 32, 8);
104 this->buffer++ =
GB(value, 40, 8);
105 this->buffer++ =
GB(value, 48, 8);
106 this->buffer++ =
GB(value, 56, 8);
109 this->buffer++ = value;
129 void rewind() { this->read_pos = 0; }
132 EndianBufferReader &operator >>(
bool &data) { data = this->Read<byte>() != 0;
return *
this; }
134 template <
typename T>
137 template <
typename... Targs>
140 this->
ReadTuple(data, std::index_sequence_for<Targs...>{});
144 template <
class T, std::enable_if_t<std::disjunction_v<std::negation<std::is_
class<T>>, std::is_base_of<StrongTypedefBase, T>>,
int> = 0>
147 if constexpr (std::is_enum_v<T>) {
148 data =
static_cast<T
>(this->Read<std::underlying_type_t<T>>());
149 }
else if constexpr (std::is_base_of_v<StrongTypedefBase, T>) {
150 data.value = this->
Read<decltype(data.value)>();
152 data = this->Read<T>();
157 template <
typename Tvalue>
168 template<
class Ttuple,
size_t... Tindices>
169 void ReadTuple(Ttuple &values, std::index_sequence<Tindices...>) {
170 ((*
this >> std::get<Tindices>(values)), ...);
177 while (this->read_pos < this->
buffer.size()) {
178 char ch = this->Read<char>();
179 if (ch ==
'\0')
break;
189 static_assert(!std::is_const_v<T>,
"Can't read into const variables");
190 static_assert(
sizeof(T) <= 8,
"Value can't be larger than 8 bytes");
192 if (
read_pos +
sizeof(T) > this->buffer.size())
return {};
194 T value =
static_cast<T
>(this->buffer[this->read_pos++]);
195 if constexpr (
sizeof(T) > 1) {
196 value +=
static_cast<T
>(this->buffer[this->read_pos++]) << 8;
198 if constexpr (
sizeof(T) > 2) {
199 value +=
static_cast<T
>(this->buffer[this->read_pos++]) << 16;
200 value +=
static_cast<T
>(this->buffer[this->read_pos++]) << 24;
202 if constexpr (
sizeof(T) > 4) {
203 value +=
static_cast<T
>(this->buffer[this->read_pos++]) << 32;
204 value +=
static_cast<T
>(this->buffer[this->read_pos++]) << 40;
205 value +=
static_cast<T
>(this->buffer[this->read_pos++]) << 48;
206 value +=
static_cast<T
>(this->buffer[this->read_pos++]) << 56;