1 #ifndef _BITCPY_TO_ARRAY_H_ 9 #define _BITCPY_TO_ARRAY_H_ 26 template <
typename T_array,
typename T_val, detail::requires_
unsigned_type<T_val> * =
nullptr>
27 CONSTEXPR_ABOVE_CPP11 size_t bitcpy(T_array *
const dest,
const T_val source,
const size_t bit_offset = 0,
const size_t bits = detail::default_bitsize<T_val>::value) noexcept
29 constexpr
size_t bits_per_T_array =
sizeof(T_array) * 8u;
30 constexpr
size_t bits_per_T_array_minus_one = bits_per_T_array - 1u;
31 size_t array_write_index = bit_offset / bits_per_T_array;
32 const size_t bit_offset_from_start_index = bit_offset & bits_per_T_array_minus_one;
35 if (bits == bits_per_T_array && bit_offset_from_start_index == 0)
37 dest[array_write_index] = source;
42 const size_t number_of_bits_after_index = bit_offset_from_start_index + bits;
43 if (number_of_bits_after_index <= bits_per_T_array)
47 const T_array unaligned_mask = detail::bitmask<T_array>(bits);
48 const size_t alignment_shift = bits_per_T_array - number_of_bits_after_index;
49 T_array &dest_array_element = dest[array_write_index];
52 dest_array_element &= ~(unaligned_mask << alignment_shift);
55 dest_array_element |=
static_cast<T_array
>(source & unaligned_mask) << alignment_shift;
60 const size_t num_array_elements_touched = (number_of_bits_after_index + bits_per_T_array - 1u) / bits_per_T_array;
61 const size_t bits_in_first_element = bits_per_T_array - bit_offset_from_start_index;
62 size_t bits_remaining = bits - bits_in_first_element;
64 const T_array aligned_mask = detail::bitmask<T_array>(bits_in_first_element);
65 T_array &dest_array_first_element = dest[array_write_index];
66 dest_array_first_element &= ~aligned_mask;
67 dest_array_first_element |=
static_cast<T_array
>(source >> bits_remaining) & aligned_mask;
69 for (
size_t i = 1u; i < num_array_elements_touched - 1u; i++)
72 bits_remaining -= bits_per_T_array;
73 dest[array_write_index] =
static_cast<T_array
>(source >> bits_remaining);
77 const size_t alignment_shift = bits_per_T_array - bits_remaining;
78 const T_array aligned_mask = detail::bitmask<T_array>(bits_remaining) << alignment_shift;
79 T_array &dest_array_last_element = dest[array_write_index];
80 dest_array_last_element &= ~aligned_mask;
81 dest_array_last_element |= (
static_cast<T_array
>(source) << alignment_shift) & aligned_mask;
96 template <
typename T_array,
typename T_val, detail::requires_
bool_type<T_val> * =
nullptr>
97 CONSTEXPR_ABOVE_CPP11 size_t bitcpy(T_array *
const dest,
const T_val source,
const size_t bit_offset = 0,
const size_t bits = detail::default_bitsize<T_val>::value) noexcept
101 constexpr
size_t bits_per_T_array =
sizeof(T_array) * 8u;
102 constexpr
size_t bits_per_T_array_minus_one = bits_per_T_array - 1u;
103 const T_array bit_mask =
static_cast<T_array
>(1u) << (bits_per_T_array_minus_one - (bit_offset & bits_per_T_array_minus_one));
104 const size_t array_index = bit_offset / bits_per_T_array;
106 dest[array_index] |= bit_mask;
108 dest[array_index] &= ~bit_mask;
111 const uint_fast8_t bool_as_uint =
static_cast<uint_fast8_t
>(source) & static_cast<uint_fast8_t>(1u);
112 return bitcpy(dest, bool_as_uint, bit_offset, bits);
125 template <
typename T_array,
typename T_val, detail::requires_small_non_
integral_type<T_val> * =
nullptr>
126 CONSTEXPR_ABOVE_CPP11 size_t bitcpy(T_array *
const dest,
const T_val source,
const size_t bit_offset = 0,
const size_t bits = detail::default_bitsize<T_val>::value) noexcept
128 return bitcpy(dest, detail::reinterpret_as_unsigned(source), bit_offset, bits);
141 template <
typename T_array,
typename T_val, detail::requires_
signed_type<T_val> * =
nullptr>
142 CONSTEXPR_ABOVE_CPP11 size_t bitcpy(T_array *
const dest,
const T_val source,
const size_t bit_offset = 0,
const size_t bits = detail::default_bitsize<T_val>::value) noexcept
144 return bitcpy(dest, detail::reinterpret_as_unsigned(source), bit_offset, bits);
158 template <
typename T_array,
typename T_val, detail::requires_
unsigned_type<T_val> * =
nullptr>
161 constexpr
size_t bits_per_T_val =
sizeof(T_val) * 8;
162 const size_t total_bits_T_val = bits_per_T_val * source.size;
163 if (bits == total_bits_T_val)
165 for (
size_t i = 0; i < source.size; i++)
166 bitcpy(dest, source.value[i], bit_offset + i * bits_per_T_val, bits_per_T_val);
168 else if (bits < total_bits_T_val)
170 const size_t bit_difference = total_bits_T_val - bits;
171 const size_t starting_source_word = bit_difference / bits_per_T_val;
172 const size_t last_bit_index = source.size - 1u;
173 const size_t last_bit_suboffset = bits_per_T_val * last_bit_index - bit_difference;
174 const size_t remainder_bits = bits - last_bit_suboffset;
175 const std::make_signed<size_t>::type offset_per_loop = bit_offset - bit_difference;
176 for (
size_t i = starting_source_word; i < source.size - 1u; i++)
177 bitcpy(dest, source.value[i], offset_per_loop + i * bits_per_T_val, bits_per_T_val);
178 bitcpy(dest, source.value[last_bit_index], bit_offset + last_bit_suboffset, remainder_bits);
182 size_t bit_difference = bits - total_bits_T_val;
183 bitcpy(dest, source.value[0], bit_offset, bits_per_T_val + bit_difference);
184 bit_difference += bit_offset;
185 for (
size_t i = 1; i < source.size; i++)
187 bit_difference += bits_per_T_val;
188 bitcpy(dest, source.value[i], bit_difference, bits_per_T_val);
203 template <
typename T_array,
typename T_val, detail::requires_
unsigned_type<T_val> * =
nullptr>
219 template <
typename T_array,
typename T_val, detail::requires_large_non_
integral_type<T_val> * =
nullptr>
223 return bitcpy(dest, source_array, bit_offset, bits);
235 template <
typename T_array =
void,
typename T_val =
void>
240 return bitcpy(dest.
value, source, bit_offset, bits);
253 template <
typename T_array,
typename T_val>
254 size_t bitcpy(T_array *
const dest,
const std::atomic<T_val> &source,
const size_t bit_offset = 0,
const size_t bits = detail::default_bitsize<T_val>::value) noexcept
256 return bitcpy(dest, source.load(), bit_offset, bits);
269 template <
typename T_val>
277 return bitcpy(reinterpret_cast<uint8_t *>(dest.
value), source, bit_offset, bits);
279 return bitcpy(reinterpret_cast<uint16_t *>(dest.
value), source, bit_offset, bits);
281 return bitcpy(reinterpret_cast<uint32_t *>(dest.
value), source, bit_offset, bits);
283 return bitcpy(reinterpret_cast<uint64_t *>(dest.
value), source, bit_offset, bits);
291 #endif // _BITCPY_TO_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
#define CONSTEXPR_ABOVE_CPP11_AND_NON_LITERAL_STORAGE
resolves automatically to "constexpr" if C++14 or greater
Definition: bitcpy_common.h:47