1 #ifndef _BITCPY_FROM_ARRAY_H_
9 #define _BITCPY_FROM_ARRAY_H_
28 template <
typename T_array,
typename T_val, detail::requires_
unsigned_type<T_val> * =
nullptr>
29 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
31 constexpr
size_t bits_per_T_array =
sizeof(T_array) * 8u;
32 constexpr
size_t bits_per_T_array_minus_one = bits_per_T_array - 1u;
33 size_t array_read_index = bit_offset / bits_per_T_array;
34 const size_t bit_offset_from_start_index = bit_offset & bits_per_T_array_minus_one;
37 if (bits == bits_per_T_array && bit_offset_from_start_index == 0)
39 dest =
static_cast<T_val
>(source[array_read_index]);
44 const size_t number_of_bits_after_index = bit_offset_from_start_index + bits;
45 if (number_of_bits_after_index <= bits_per_T_array)
49 const T_array unaligned_mask = detail::bitmask<T_val>(bits);
50 const size_t alignment_shift = bits_per_T_array - number_of_bits_after_index;
51 dest =
static_cast<T_val
>(
static_cast<T_array
>(source[array_read_index] >> alignment_shift) & unaligned_mask);
58 constexpr
size_t bits_per_T_val =
sizeof(T_val) * 8u;
59 if (number_of_bits_after_index <= bits_per_T_val)
61 const size_t alignment_shift = bits_per_T_val - number_of_bits_after_index;
62 if (alignment_shift < bits_per_T_array)
64 dest = detail::big_endian_memcpy_unsigned<T_val, T_array>(&source[array_read_index]);
65 const T_val unaligned_mask = detail::bitmask<T_val>(bits);
66 dest =
static_cast<T_val
>(dest >> alignment_shift) & unaligned_mask;
72 const size_t num_array_elements_touched_minus_one = (number_of_bits_after_index + bits_per_T_array - 1u) / bits_per_T_array - 1u;
73 const size_t bits_in_first_element = bits_per_T_array - bit_offset_from_start_index;
74 size_t bits_remaining = bits - bits_in_first_element;
75 size_t start_index = 1u;
76 if (bits_remaining < bits_per_T_val)
78 const T_array unaligned_mask = detail::bitmask<T_array>(bits_in_first_element);
79 dest =
static_cast<T_val
>(source[array_read_index] & unaligned_mask) << bits_remaining;
86 const size_t start_index_minus_one = (bits_remaining - bits_per_T_val) / bits_per_T_array;
87 start_index = start_index_minus_one + 1u;
88 bits_remaining -= bits_per_T_array * start_index_minus_one;
89 array_read_index += start_index_minus_one;
91 for (
size_t i = start_index; i < num_array_elements_touched_minus_one; i++)
93 bits_remaining -= bits_per_T_array;
95 dest |=
static_cast<T_val
>(source[array_read_index]) << bits_remaining;
98 const size_t remainder_right_shift = bits_per_T_array - bits_remaining;
99 const T_array unaligned_mask = detail::bitmask<T_array>(bits_remaining);
101 dest |=
static_cast<T_val
>((source[array_read_index] >> remainder_right_shift) & unaligned_mask);
116 template <
typename T_array,
typename T_val, detail::requires_
bool_type<T_val> * =
nullptr>
117 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
121 constexpr
size_t bits_per_T_array =
sizeof(T_array) * 8u;
122 constexpr
size_t bits_per_T_array_minus_one = bits_per_T_array - 1u;
123 const T_array bit_mask =
static_cast<T_array
>(1u) << (bits_per_T_array_minus_one - (bit_offset & bits_per_T_array_minus_one));
124 const size_t array_index = bit_offset / bits_per_T_array;
125 dest = (source[array_index] & bit_mask) == bit_mask;
128 uint8_t temp_write_val = 0u;
129 bitcpy(temp_write_val, source, bit_offset, bits);
130 dest = temp_write_val != 0u;
144 template <
typename T_array,
typename T_val, detail::requires_small_non_
integral_type<T_val> * =
nullptr>
145 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
149 typename detail::unsigned_type_sizeof<
sizeof(T_val)>::type dest_copy{};
150 const size_t result_size =
bitcpy(dest_copy, source, bit_offset, bits);
151 if (result_size == 0u)
153 std::memcpy(&dest, &dest_copy,
sizeof(T_val));
167 template <
typename T_array,
typename T_val, detail::requires_
signed_type<T_val> * =
nullptr>
168 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
170 #ifdef configCPP_SERDES_ALLOW_REINTERPRET_BUILTINS_UB
171 bitcpy(detail::reinterpret_as_unsigned(dest), source, bit_offset, bits);
172 detail::extend_sign(dest, bits);
174 typename detail::unsigned_type_sizeof<
sizeof(T_val)>::type dest_copy{};
175 bitcpy(dest_copy, source, bit_offset, bits);
176 std::memcpy(&dest, &dest_copy,
sizeof(T_val));
177 detail::extend_sign(dest, bits);
192 template <
typename T_array,
typename T_val, detail::requires_
unsigned_type<T_val> * =
nullptr>
195 constexpr
size_t bits_per_T_val =
sizeof(T_val) * 8;
196 const size_t total_bits_T_val = bits_per_T_val * dest.size;
197 if (bits == total_bits_T_val)
199 for (
size_t i = 0; i < dest.size; i++)
200 bitcpy(dest.value[i], source, bit_offset + i * bits_per_T_val, bits_per_T_val);
202 else if (bits < total_bits_T_val)
204 const size_t bit_difference = total_bits_T_val - bits;
205 const size_t starting_source_word = bit_difference / bits_per_T_val;
206 const size_t last_bit_index = dest.size - 1u;
207 const size_t last_bit_suboffset = bits_per_T_val * last_bit_index - bit_difference;
208 const size_t remainder_bits = bits - last_bit_suboffset;
209 const std::make_signed<size_t>::type offset_per_loop = bit_offset - bit_difference;
210 for (
size_t i = starting_source_word; i < dest.size - 1u; i++)
211 bitcpy(dest.value[i], source, offset_per_loop + i * bits_per_T_val, bits_per_T_val);
212 bitcpy(dest.value[last_bit_index], source, bit_offset + last_bit_suboffset, remainder_bits);
216 size_t adjusted_offset = bit_offset + bits - total_bits_T_val;
217 bitcpy(dest.value[0], source, adjusted_offset, bits_per_T_val);
218 for (
size_t i = 1; i < dest.size; i++)
220 adjusted_offset += bits_per_T_val;
221 bitcpy(dest.value[i], source, adjusted_offset, bits_per_T_val);
237 template <
typename T_array,
typename T_val, detail::requires_
unsigned_type<T_val> * =
nullptr>
253 template <
typename T_array,
typename T_val, detail::requires_large_non_
integral_type<T_val> * =
nullptr>
258 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
260 sized_pointer<uint8_t> dest_array(
reinterpret_cast<uint8_t *
>(&dest),
sizeof(T_val));
261 return bitcpy(dest_array, source, bit_offset, bits);
274 template <
typename T_array =
void,
typename T_val =
void, detail::requires_not_po
inter_or_load_store<T_val> * =
nullptr>
277 if (source.bit_capacity() < (bits + bit_offset))
279 bitcpy(dest, source.value, bit_offset, bits);
292 template <
typename T_array,
typename T_val>
293 size_t bitcpy_disambiguous_pointer_from_array(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
297 typename detail::unsigned_type_sizeof<
sizeof(T_val)>::type dest_copy{};
298 const size_t result_size =
bitcpy(dest_copy, source, bit_offset, bits);
299 if (result_size == 0u)
301 std::memcpy(&dest, &dest_copy,
sizeof(T_val));
317 template <
typename T_array =
void,
typename T_val =
void, detail::requires_po
inter_type<T_val> * =
nullptr>
318 size_t bitcpy(T_val &dest,
const sized_pointer<T_array> source,
const size_t bit_offset = 0,
const size_t bits = detail::default_bitsize<T_val>::value) noexcept
320 if (source.bit_capacity() < (bits + bit_offset))
322 return detail::bitcpy_disambiguous_pointer_from_array(dest, source.value, bit_offset, bits);
337 template <
typename T_array,
typename T_val,
template<
typename>
class T_wrap, detail::requires_load_and_store_of_builtin<T_wrap<T_val>> * =
nullptr>
338 size_t bitcpy(T_wrap<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
340 T_val temp_value = 0;
341 const size_t bits_written =
bitcpy(temp_value, source, bit_offset, bits);
342 if (bits_written > 0)
343 dest.store(temp_value);
357 template <
typename T_val =
void>
360 if (source.bit_capacity() < (bits + bit_offset))
362 switch (source.element_size)
365 return bitcpy(dest,
reinterpret_cast<const uint8_t *
>(source.value), bit_offset, bits);
367 return bitcpy(dest,
reinterpret_cast<const uint16_t *
>(source.value), bit_offset, bits);
369 return bitcpy(dest,
reinterpret_cast<const uint32_t *
>(source.value), bit_offset, bits);
371 return bitcpy(dest,
reinterpret_cast<const uint64_t *
>(source.value), bit_offset, bits);
379 #endif // _BITCPY_FROM_ARRAY_H_