18 #include "serdes_fwd_declarations.h" 45 template <typename T_pointer, typename std::enable_if<std::is_pointer<T_pointer>::value,
int *>::type =
nullptr>
47 : buffer{array_init, max_elements},
58 template <
typename T_array,
size_t N>
60 : buffer{array_init, max_elements < N ? max_elements : N},
70 template <typename T_sized_pointer, typename std::enable_if<serdes::detail::is_sized_pointer<T_sized_pointer>::value,
int *>::type =
nullptr>
72 : buffer{array_init.
value, array_init.size},
79 void pad(
const size_t bits)
82 pad_assuming_no_prior_errors(bits);
90 align_assuming_no_prior_errors(bits);
102 template <
typename T,
size_t N>
103 void load(T (&value)[N],
size_t bits = detail::default_bitsize<T>::value)
105 constexpr
size_t size = N;
107 load(temp_arr, bits);
114 template <typename T, typename std::enable_if<!detail::is_format_modifier<T>::value,
int *>::type =
nullptr>
115 void load(T &value,
size_t bits = detail::default_bitsize<T>::value)
120 const size_t bits_touched =
bitcpy(value, buffer, bit_offset, bits);
121 bit_offset += bits_touched;
122 if (bits_touched < bits)
128 template <typename T, typename std::enable_if<std::is_rvalue_reference<T &&>::value && !std::is_base_of<packet_base, T>::value,
int *>::type =
nullptr>
129 void load(T &&value,
size_t bits = detail::default_bitsize<T>::value)
165 template <typename T, typename std::enable_if<!detail::is_format_modifier<T>::value,
int *>::type =
nullptr>
171 constexpr
size_t bits_per_element =
sizeof(T) * 8;
174 if (bits == bits_per_element && buffer.
element_size ==
sizeof(T) && bit_offset % bits_per_element == 0)
176 if (bit_capacity < bits_per_element)
181 const size_t max_bit_offset_minus_one_element = bit_capacity - bits_per_element;
182 const T *buffer_head = &
reinterpret_cast<const T *
>(buffer.
value)[bit_offset / bits_per_element];
183 for (
size_t i = 0; i < value.
max_size; i++)
185 if (bit_offset > max_bit_offset_minus_one_element)
190 const T &source_value = *buffer_head;
191 value.
value[i] = source_value;
200 for (
size_t i = 0; i < value.
max_size; i++)
202 const size_t bits_touched =
bitcpy(value.
value[i], buffer, bit_offset, bits);
203 bit_offset += bits_touched;
204 if (bits_touched < bits)
219 template <typename T, typename std::enable_if<std::is_base_of<packet_base, T>::value,
int *>::type =
nullptr>
225 for (
size_t i = 0; i < value.
max_size; i++)
227 value.
value[i].format(*
this);
237 template <
typename T>
248 template <typename T, typename T2, typename std::enable_if<!detail::is_format_modifier<T>::value,
int *>::type =
nullptr>
254 size_t array_size =
static_cast<size_t>(value.
size);
260 const size_t total_bits = array_size *
sizeof(T) * 8;
262 if (
sizeof(T) == 1 && bits == 8 && buffer.
element_size == 1 && (bit_offset & 7u) == 0u && bit_capacity - bit_offset >= total_bits)
264 memcpy(&value.
value[0], &reinterpret_cast<uint8_t *>(buffer.
value)[bit_offset >> 3], array_size);
265 bit_offset += total_bits;
268 for (
size_t i = 0; i < array_size; i++)
270 const size_t bits_touched =
bitcpy(value.
value[i], buffer, bit_offset, bits);
271 bit_offset += bits_touched;
272 if (bits_touched < bits)
284 template <typename T, typename T2, typename std::enable_if<std::is_base_of<packet_base, T>::value,
int *>::type =
nullptr>
290 size_t array_size =
static_cast<size_t>(value.
size);
296 for (
size_t i = 0; i < array_size; i++)
298 value.
value[i].format(*
this);
308 template <
typename T,
typename T2>
317 template <
typename ST>
323 pad_assuming_no_prior_errors(padding.
value);
329 template <
typename ST>
335 align_assuming_no_prior_errors(alignment.
value);
342 template <
typename T,
typename ST>
345 load(value.value, value.bits);
352 template <
typename T,
typename ST>
383 template <typename T, typename std::enable_if<!detail::is_format_modifier<T>::value,
int *>::type =
nullptr>
384 void store(
const T &value,
size_t bits = detail::default_bitsize<T>::value)
389 const size_t bits_touched =
bitcpy(buffer, value, bit_offset, bits);
390 bit_offset += bits_touched;
391 if (bits_touched < bits)
400 template <
typename T,
size_t N>
401 void store(
const T (&value)[N],
size_t bits = detail::default_bitsize<T>::value)
411 template <
typename T,
size_t N>
412 void store(
const T(&&value)[N],
size_t bits = detail::default_bitsize<T>::value)
421 template <typename T, typename std::enable_if<!detail::is_format_modifier<T>::value,
int *>::type =
nullptr>
427 constexpr
size_t bits_per_element =
sizeof(T) * 8;
429 if (bits == bits_per_element && buffer.
element_size ==
sizeof(T) && bit_offset % bits_per_element == 0)
431 if (bit_capacity < bits_per_element)
436 const size_t max_bit_offset_minus_one_element = bit_capacity - bits_per_element;
437 T *buffer_head = &
reinterpret_cast<T *
>(buffer.
value)[bit_offset / bits_per_element];
438 for (
size_t i = 0; i < value.
max_size; i++)
440 if (bit_offset > max_bit_offset_minus_one_element)
445 const T &source_value = value.
value[i];
446 *buffer_head = source_value;
455 for (
size_t i = 0; i < value.
max_size; i++)
457 const size_t bits_touched =
bitcpy(buffer, value.
value[i], bit_offset, bits);
458 bit_offset += bits_touched;
459 if (bits_touched < bits)
474 template <typename T, typename std::enable_if<std::is_base_of<packet_base, T>::value,
int *>::type =
nullptr>
480 for (
size_t i = 0; i < value.
max_size; i++)
482 value.
value[i].format(*
this);
492 template <
typename T>
503 template <typename T, typename T2, typename std::enable_if<!detail::is_format_modifier<T>::value,
int *>::type =
nullptr>
509 size_t array_size =
static_cast<size_t>(value.
size);
515 const size_t total_bits = array_size *
sizeof(T) * 8;
517 if (
sizeof(T) == 1 && bits == 8 && buffer.
element_size == 1 && (bit_offset & 7u) == 0u && bit_capacity - bit_offset >= total_bits)
519 memcpy(&reinterpret_cast<uint8_t *>(buffer.
value)[bit_offset >> 3], &value.
value[0], array_size);
520 bit_offset += total_bits;
523 for (
size_t i = 0; i < array_size; i++)
525 const size_t bits_touched =
bitcpy(buffer, value.
value[i], bit_offset, bits);
526 bit_offset += bits_touched;
527 if (bits_touched < bits)
539 template <typename T, typename T2, typename std::enable_if<std::is_base_of<packet_base, T>::value,
int *>::type =
nullptr>
545 size_t array_size =
static_cast<size_t>(value.
size);
551 for (
size_t i = 0; i < array_size; i++)
553 value.
value[i].format(*
this);
563 template <
typename T,
typename T2>
594 template <
typename ST>
600 pad_assuming_no_prior_errors(padding.
value);
606 template <
typename ST>
619 template <
typename T,
typename ST>
622 store(value.value, value.bits);
629 template <
typename T,
typename ST>
660 template <
typename T>
663 load(std::forward<T>(x));
671 template <
typename T>
674 store(std::forward<T>(x));
686 template <
typename T>
687 void add(T &&x,
size_t bits)
690 load(std::forward<T>(x), bits);
692 store(std::forward<T>(x), bits);
699 template <
typename T,
size_t N>
700 void add(T (&x)[N],
size_t bits)
703 for (
size_t i = 0; i < N; i++)
706 for (
size_t i = 0; i < N; i++)
713 template <
typename T>
717 load(std::forward<T>(x));
719 store(std::forward<T>(x));
725 template <
typename T,
size_t N>
729 for (
size_t i = 0; i < N; i++)
732 for (
size_t i = 0; i < N; i++)
741 template <
typename T>
742 void add(T &value,
const std::function<
bool()> &validation)
759 template <
typename T>
760 void add(T &&value, std::function<
bool()> &&validation)
762 add(value, validation);
769 #if (defined(__GNUC__) && !defined(__clang__)) 770 #pragma GCC diagnostic push 771 #pragma GCC diagnostic ignored "-Weffc++" 773 template <
typename T>
780 add(std::forward<T>(value));
783 #if (defined(__GNUC__) && !defined(__clang__)) 784 #pragma GCC diagnostic pop 790 inline void pad_assuming_no_prior_errors(
const size_t bits)
792 const size_t next_bit_offset = bit_offset + bits;
793 if (next_bit_offset > bit_capacity)
798 bit_offset = next_bit_offset;
803 inline void align_assuming_no_prior_errors(
size_t bits)
805 const size_t alignment = bit_offset % bits;
808 const size_t next_bit_offset = bit_offset + bits - alignment;
809 if (next_bit_offset > bit_capacity)
814 bit_offset = next_bit_offset;
819 inline void ensure_load()
830 inline void ensure_store()
841 template <
typename T_array,
size_t N>
844 if (N < max_elements)
851 template <typename T_pointer, typename std::enable_if<std::is_pointer<T_pointer>::value,
int *>::type>
859 template <typename T_sized_pointer, typename std::enable_if<serdes::detail::is_sized_pointer<T_sized_pointer>::value,
int *>::type>
866 template <
typename T_array,
size_t N>
869 if (N < max_elements)
875 template <typename T_pointer, typename std::enable_if<std::is_pointer<T_pointer>::value,
int *>::type>
882 template <typename T_sized_pointer, typename std::enable_if<serdes::detail::is_sized_pointer<T_sized_pointer>::value,
int *>::type>
889 template <
typename T>
892 return store(std::forward<T>(value));
894 template <
typename T>
897 return load(std::forward<T>(value));
const size_t bit_capacity
buffer.bit_capacity() value
Definition: serdes.h:30
tried to loading data from a serial buffer into a temperary rvalue (causes the serdes process to abor...
void load(T(&value)[N], size_t bits=detail::default_bitsize< T >::value)
[[deserialize]] loads from serial buffer into the passed array of values
Definition: serdes.h:103
specifies a number of bits to be used to pad (add to) the current bit offset
Definition: serdes_format_modifiers.h:35
const size_t max_size
maximum size of the array (used for bounds checking)
Definition: serdes_format_modifiers.h:139
void store(const formatter &value)
[[serialize]] stores a formatter reference into a serial buffer
Definition: serdes.h:571
not yet configured for storing/loading
packet & operator+(T &&value)
adds a field to the serial format for both serialization and deserialization (same as packet...
Definition: serdes.h:778
void align(size_t bits)
aligns (increases) the bit offset to a multiple of the specified bits
Definition: serdes.h:87
packet & operator>>(T &&x)
[[deserialize]] loads serial data into the passed value (same as load)
Definition: serdes.h:661
mode_e mode
the serdes mode (LOADING, STORING, or UNSPECIFIED)
Definition: serdes.h:28
specifies a number of bits to be used to align the bit offset as a multiple of
Definition: serdes_format_modifiers.h:18
void load(const serdes::pad< ST > padding)
[[deserialize, pad]] applies a padding step to the load process
Definition: serdes.h:318
a fields validation check failed (causes the serdes process to abort)
void reset() noexcept
resets the bit offset to 0 and the status to NO_ERROR
Definition: serdes.h:33
serdes::status_t store(T_array(&target_buffer)[N], size_t max_elements=N, size_t bit_offset=0)
[[serialize]] stores data into the target "sized" serial array according to the format() process ...
status_e
error status of serialization/deserialization process
Definition: serdes_errors.h:14
a serialization/deserialization helper class, with load, store, and stream operators ...
Definition: serdes.h:24
void store(const array< T, T2 > &value)
[[serialize]] stores an array<packet_base, T2> reference into a serial buffer
Definition: serdes.h:540
const ST & value
bit pad reference value
Definition: serdes_format_modifiers.h:38
CppSerdes library namespace.
Definition: bitcpy_common.h:69
void load(bitpack< T, ST > &&value)
[[deserialize]] loads from serial buffer into a bitpack<T, ST> rvalue
Definition: serdes.h:343
void add(T &&x)
adds a referenced field to the serial format for both serialization and deserialization ...
Definition: serdes.h:714
void store(const array< T, T2 > &value, size_t bits=detail::default_bitsize< T >::value)
[[serialize]] stores an array<T1, T2> reference into a serial buffer
Definition: serdes.h:504
void load(array< T, T2 > &value, size_t bits=detail::default_bitsize< T >::value)
[[deserialize]] loads from serial buffer into a array<T1, T2> reference
Definition: serdes.h:249
void store(const delimited_array< T > &value)
[[serialize]] stores a delimited_array<packet_base> reference into a serial buffer ...
Definition: serdes.h:475
void add(T &&x, size_t bits)
adds a referenced field to the serial format for both serialization and deserialization ...
Definition: serdes.h:687
void store(const bitpack< T, ST > &&value)
[[serialize]] stores a bitpack<T, ST> rvalue into a serial buffer
Definition: serdes.h:620
void store(const serdes::align< ST > alignment)
[[serialize, align]] applies an alignment step to the store process
Definition: serdes.h:607
void store(const bitpack< T, ST > &value)
[[serialize]] stores a bitpack<T, ST> reference into a serial buffer
Definition: serdes.h:630
void store(const packet_base &value)
[[serialize]] stores a packet_base reference into a serial buffer
Definition: serdes.h:637
inheritable base class to allow format recording and application with no additional memory storage (e...
Definition: serdes_fwd_declarations.h:42
void store(const T &value, size_t bits=detail::default_bitsize< T >::value)
[[serialize]] stores a value reference into a serial buffer
Definition: serdes.h:384
mode_e
the serdes mode of operation
Definition: serdes_errors.h:82
serdes::status_t operator>>(T &&value)
[[serialize]] stores the packet_base object into the passed serial data (same as store) ...
Defines string literals for fixed sized types, useful for serdes definitions. For example: Writting "...
packet & operator<<(T &&x)
[[serialize]] stores the passed value into the serial data (same as store)
Definition: serdes.h:672
during serialization/deserialization the serial array boundary was reached (causes the serdes process...
packet(T_array(&array_init)[N], size_t max_elements=~size_t(0), size_t b_offset=0, mode_e m=mode_e::UNSPECIFIED)
Construct a new packet object from an c style array pointer.
Definition: serdes.h:59
void load(const serdes::align< ST > alignment)
[[deserialize, align]] applies an alignment step to the load process
Definition: serdes.h:330
void add(T &&value, std::function< bool()> &&validation)
adds a referenced field to the serial format for both serialization and deserialization along with a ...
Definition: serdes.h:760
packet(T_pointer array_init, size_t max_elements=~size_t(0), size_t b_offset=0, mode_e m=mode_e::UNSPECIFIED)
Construct a new packet object from an c style array pointer.
Definition: serdes.h:46
void load(formatter &&value)
[[deserialize]] loads from serial buffer into a formatter rvalue
Definition: serdes.h:156
void load(bitpack< T, ST > &value)
[[deserialize]] loads from serial buffer into a bitpack<T, ST> reference
Definition: serdes.h:353
a container for dynamically sized arrays with their ending marked by a reserved delimiter value ...
Definition: serdes_format_modifiers.h:130
serdes::sized_pointer< void > buffer
underlying buffer to serialize/deserialize to/from
Definition: serdes.h:26
the serdes::array object's size exceeded the maximum size of the array when evaluated (causes the ser...
void load(delimited_array< T > &value)
[[deserialize]] loads from serial buffer into a delimited_array<packet_base> reference ...
Definition: serdes.h:220
void add(T &value, const std::function< bool()> &validation)
adds a referenced field to the serial format for both serialization and deserialization along with a ...
Definition: serdes.h:742
size_t bit_offset
current bit offset in the serdes process
Definition: serdes.h:27
void store(const array< T, T2 > &&value)
[[serialize]] stores an array<T, T2> rvalue into a serial buffer
Definition: serdes.h:564
void load(packet_base &value)
[[deserialize]] loads from serial buffer into a packet_base reference
Definition: serdes.h:360
status returned after any serialization/deserialization process
Definition: serdes_errors.h:72
void load(array< T, T2 > &&value)
[[deserialize]] loads from serial buffer into a array<T, T2> forwarding reference ...
Definition: serdes.h:309
Includes all the bitcpy definitions for serialization and deserialization.
const size_t max_size
maximum size of the array (used for bounds checking)
Definition: serdes_format_modifiers.h:96
status_e status
the current error status of the serdes process
Definition: serdes.h:29
void store(const T(&&value)[N], size_t bits=detail::default_bitsize< T >::value)
[[serialize]] stores a raw array rvalue into a serial buffer
Definition: serdes.h:412
a pure_virtual_formatter (a.k.a "serdes::formatter(nullptr)") was used but not overriden (causes the ...
const T & delimiter
reference to a reserved delimiter value marking the end of the array
Definition: serdes_format_modifiers.h:136
packet(T_sized_pointer array_init, size_t b_offset=0, mode_e m=mode_e::UNSPECIFIED)
Construct a new packet object from an sized_pointer array for size safety.
Definition: serdes.h:71
void load(array< T, T2 > &value)
[[deserialize]] loads from serial buffer into a array<packet_base, T2> reference
Definition: serdes.h:285
void load(delimited_array< T > &&value)
[[deserialize]] loads from serial buffer into a delimited_array<T> reference
Definition: serdes.h:238
size_t bit_capacity() const noexcept
returns the number of bits in the array
Definition: bitcpy_sized_pointer.h:76
(serializing) storing variables into serial data
Defines error and status types: status_e, status_t, mode_e, status2str(status_e)
const uint_fast8_t element_size
Number of bytes per element of the original array type, same as sizeof(T_original) ...
Definition: bitcpy_sized_pointer.h:57
T * value
pointer to the head of the array
Definition: serdes_format_modifiers.h:133
const ST & size
a reference to a value that contains the dynamic size of the array
Definition: serdes_format_modifiers.h:93
CONSTEXPR_ABOVE_CPP11 size_t bitcpy(T_val &dest, const T_array *const source, const size_t bit_offset=0, const size_t bits=detail::default_bitsize< T_val >::value) noexcept
[[deserialize, uint destination]] copies the specified number of bits from an array into a value ...
Definition: bitcpy_from_array.h:29
a container for fixed or dynamically sized arrays, with an upper bounds limit for safety ...
Definition: serdes_format_modifiers.h:87
the specified delimiter in a delimited_array object was not found before the end of the array (causes...
void load(delimited_array< T > &value, size_t bits=detail::default_bitsize< T >::value)
[[deserialize]] loads from serial buffer into a delimited_array reference
Definition: serdes.h:166
virtual void format(packet &)=0
override to declare the serdes process used in store() and load()
void store(const T(&value)[N], size_t bits=detail::default_bitsize< T >::value)
[[serialize]] stores a raw array reference into a serial buffer
Definition: serdes.h:401
void store(const formatter &&value)
[[serialize]] stores a formatter rvalue into a serial buffer
Definition: serdes.h:586
void load(formatter &value)
[[deserialize]] loads from serial buffer into a formatter reference
Definition: serdes.h:141
void store(const serdes::pad< ST > padding)
[[serialize, pad]] applies a padding step to the store process
Definition: serdes.h:595
T * value
a pointer to the array head
Definition: serdes_format_modifiers.h:90
no serialization/deserialization errors occurred
serdes::status_t load(const T_array(&source_buffer)[N], size_t max_elements=N, size_t bit_offset=0)
[[deserialize]] loads data from the source "sized" array according to the format() process ...
const ST & value
bit alignment reference value
Definition: serdes_format_modifiers.h:21
void store(const packet_base &&value)
[[serialize]] stores a packet_base rvalue into a serial buffer
Definition: serdes.h:647
T & value
a reference to the bitpacked value
Definition: serdes_format_modifiers.h:57
const ST & bits
a reference to the number of bits to use when storing/loading the referenced value ...
Definition: serdes_format_modifiers.h:60
void add(T(&x)[N])
adds an array field to the serial format for both serialization and deserialization ...
Definition: serdes.h:726
serdes::status_t operator<<(T &&value)
[[deserialize]] loads packet_base data into the passed serial data (same as load) ...
void add(T(&x)[N], size_t bits)
adds an array field to the serial format for both serialization and deserialization ...
Definition: serdes.h:700
void *const value
the underlying pointer reinterpreted as a void* type
Definition: bitcpy_sized_pointer.h:51
void pad(const size_t bits)
moves the bit offset head the specified bits
Definition: serdes.h:79
(deserializing) loading from serial data into variables
void store(const delimited_array< T > &&value)
[[serialize]] stores a delimited_array<packet_base> rvalue into a serial buffer
Definition: serdes.h:493
Holds a pointer to an array (with its type information) with a constant size.
Definition: bitcpy_sized_pointer.h:19
void load(T &value, size_t bits=detail::default_bitsize< T >::value)
[[deserialize]] loads from serial buffer into the passed value reference
Definition: serdes.h:115
void load(T &&value, size_t bits=detail::default_bitsize< T >::value)
[[deserialize]] loads from serial buffer into the passed value rvalue NOTE: using this method will ca...
Definition: serdes.h:129
void load(packet_base &&value)
[[deserialize]] loads from serial buffer into a packet_base rvalue
Definition: serdes.h:370
Holds a pointer to a void array (with type information stored as a runtime element size paramenter) w...
Definition: bitcpy_sized_pointer.h:48
void store(const delimited_array< T > &value, size_t bits=detail::default_bitsize< T >::value)
[[serialize]] stores a delimited_array reference into a serial buffer
Definition: serdes.h:422
bitpack a value into an exact number of specified bits. If applied to an array it will be applied to ...
Definition: serdes_format_modifiers.h:54