|
| 1 | +# bit |
| 2 | + |
| 3 | +Source code: https://github.com/intel/cpp-std-extensions/blob/main/include/stdx/bit.hpp |
| 4 | +Documentation: https://intel.github.io/cpp-std-extensions/#_bit_hpp |
| 5 | + |
| 6 | +## No more manual bit twiddling! |
| 7 | + |
| 8 | +A lot of the functionality in this header exists to put an end to manual bit |
| 9 | +shifting, masking, etc. Yes it's easy, but it's not simple. Manual bit |
| 10 | +operations are prone to sign and integer promotion errors, and sprinkling |
| 11 | +`static_cast` everywhere to guard against this makes things ugly and less |
| 12 | +understandable. |
| 13 | + |
| 14 | +## `to_be`, `from_be`, `to_le`, `from_le` |
| 15 | + |
| 16 | +`to_be` and `from_be` have identical implementations. As do `to_le` and |
| 17 | +`from_le`. But they are different in showing the intent of user code. And also |
| 18 | +different in pre and post conditions: |
| 19 | + |
| 20 | +```cpp |
| 21 | +// pre: x is big-endian |
| 22 | +// post: x is platform-endian |
| 23 | +auto x = stdx::from_be(y); |
| 24 | + |
| 25 | +// pre: x is platform-endian |
| 26 | +// post: x is big-endian |
| 27 | +auto x = stdx::to_be(y); |
| 28 | +``` |
| 29 | + |
| 30 | +In other words, the use of `from_be`/`to_be` is very different from the use of |
| 31 | +`std::byteswap` in cross-platform friendly code. |
| 32 | + |
| 33 | +## `bit_pack` and `bit_unpack` |
| 34 | + |
| 35 | +These functions have some interesting endianness concerns. It is important that |
| 36 | +the functions round-trip properly. |
| 37 | + |
| 38 | +```cpp |
| 39 | +std::uint8_t a{0x12u}, b{0x34u}, c{0x56u}, d{0x78u}; |
| 40 | +auto x = stdx::bit_pack<std::uint32_t>(a, b, c, d); |
| 41 | +auto [a_, b_, c_, d_] = stdx::bit_unpack<std::uint8_t>(x); |
| 42 | +// a == a_, b == b_; c == c_, d == d_ |
| 43 | +``` |
| 44 | +
|
| 45 | +This also means that that "written order" (big-endian) is the expected ordering. |
| 46 | +
|
| 47 | +```cpp |
| 48 | +auto [a, b, c, d] = stdx::bit_unpack<std::uint8_t>(0x12345678u); |
| 49 | +// a == 0x12, b == 0x34; c == 0x56, d == 0x78 |
| 50 | +``` |
| 51 | + |
| 52 | +## `bit_destructure` |
| 53 | + |
| 54 | +`bit_destructure` and `bit_unpack` are similar, but where `bit_unpack` is |
| 55 | +"big-endian" (for the above reasons), `bit_destructure` is "little-endian". |
| 56 | +Because it makes sense to count **up** in bits. |
| 57 | + |
| 58 | +Also, N split points mean N+1 values. |
| 59 | + |
| 60 | +```cpp |
| 61 | +auto [a, b, c, d] = stdx::bit_destructure<8, 16, 24>(0x12345678u); |
| 62 | +// a == 0x78, b == 0x56; c == 0x34, d == 0x12 |
| 63 | +``` |
0 commit comments