| 1 | /* -*- C++ -*- |
| 2 | SPDX-FileCopyrightText: 1998 Netscape Communications Corporation <developer@mozilla.org> |
| 3 | |
| 4 | SPDX-License-Identifier: MIT |
| 5 | */ |
| 6 | |
| 7 | #ifndef nsPkgInt_h__ |
| 8 | #define nsPkgInt_h__ |
| 9 | |
| 10 | #include <array> |
| 11 | #include <concepts> |
| 12 | #include <cstdint> |
| 13 | |
| 14 | namespace kencodingprober |
| 15 | { |
| 16 | typedef enum { |
| 17 | eIdxSft4bits = 3, |
| 18 | eIdxSft8bits = 2, |
| 19 | eIdxSft16bits = 1, |
| 20 | } nsIdxSft; |
| 21 | |
| 22 | typedef enum { |
| 23 | eSftMsk4bits = 7, |
| 24 | eSftMsk8bits = 3, |
| 25 | eSftMsk16bits = 1, |
| 26 | } nsSftMsk; |
| 27 | |
| 28 | typedef enum { |
| 29 | eBitSft4bits = 2, |
| 30 | eBitSft8bits = 3, |
| 31 | eBitSft16bits = 4, |
| 32 | } nsBitSft; |
| 33 | |
| 34 | typedef enum { |
| 35 | eUnitMsk4bits = 0x0000000FL, |
| 36 | eUnitMsk8bits = 0x000000FFL, |
| 37 | eUnitMsk16bits = 0x0000FFFFL, |
| 38 | } nsUnitMsk; |
| 39 | |
| 40 | typedef struct nsPkgInt { |
| 41 | nsIdxSft idxsft; |
| 42 | nsSftMsk sftmsk; |
| 43 | nsBitSft bitsft; |
| 44 | nsUnitMsk unitmsk; |
| 45 | const unsigned int *data; |
| 46 | } nsPkgInt; |
| 47 | } |
| 48 | |
| 49 | constexpr auto PCKXBITS(std::convertible_to<uint8_t> auto... il) |
| 50 | { |
| 51 | constexpr auto N = sizeof...(il); |
| 52 | std::array<uint32_t, N / 8> val = {0}; |
| 53 | |
| 54 | int pos = 0; |
| 55 | for (auto i : {uint8_t(il)...}) { |
| 56 | val[pos / 8] |= (i << (4 * (pos % 8))); |
| 57 | pos++; |
| 58 | } |
| 59 | return val; |
| 60 | } |
| 61 | static_assert(PCKXBITS(il: 0, il: 0, il: 0, il: 0, il: 0, il: 0, il: 0, il: 0) == std::array<uint32_t, 1>{0x00000000}); |
| 62 | static_assert(PCKXBITS(il: 0, il: 0, il: 0, il: 0, il: 0, il: 0, il: 0, il: 1) == std::array<uint32_t, 1>{0x10000000}); |
| 63 | static_assert(PCKXBITS(il: 1, il: 0, il: 0, il: 0, il: 0, il: 0, il: 0, il: 0) == std::array<uint32_t, 1>{0x00000001}); |
| 64 | static_assert(PCKXBITS(il: 1, il: 2, il: 3, il: 4, il: 5, il: 6, il: 7, il: 8) == std::array<uint32_t, 1>{0x87654321}); |
| 65 | static_assert(PCKXBITS(il: 8, il: 7, il: 6, il: 5, il: 4, il: 3, il: 2, il: 1) == std::array<uint32_t, 1>{0x12345678}); |
| 66 | |
| 67 | constexpr unsigned int GETFROMPCK(int index, const kencodingprober::nsPkgInt &table) |
| 68 | { |
| 69 | const auto high = index >> table.idxsft; |
| 70 | const auto low = (index & table.sftmsk) << table.bitsft; |
| 71 | |
| 72 | uint32_t data = table.data[high] >> low; |
| 73 | return data & table.unitmsk; |
| 74 | } |
| 75 | |
| 76 | namespace |
| 77 | { |
| 78 | using namespace kencodingprober; |
| 79 | constexpr std::array data{ |
| 80 | // clang-format off |
| 81 | PCKXBITS(il: 1, il: 2, il: 3, il: 4, il: 5, il: 6, il: 7, il: 8, |
| 82 | il: 15, il: 14, il: 13, il: 12, il: 11, il: 10, il: 9, il: 8), |
| 83 | // clang-format on |
| 84 | }; |
| 85 | constexpr nsPkgInt table{.idxsft: eIdxSft4bits, .sftmsk: eSftMsk4bits, .bitsft: eBitSft4bits, .unitmsk: eUnitMsk4bits, .data: data.data()}; |
| 86 | |
| 87 | static_assert(GETFROMPCK(index: 0, table) == 1); |
| 88 | static_assert(GETFROMPCK(index: 9, table) == 14); |
| 89 | static_assert(GETFROMPCK(index: 15, table) == 8); |
| 90 | } |
| 91 | |
| 92 | #endif /* nsPkgInt_h__ */ |
| 93 | |