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
148 typename detail::unsigned_type_sizeof<sizeof(T_val)>::type dest_copy;
149 const size_t result_size =
bitcpy(dest_copy, source, bit_offset, bits);
150 if (result_size == 0u)
152 memcpy(&dest, &dest_copy,
sizeof(T_val));
166 template <
typename T_array,
typename T_val, detail::requires_
signed_type<T_val> * =
nullptr>
167 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
169 bitcpy(detail::reinterpret_as_unsigned(dest), source, bit_offset, bits);
170 detail::extend_sign(dest, bits);
184 template <
typename T_array,
typename T_val, detail::requires_
unsigned_type<T_val> * =
nullptr>
187 constexpr
size_t bits_per_T_val =
sizeof(T_val) * 8;
188 const size_t total_bits_T_val = bits_per_T_val * dest.size;
189 if (bits == total_bits_T_val)
191 for (
size_t i = 0; i < dest.size; i++)
192 bitcpy(dest.value[i], source, bit_offset + i * bits_per_T_val, bits_per_T_val);
194 else if (bits < total_bits_T_val)
196 const size_t bit_difference = total_bits_T_val - bits;
197 const size_t starting_source_word = bit_difference / bits_per_T_val;
198 const size_t last_bit_index = dest.size - 1u;
199 const size_t last_bit_suboffset = bits_per_T_val * last_bit_index - bit_difference;
200 const size_t remainder_bits = bits - last_bit_suboffset;
201 const std::make_signed<size_t>::type offset_per_loop = bit_offset - bit_difference;
202 for (
size_t i = starting_source_word; i < dest.size - 1u; i++)
203 bitcpy(dest.value[i], source, offset_per_loop + i * bits_per_T_val, bits_per_T_val);
204 bitcpy(dest.value[last_bit_index], source, bit_offset + last_bit_suboffset, remainder_bits);
208 size_t adjusted_offset = bit_offset + bits - total_bits_T_val;
209 bitcpy(dest.value[0], source, adjusted_offset, bits_per_T_val);
210 for (
size_t i = 1; i < dest.size; i++)
212 adjusted_offset += bits_per_T_val;
213 bitcpy(dest.value[i], source, adjusted_offset, bits_per_T_val);
229 template <
typename T_array,
typename T_val, detail::requires_
unsigned_type<T_val> * =
nullptr>
245 template <
typename T_array,
typename T_val, detail::requires_large_non_
integral_type<T_val> * =
nullptr>
250 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
253 return bitcpy(dest_array, source, bit_offset, bits);
266 template <
typename T_array =
void,
typename T_val =
void, detail::requires_not_a_po
inter_type<T_val> * =
nullptr>
284 template <
typename T_array,
typename T_val>
285 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
288 typename detail::unsigned_type_sizeof<sizeof(T_val)>::type dest_copy;
289 const size_t result_size =
bitcpy(dest_copy, source, bit_offset, bits);
290 if (result_size == 0u)
292 memcpy(&dest, &dest_copy,
sizeof(T_val));
308 template <
typename T_array =
void,
typename T_val =
void, detail::requires_po
inter_type<T_val> * =
nullptr>
309 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
313 return detail::bitcpy_disambiguous_pointer_from_array(dest, source.
value, bit_offset, bits);
326 template <
typename T_array,
typename T_val>
327 size_t bitcpy(std::atomic<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
329 T_val temp_value = 0;
330 const size_t bits_written =
bitcpy(temp_value, source, bit_offset, bits);
331 if (bits_written > 0)
332 dest.store(temp_value);
346 template <
typename T_val =
void>
354 return bitcpy(dest, reinterpret_cast<const uint8_t *>(source.
value), bit_offset, bits);
356 return bitcpy(dest, reinterpret_cast<const uint16_t *>(source.
value), bit_offset, bits);
358 return bitcpy(dest, reinterpret_cast<const uint32_t *>(source.
value), bit_offset, bits);
360 return bitcpy(dest, reinterpret_cast<const uint64_t *>(source.
value), bit_offset, bits);
368 #endif // _BITCPY_FROM_ARRAY_H_ Defines common bitcpy details as well as a info::version number, and bit_length function.
CppSerdes library namespace.
Definition: bitcpy_common.h:69
T_array *const value
the underlying pointer
Definition: bitcpy_sized_pointer.h:22
size_t bit_capacity() const noexcept
returns the number of bits in the array
Definition: bitcpy_sized_pointer.h:76
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
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
void *const value
the underlying pointer reinterpreted as a void* type
Definition: bitcpy_sized_pointer.h:51
size_t bit_capacity() const noexcept
returns the number of bits in the array
Definition: bitcpy_sized_pointer.h:39
Holds a pointer to an array (with its type information) with a constant size.
Definition: bitcpy_sized_pointer.h:19
Holds a pointer to a void array (with type information stored as a runtime element size paramenter) w...
Definition: bitcpy_sized_pointer.h:48
#define CONSTEXPR_ABOVE_CPP11
resolves automatically to "constexpr" if C++14 or greater
Definition: bitcpy_common.h:31