Reputation: 415
I have a uint8_t array, containing three bytes.
// 1010 1010 1011 1011 1000 0000
uint8_t command[3] = {0xAA, 0xBB, 0x80};
I now want to zero-pad the array with 7 zeroes on the left side, eventually creating the following array (the 4th byte is of no interest to me):
// 0000 0001 0101 0101 0111 0111 0000 0000
uint8_t expected_output[4] = {0x01, 0x55, 0x77, 0x00};
What's the best way to get this zero-padding implemented in C++ ?
Upvotes: 2
Views: 1603
Reputation: 26272
Solution using std::bitset
:
std::array<std::uint8_t, 4>
left_pad(const std::array<std::uint8_t, 3>& in) {
using Bitset = std::bitset<8 * 4>;
Bitset bitset;
for (auto b = in.begin(); b != in.end(); ++b, bitset <<= 8)
bitset |= Bitset{*b};
bitset >>= 7;
std::array<std::uint8_t, 4> out;
for (auto b = out.rbegin(); b != out.rend(); ++b, bitset >>= 8)
*b = (bitset & Bitset{0xFF}).to_ulong();
return out;
}
And then:
void foo(std::uint8_t[4]);
void bar() {
std::array<std::uint8_t, 3> command{0xCA, 0xBB, 0x80};
std::array<std::uint8_t, 4> out = left_pad(command);
foo(out.data());
}
If the input length is fixed to 3 bytes and no generalization for larger lengths is needed, std::bitset<8 * 4>
can be replaced with std::uint32_t
.
Addition after discussion in comments.
This equivalent version
std::array<std::uint8_t, 4>
left_pad2(const std::array<std::uint8_t, 3>& in) {
using Bitset = std::bitset<8 * 4>;
Bitset bitset;
for (auto b = in.begin(); b != in.end(); ++b) {
bitset <<= 8;
bitset |= Bitset{*b};
}
bitset <<= 1;
std::array<std::uint8_t, 4> out;
for (auto b = out.rbegin(); b != out.rend(); ++b, bitset >>= 8)
*b = (bitset & Bitset{0xFF}).to_ulong();
return out;
}
gives better assembly code with GCC and -O3
optimization:
left_pad2(std::array<unsigned char, 3ul> const&):
movzx eax, BYTE PTR [rdi]
movzx edx, BYTE PTR [rdi+1]
sal rax, 8
or rax, rdx
movzx edx, BYTE PTR [rdi+2]
sal rax, 8
or rax, rdx
add rax, rax
bswap eax
ret
versus
left_pad(std::array<unsigned char, 3ul> const&):
movzx eax, BYTE PTR [rdi]
movzx edx, BYTE PTR [rdi+1]
sal rax, 8
or rax, rdx
movzx edx, BYTE PTR [rdi+2]
sal rax, 8
or rax, rdx
sal rax, 8
mov rdx, rax
shr rdx, 7
mov BYTE PTR [rsp-1], dl
mov rdx, rax
shr rdx, 15
mov BYTE PTR [rsp-2], dl
mov rdx, rax
shr rax, 31
shr rdx, 23
mov BYTE PTR [rsp-4], al
mov BYTE PTR [rsp-3], dl
mov eax, DWORD PTR [rsp-4]
ret
Upvotes: 3