Date: Sat, 16 Nov 2024 22:55:42 +0100
Hi
When working with binary data, one often needs to split a larger
std::bitset into several smaller std::bitsets. One example is if you
have a memory-mapped register read into a std::bitset.
The reverse is also needed to concatenate sub-bitsets into a larger bitset.
Currently, splitting and concatenating these requires using mask and
shift operations on the bitset, which can be complicated to read and
thus, error-prone.
I propose adding two utility functions (split and concat) for std::bitset:
template<size_t... slices, size_t num_bits_in_source>
constexpr auto split(std::bitset<num_bits_in_source> source)
template<size_t num_bits, size_t... num_bits_rest>
constexpr auto concat(std::bitset<num_bits> bits,
std::bitset<num_bits_rest>... rest)
split would return a tuple of bitsets.
The use of these functions could be as follows:
std::bitset<8> uxlcr{"10010111"};
auto [divisor_latch_access, break_ctrl, parity, parity_enable,
stopbit, word_length] = split<1,1,2,1,1,2>(uxlcr);
word_length = 0b10;
uxlcr = concat(divisor_latch_access, break_ctrl, parity,
parity_enable, stopbit, word_length);
Another use-case is extracting sextets to generate base-64 encoded data:
--- to base64 ---
const auto datablock = std::bitset<24>{...};
const auto sextets = std::split<6,6,6,6>(data);
const auto ascii = sextets2chars(sextets);
--- from base64 ---
const auto chars = std::array<char, 4>{...};
const auto sextets = chars2sextets(chars);
const auto binary = std::concat(sextets);
sextets will in these examples be a tuple of 4 std::bitset<6>
Example implementation:
https://godbolt.org/z/P8PaqvnMa
Looking forward to your thoughts on this.
Best regards
Nikolaj Fogh
When working with binary data, one often needs to split a larger
std::bitset into several smaller std::bitsets. One example is if you
have a memory-mapped register read into a std::bitset.
The reverse is also needed to concatenate sub-bitsets into a larger bitset.
Currently, splitting and concatenating these requires using mask and
shift operations on the bitset, which can be complicated to read and
thus, error-prone.
I propose adding two utility functions (split and concat) for std::bitset:
template<size_t... slices, size_t num_bits_in_source>
constexpr auto split(std::bitset<num_bits_in_source> source)
template<size_t num_bits, size_t... num_bits_rest>
constexpr auto concat(std::bitset<num_bits> bits,
std::bitset<num_bits_rest>... rest)
split would return a tuple of bitsets.
The use of these functions could be as follows:
std::bitset<8> uxlcr{"10010111"};
auto [divisor_latch_access, break_ctrl, parity, parity_enable,
stopbit, word_length] = split<1,1,2,1,1,2>(uxlcr);
word_length = 0b10;
uxlcr = concat(divisor_latch_access, break_ctrl, parity,
parity_enable, stopbit, word_length);
Another use-case is extracting sextets to generate base-64 encoded data:
--- to base64 ---
const auto datablock = std::bitset<24>{...};
const auto sextets = std::split<6,6,6,6>(data);
const auto ascii = sextets2chars(sextets);
--- from base64 ---
const auto chars = std::array<char, 4>{...};
const auto sextets = chars2sextets(chars);
const auto binary = std::concat(sextets);
sextets will in these examples be a tuple of 4 std::bitset<6>
Example implementation:
https://godbolt.org/z/P8PaqvnMa
Looking forward to your thoughts on this.
Best regards
Nikolaj Fogh
Received on 2024-11-16 21:55:58