19 #include "serdes_fwd_declarations.h"
24 #if !defined(configCPP_SERDES_LIB_EXCLUDE_CPP_CRC) && BITCPY_CONSTEXPR_SUPPORTED
33 #ifndef configCPP_SERDES_LIB_INLINE_PACKET_API_AGGRESSION
34 #define configCPP_SERDES_LIB_INLINE_PACKET_API_AGGRESSION 1
36 #if configCPP_SERDES_LIB_INLINE_PACKET_API_AGGRESSION < 0 || configCPP_SERDES_LIB_INLINE_PACKET_API_AGGRESSION > 2
37 #error "configCPP_SERDES_LIB_INLINE_PACKET_API_AGGRESSION must be 0, 1, or 2"
39 #if configCPP_SERDES_LIB_INLINE_PACKET_API_AGGRESSION == 0
40 #define CPP_SERDES_LIB_PACKET_API_INLINE1
41 #define CPP_SERDES_LIB_PACKET_API_INLINE2
42 #elif configCPP_SERDES_LIB_INLINE_PACKET_API_AGGRESSION == 1
43 #define CPP_SERDES_LIB_PACKET_API_INLINE1 inline
44 #define CPP_SERDES_LIB_PACKET_API_INLINE2
45 #elif configCPP_SERDES_LIB_INLINE_PACKET_API_AGGRESSION == 2
46 #define CPP_SERDES_LIB_PACKET_API_INLINE1 inline
47 #define CPP_SERDES_LIB_PACKET_API_INLINE2 inline
75 template <typename T_pointer, typename std::enable_if<std::is_pointer<T_pointer>::value,
int *>::type =
nullptr>
77 :
buffer{array_init, max_elements},
88 template <
typename T_array,
size_t N>
90 :
buffer{array_init, max_elements < N ? max_elements : N},
100 template <typename T_sized_pointer, typename std::enable_if<serdes::detail::is_sized_pointer<T_sized_pointer>::value,
int *>::type =
nullptr>
114 template <
typename T_array, detail::requires_data_and_size<T_array>* =
nullptr>
116 :
buffer{array_init.data(), max_elements < array_init.
size() ? max_elements : array_init.size()},
123 inline void pad(
const size_t bits) noexcept
126 pad_assuming_no_prior_errors(bits);
131 inline void align(
size_t bits) noexcept
134 align_assuming_no_prior_errors(bits);
146 template <
typename T,
size_t N>
147 CPP_SERDES_LIB_PACKET_API_INLINE1
void load(T (&value)[N],
size_t bits = detail::default_bitsize<T>::value)
150 load(temp_arr, bits);
158 template <
typename T,
typename std::enable_if<
159 detail::has_data_and_size<typename detail::remove_cvref_cpp11<T>::type>::value &&
160 !detail::has_custom_type_override<typename detail::remove_cvref_cpp11<T>::type>::value
161 ,
int *>::type =
nullptr>
162 CPP_SERDES_LIB_PACKET_API_INLINE2
void load(T &&value,
size_t bits = detail::default_bitsize<
typename detail::has_data_and_size<
typename detail::remove_cvref_cpp11<T>::type>::elem_type>::value)
166 size_t size = value.size();
173 using elem_type =
typename detail::has_data_and_size<typename detail::remove_cvref_cpp11<T>::type>::elem_type;
175 load(temp_arr, bits);
182 template <
typename T,
typename std::enable_if<
183 !detail::is_format_modifier<typename detail::remove_cvref_cpp11<T>::type>::value &&
184 detail::supported_by_bitcpy<typename detail::remove_cvref_cpp11<T>::type>::value,
185 int *>::type =
nullptr>
186 CPP_SERDES_LIB_PACKET_API_INLINE1
void load(T &value,
size_t bits = detail::default_bitsize<T>::value)
193 if (bits_touched < bits)
203 template <
typename T,
typename std::enable_if<
204 detail::has_custom_type_with_bit_support<typename detail::remove_cvref_cpp11<T>::type>::value
207 detail::has_custom_type_override<typename detail::remove_cvref_cpp11<T>::type>::value ||
210 !detail::is_format_modifier<typename detail::remove_cvref_cpp11<T>::type>::value &&
211 !detail::supported_by_bitcpy<typename detail::remove_cvref_cpp11<T>::type>::value &&
212 !std::is_array<typename detail::remove_cvref_cpp11<T>::type>::value &&
213 !detail::has_load_and_store<typename detail::remove_cvref_cpp11<T>::type>::value &&
214 !detail::has_data_and_size<typename detail::remove_cvref_cpp11<T>::type>::value
216 ),
int *>::type =
nullptr>
217 CPP_SERDES_LIB_PACKET_API_INLINE2
void load(T &&value,
size_t bits =
custom_type<
typename detail::remove_cvref_cpp11<T>::type>::default_bits)
230 template <
typename T,
typename std::enable_if<
231 detail::has_custom_type_without_bit_support<typename detail::remove_cvref_cpp11<T>::type>::value
234 detail::has_custom_type_override<typename detail::remove_cvref_cpp11<T>::type>::value ||
237 !detail::is_format_modifier<typename detail::remove_cvref_cpp11<T>::type>::value &&
238 !detail::supported_by_bitcpy<typename detail::remove_cvref_cpp11<T>::type>::value &&
239 !std::is_array<typename detail::remove_cvref_cpp11<T>::type>::value &&
240 !detail::has_load_and_store<typename detail::remove_cvref_cpp11<T>::type>::value &&
241 !detail::has_data_and_size<typename detail::remove_cvref_cpp11<T>::type>::value
243 ),
int *>::type =
nullptr>
244 CPP_SERDES_LIB_PACKET_API_INLINE2
void load(T &&value)
256 template <typename T, typename std::enable_if<detail::has_format_method<T>::value,
int *>::type =
nullptr>
257 CPP_SERDES_LIB_PACKET_API_INLINE2
void load(T &&value)
262 std::forward<T>(value).format(*
this);
269 template <typename T, typename std::enable_if<detail::has_load_and_store<typename detail::remove_cvref_cpp11<T>::type>::value,
int *>::type =
nullptr>
270 CPP_SERDES_LIB_PACKET_API_INLINE1
void load(T &&value)
275 typename detail::get_inner_wrapped_type<typename detail::remove_cvref_cpp11<T>::type>::type temp_value{};
278 value.store(temp_value);
283 template <
typename T,
typename std::enable_if<
284 std::is_rvalue_reference<T &&>::value
287 && detail::supported_by_bitcpy<T>::value,
288 int *>::type =
nullptr>
289 CPP_SERDES_LIB_PACKET_API_INLINE2
void load(T &&value,
size_t bits = detail::default_bitsize<T>::value)
301 template<
typename T,
typename std::enable_if<
302 detail::is_formatter<typename detail::remove_cvref_cpp11<T>::type>::value,
303 int *>::type* =
nullptr>
304 CPP_SERDES_LIB_PACKET_API_INLINE2
void load(T &&value)
309 if (value.formatter_lambda ==
nullptr)
314 value.formatter_lambda(*
this);
321 template <typename T, typename std::enable_if<!detail::is_format_modifier<typename delimited_array<T>::elem_type>::value,
int *>::type =
nullptr>
328 constexpr
size_t bits_per_element =
sizeof(elem_type) * 8;
338 const size_t max_bit_offset_minus_one_element =
bit_capacity - bits_per_element;
339 const elem_type *buffer_head = &
reinterpret_cast<const elem_type *
>(
buffer.
value)[
bit_offset / bits_per_element];
340 for (
size_t i = 0; i < value.
max_size; i++)
342 if (
bit_offset > max_bit_offset_minus_one_element)
347 const elem_type &source_value = *buffer_head;
348 value.
value[i] = source_value;
357 for (
size_t i = 0; i < value.
max_size; i++)
361 if (bits_touched < bits)
377 template <typename T, typename std::enable_if<detail::has_format_method<typename delimited_array<T>::elem_type>::value,
int *>::type =
nullptr>
383 for (
size_t i = 0; i < value.
max_size; i++)
385 value.
value[i].format(*
this);
395 template <
typename T>
406 template <
typename T,
typename T2,
typename std::enable_if<
407 !detail::is_format_modifier<typename serdes::array<T, T2>::elem_type>::value &&
408 detail::supported_by_bitcpy<typename serdes::array<T, T2>::elem_type>::value
409 ,
int *>::type =
nullptr>
417 size_t array_size =
static_cast<size_t>(value.
size);
431 for (
size_t i = 0; i < array_size; i++)
435 if (bits_touched < bits)
448 template <
typename T,
typename T2,
typename std::enable_if<
449 !detail::is_format_modifier<typename serdes::array<T, T2>::elem_type>::value &&
450 !detail::supported_by_bitcpy<typename serdes::array<T, T2>::elem_type>::value
451 ,
int *>::type =
nullptr>
459 size_t array_size =
static_cast<size_t>(value.
size);
473 template <typename T, typename T2, typename std::enable_if<detail::has_format_method<typename serdes::array<T, T2>::elem_type>::value,
int *>::type =
nullptr>
481 size_t array_size =
static_cast<size_t>(value.
size);
487 for (
size_t i = 0; i < array_size; i++)
489 value.
value[i].format(*
this);
499 template <
typename T,
typename T2>
508 template <
typename ST>
514 pad_assuming_no_prior_errors(padding.
value);
520 template <
typename ST>
526 align_assuming_no_prior_errors(alignment.
value);
533 template <
typename T,
typename ST>
536 load(value.value, value.bits);
543 template <
typename T,
typename ST>
574 template <
typename T,
typename std::enable_if<
575 !detail::is_format_modifier<typename detail::remove_cvref_cpp11<T>::type>::value &&
576 detail::supported_by_bitcpy<typename detail::remove_cvref_cpp11<T>::type>::value,
577 int *>::type =
nullptr>
578 CPP_SERDES_LIB_PACKET_API_INLINE1
void store(
const T &value,
size_t bits = detail::default_bitsize<T>::value)
585 if (bits_touched < bits)
595 template <
typename T,
typename std::enable_if<
596 detail::has_custom_type_with_bit_support<typename detail::remove_cvref_cpp11<T>::type>::value
600 detail::has_custom_type_override<typename detail::remove_cvref_cpp11<T>::type>::value ||
603 !detail::is_format_modifier<typename detail::remove_cvref_cpp11<T>::type>::value &&
604 !detail::supported_by_bitcpy<typename detail::remove_cvref_cpp11<T>::type>::value &&
605 !std::is_array<typename detail::remove_cvref_cpp11<T>::type>::value &&
606 !detail::has_load_and_store<typename detail::remove_cvref_cpp11<T>::type>::value &&
607 !detail::has_data_and_size<typename detail::remove_cvref_cpp11<T>::type>::value
609 ),
int *>::type =
nullptr>
610 CPP_SERDES_LIB_PACKET_API_INLINE2
void store(T &&value,
size_t bits =
custom_type<
typename detail::remove_cvref_cpp11<T>::type>::default_bits)
622 template <
typename T,
typename std::enable_if<
623 detail::has_custom_type_without_bit_support<typename detail::remove_cvref_cpp11<T>::type>::value
627 detail::has_custom_type_override<typename detail::remove_cvref_cpp11<T>::type>::value ||
630 !detail::is_format_modifier<typename detail::remove_cvref_cpp11<T>::type>::value &&
631 !detail::supported_by_bitcpy<typename detail::remove_cvref_cpp11<T>::type>::value &&
632 !std::is_array<typename detail::remove_cvref_cpp11<T>::type>::value &&
633 !detail::has_load_and_store<typename detail::remove_cvref_cpp11<T>::type>::value &&
634 !detail::has_data_and_size<typename detail::remove_cvref_cpp11<T>::type>::value
636 ),
int *>::type =
nullptr>
637 CPP_SERDES_LIB_PACKET_API_INLINE2
void store(T &&value)
648 template <typename T, typename std::enable_if<detail::has_format_method<T>::value,
int *>::type =
nullptr>
649 CPP_SERDES_LIB_PACKET_API_INLINE2
void store(T &&value)
654 std::forward<T>(value).format(*
this);
660 template <
typename T,
typename std::enable_if<detail::has_load_and_store<
661 typename detail::remove_cvref_cpp11<T>::type>::value,
int *>::type =
nullptr>
662 CPP_SERDES_LIB_PACKET_API_INLINE1
void store(T &&value)
675 template <
typename T,
size_t N>
676 CPP_SERDES_LIB_PACKET_API_INLINE1
void store(
const T (&value)[N],
size_t bits = detail::default_bitsize<T>::value)
686 template <
typename T,
typename std::enable_if<
687 detail::has_data_and_size<typename detail::remove_cvref_cpp11<T>::type>::value &&
688 !detail::has_custom_type_override<typename detail::remove_cvref_cpp11<T>::type>::value
689 ,
int *>::type =
nullptr>
690 CPP_SERDES_LIB_PACKET_API_INLINE2
void store(T &&value,
size_t bits = detail::default_bitsize<
typename detail::has_data_and_size<
typename detail::remove_cvref_cpp11<T>::type>::elem_type>::value)
692 size_t size = value.size();
695 using elem_type =
typename detail::has_data_and_size<typename detail::remove_cvref_cpp11<T>::type>::elem_type;
697 store(temp_arr, bits);
705 template <
typename T,
size_t N>
706 CPP_SERDES_LIB_PACKET_API_INLINE1
void store(
const T (&&value)[N],
size_t bits = detail::default_bitsize<T>::value)
715 template <typename T, typename std::enable_if<!detail::is_format_modifier<typename delimited_array<T>::elem_type>::value,
int *>::type =
nullptr>
721 using elem_type =
typename detail::remove_cvref_cpp11<typename delimited_array<T>::elem_type>::type;
722 constexpr
size_t bits_per_element =
sizeof(elem_type) * 8;
731 const size_t max_bit_offset_minus_one_element =
bit_capacity - bits_per_element;
732 elem_type *buffer_head = &
reinterpret_cast<elem_type *
>(
buffer.
value)[
bit_offset / bits_per_element];
733 for (
size_t i = 0; i < value.
max_size; i++)
735 if (
bit_offset > max_bit_offset_minus_one_element)
740 const elem_type &source_value = value.
value[i];
741 *buffer_head = source_value;
750 for (
size_t i = 0; i < value.
max_size; i++)
754 if (bits_touched < bits)
769 template <typename T, typename std::enable_if<detail::has_format_method<typename delimited_array<T>::elem_type>::value,
int *>::type =
nullptr>
775 for (
size_t i = 0; i < value.
max_size; i++)
777 value.
value[i].format(*
this);
787 template <
typename T>
798 template <
typename T,
typename T2,
typename std::enable_if<
799 !detail::is_format_modifier<typename serdes::array<T, T2>::elem_type>::value &&
800 detail::supported_by_bitcpy<typename serdes::array<T, T2>::elem_type>::value
801 ,
int *>::type =
nullptr>
809 size_t array_size =
static_cast<size_t>(value.
size);
823 for (
size_t i = 0; i < array_size; i++)
827 if (bits_touched < bits)
840 template <
typename T,
typename T2,
typename std::enable_if<
841 !detail::is_format_modifier<typename serdes::array<T, T2>::elem_type>::value &&
842 !detail::supported_by_bitcpy<typename serdes::array<T, T2>::elem_type>::value
843 ,
int *>::type =
nullptr>
851 size_t array_size =
static_cast<size_t>(value.
size);
865 template <typename T, typename T2, typename std::enable_if<detail::has_format_method<typename serdes::array<T, T2>::elem_type>::value,
int *>::type =
nullptr>
873 size_t array_size =
static_cast<size_t>(value.
size);
879 for (
size_t i = 0; i < array_size; i++)
881 value.
value[i].format(*
this);
891 template <
typename T,
typename T2>
899 template<
typename T,
typename std::enable_if<
900 detail::is_formatter<typename detail::remove_cvref_cpp11<T>::type>::value,
901 int *>::type* =
nullptr>
902 CPP_SERDES_LIB_PACKET_API_INLINE2
void store(T &&value)
907 if (value.formatter_lambda ==
nullptr)
912 value.formatter_lambda(*
this);
918 template <
typename ST>
924 pad_assuming_no_prior_errors(padding.
value);
930 template <
typename ST>
943 template <
typename T,
typename ST>
946 store(value.value, value.bits);
953 template <
typename T,
typename ST>
984 template <
typename T>
987 load(std::forward<T>(x));
995 template <
typename T>
998 store(std::forward<T>(x));
1010 template <
typename T>
1011 CPP_SERDES_LIB_PACKET_API_INLINE1
void add(T &&x,
size_t bits)
1014 load(std::forward<T>(x), bits);
1016 store(std::forward<T>(x), bits);
1023 template <
typename T,
size_t N>
1024 CPP_SERDES_LIB_PACKET_API_INLINE1
void add(T (&x)[N],
size_t bits)
1027 for (
size_t i = 0; i < N; i++)
1030 for (
size_t i = 0; i < N; i++)
1037 template <
typename T,
typename std::enable_if<
1038 !detail::is_validator<typename detail::remove_cvref_cpp11<T>::type>::value,
1039 int *>::type* =
nullptr>
1040 CPP_SERDES_LIB_PACKET_API_INLINE1
void add(T &&x)
1043 load(std::forward<T>(x));
1045 store(std::forward<T>(x));
1051 template <
typename T,
size_t N>
1052 CPP_SERDES_LIB_PACKET_API_INLINE1
void add(T (&x)[N])
1055 for (
size_t i = 0; i < N; i++)
1058 for (
size_t i = 0; i < N; i++)
1067 template <
typename T,
typename F>
1068 CPP_SERDES_LIB_PACKET_API_INLINE1
void add(T &&value, F &&validation)
1073 load(std::forward<T>(value));
1074 if (!std::forward<F>(validation)())
1077 store(std::forward<T>(value));
1089 template <
typename T,
typename std::enable_if<
1090 detail::is_validator<typename detail::remove_cvref_cpp11<T>::type>::value,
1091 int *>::type* =
nullptr>
1092 CPP_SERDES_LIB_PACKET_API_INLINE1
void add(T &&value)
1094 add(value.field, value.validation);
1101 #if (defined(__GNUC__) && !defined(__clang__))
1102 #pragma GCC diagnostic push
1103 #pragma GCC diagnostic ignored "-Weffc++"
1105 template <
typename T>
1112 add(std::forward<T>(value));
1115 #if (defined(__GNUC__) && !defined(__clang__))
1116 #pragma GCC diagnostic pop
1132 const size_t end_byte_index_plus_one = start.value + size.value;
1133 if (end_byte_index_plus_one >= max_num_bytes)
1138 return {
buffer, start.value, end_byte_index_plus_one};
1152 const size_t max_num_bytes =
bit_offset / 8u;
1153 if (start.value >= max_num_bytes)
1174 #if !defined(configCPP_SERDES_LIB_EXCLUDE_CPP_CRC) && BITCPY_CONSTEXPR_SUPPORTED
1175 template <
typename cpp_crc_type>
1182 CPP_SERDES_LIB_PACKET_API_INLINE2
typename cpp_crc_type::type calculate_crc(
typename cpp_crc_type::type *crc_field =
nullptr)
1184 auto crc_calculated = cpp_crc_type::null_crc;
1186 crc_calculated = cpp_crc_type::calc(segment.bytes, segment.num_bytes, crc_calculated);
1188 *crc_field = crc_calculated;
1189 return crc_calculated;
1196 inline void pad_assuming_no_prior_errors(
const size_t bits) noexcept
1198 const size_t next_bit_offset =
bit_offset + bits;
1209 inline void align_assuming_no_prior_errors(
size_t bits) noexcept
1214 const size_t next_bit_offset =
bit_offset + bits - alignment;
1225 inline void ensure_load() noexcept
1236 inline void ensure_store() noexcept
1247 template <
typename T_array,
size_t N>
1248 status_t
packet_base::store(T_array (&target_buffer)[N],
size_t max_elements,
size_t bit_offset)
1250 if (N < max_elements)
1254 return {pkt_obj.status, pkt_obj.bit_offset};
1257 template <typename T_pointer, typename std::enable_if<std::is_pointer<T_pointer>::value,
int *>::type>
1258 status_t
packet_base::store(T_pointer target_buffer,
size_t max_elements,
size_t bit_offset)
1262 return {pkt_obj.status, pkt_obj.bit_offset};
1265 template <typename T_sized_pointer, typename std::enable_if<serdes::detail::is_sized_pointer<T_sized_pointer>::value,
int *>::type>
1270 return {pkt_obj.status, pkt_obj.bit_offset};
1272 template <
typename T_array,
size_t N>
1273 status_t
packet_base::load(
const T_array (&source_buffer)[N],
size_t max_elements,
size_t bit_offset)
1275 if (N < max_elements)
1279 return {pkt_obj.status, pkt_obj.bit_offset};
1281 template <typename T_pointer, typename std::enable_if<std::is_pointer<T_pointer>::value,
int *>::type>
1282 status_t
packet_base::load(
const T_pointer source_buffer,
size_t max_elements,
size_t bit_offset)
1286 return {pkt_obj.status, pkt_obj.bit_offset};
1288 template <typename T_sized_pointer, typename std::enable_if<serdes::detail::is_sized_pointer<T_sized_pointer>::value,
int *>::type>
1289 status_t
packet_base::load(
const T_sized_pointer target_buffer,
size_t bit_offset)
1293 return {pkt_obj.status, pkt_obj.bit_offset};
1295 template <
typename T>
1298 return store(std::forward<T>(value));
1300 template <
typename T>
1303 return load(std::forward<T>(value));
1327 #endif // _SERDES_H_