|
| 1 | +#include "bitstream.h" |
| 2 | + |
| 3 | +#include <assert.h> |
| 4 | +#include <limits.h> |
| 5 | +#include <stdlib.h> |
| 6 | + |
| 7 | +/* Closes a bitstream by consuming all remaining bits. |
| 8 | + * Returns false if CHAR_BIT or more bits remain in the stream or if any remaining bits are non-zero. |
| 9 | + * |
| 10 | + * Precondition: NULL != stream |
| 11 | + */ |
| 12 | +bool closeBitstream(bitstream* stream) { |
| 13 | + if (1 < stream->len) return false; /* If there is more than one byte remaining. */ |
| 14 | + if (1 == stream->len && /* If there is one byte remaining */ |
| 15 | + (0 == stream->offset || /* and either no bits have been consumed */ |
| 16 | + 0 != (*stream->arr & (UCHAR_MAX >> stream->offset)) /* or any of the unconsumed bits are non-zero */ |
| 17 | + )) return false; |
| 18 | + /* Otherwise there are either 0 bits remaining or there are between 1 and CHAR_BITS-1 bits remaining and they are all zero. */ |
| 19 | + *stream = (bitstream){0}; |
| 20 | + return true; |
| 21 | +} |
| 22 | + |
| 23 | +/* Fetches up to 31 bits from 'stream' as the 'n' least significant bits of return value. |
| 24 | + * The 'n' bits are set from the MSB to the LSB. |
| 25 | + * Returns 'SIMPLICITY_ERR_BITSTREAM_EOF' if not enough bits are available. |
| 26 | + * |
| 27 | + * Precondition: 0 <= n < 32 |
| 28 | + * NULL != stream |
| 29 | + */ |
| 30 | +int32_t readNBits(int n, bitstream* stream) { |
| 31 | + assert(0 <= n && n < 32); |
| 32 | + |
| 33 | + uint32_t result = 0; |
| 34 | + while (CHAR_BIT <= stream->offset + n) { |
| 35 | + if (!stream->len) return SIMPLICITY_ERR_BITSTREAM_EOF; |
| 36 | + n -= CHAR_BIT - stream->offset; |
| 37 | + result |= (uint32_t)(*stream->arr & (UCHAR_MAX >> stream->offset)) << n; |
| 38 | + stream->arr++; stream->len--; stream->offset = 0; |
| 39 | + } |
| 40 | + /* stream->offset + n < CHAR_BIT */ |
| 41 | + if (n) { |
| 42 | + if (!stream->len) return SIMPLICITY_ERR_BITSTREAM_EOF; |
| 43 | + stream->offset += (unsigned char)n; |
| 44 | + result |= (*stream->arr >> (CHAR_BIT - stream->offset)) & ((UCHAR_MAX >> (CHAR_BIT - n))); |
| 45 | + } |
| 46 | + return (int32_t)result; |
| 47 | +} |
| 48 | +/* Decode an encoded bitstring up to length 1. |
| 49 | + * If successful returns the length of the bitstring and 'result' contains the decoded bits. |
| 50 | + * The decoded bitstring is stored in the LSBs of 'result', with the LSB being the last bit decoded. |
| 51 | + * Any remaining bits in 'result' are reset to 0. |
| 52 | + * If the decoded bitstring would be too long 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned ('result' may be modified). |
| 53 | + * If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned ('result' may be modified). |
| 54 | + * If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned ('result' may be modified). |
| 55 | + * |
| 56 | + * Precondition: NULL != result |
| 57 | + * NULL != stream |
| 58 | + */ |
| 59 | +static int32_t decodeUpto1Bit(int32_t* result, bitstream* stream) { |
| 60 | + *result = read1Bit(stream); |
| 61 | + if (*result <= 0) return *result; |
| 62 | + |
| 63 | + *result = read1Bit(stream); |
| 64 | + if (*result < 0) return *result; |
| 65 | + if (0 != *result) return SIMPLICITY_ERR_DATA_OUT_OF_RANGE; |
| 66 | + |
| 67 | + *result = read1Bit(stream); |
| 68 | + if (*result < 0) return *result; |
| 69 | + return 1; |
| 70 | +} |
| 71 | + |
| 72 | +/* Decode an encoded number between 1 and 3 inclusive. |
| 73 | + * When successful returns the decoded result. |
| 74 | + * If the decoded value would be too large, 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned. |
| 75 | + * If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned. |
| 76 | + * If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned. |
| 77 | + * |
| 78 | + * Precondition: NULL != stream |
| 79 | + */ |
| 80 | +static int32_t decodeUpto3(bitstream* stream) { |
| 81 | + int32_t result; |
| 82 | + int32_t len = decodeUpto1Bit(&result, stream); |
| 83 | + if (len < 0) return len; |
| 84 | + result |= 1 << len; |
| 85 | + return result; |
| 86 | +} |
| 87 | + |
| 88 | +/* Decode an encoded bitstring up to length 3. |
| 89 | + * If successful returns the length of the bitstring and 'result' contains the decoded bits. |
| 90 | + * The decoded bitstring is stored in the LSBs of 'result', with the LSB being the last bit decoded. |
| 91 | + * Any remaining bits in 'result' are reset to 0. |
| 92 | + * If the decoded bitstring would be too long 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned ('result' may be modified). |
| 93 | + * If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned ('result' may be modified). |
| 94 | + * If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned ('result' may be modified). |
| 95 | + * |
| 96 | + * Precondition: NULL != result |
| 97 | + * NULL != stream |
| 98 | + */ |
| 99 | +static int32_t decodeUpto3Bits(int32_t* result, bitstream* stream) { |
| 100 | + int32_t bit = read1Bit(stream); |
| 101 | + if (bit < 0) return bit; |
| 102 | + |
| 103 | + *result = 0; |
| 104 | + if (0 == bit) { |
| 105 | + return 0; |
| 106 | + } else { |
| 107 | + int32_t n = decodeUpto3(stream); |
| 108 | + if (0 <= n) { |
| 109 | + *result = readNBits(n, stream); |
| 110 | + if (*result < 0) return *result; |
| 111 | + } |
| 112 | + return n; |
| 113 | + } |
| 114 | +} |
| 115 | + |
| 116 | +/* Decode an encoded number between 1 and 15 inclusive. |
| 117 | + * When successful returns the decoded result. |
| 118 | + * If the decoded value would be too large, 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned. |
| 119 | + * If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned. |
| 120 | + * If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned. |
| 121 | + * |
| 122 | + * Precondition: NULL != stream |
| 123 | + */ |
| 124 | +static int32_t decodeUpto15(bitstream* stream) { |
| 125 | + int32_t result; |
| 126 | + int32_t len = decodeUpto3Bits(&result, stream); |
| 127 | + if (len < 0) return len; |
| 128 | + result |= 1 << len; |
| 129 | + return result; |
| 130 | +} |
| 131 | + |
| 132 | +/* Decode an encoded bitstring up to length 15. |
| 133 | + * If successful returns the length of the bitstring and 'result' contains the decoded bits. |
| 134 | + * The decoded bitstring is stored in the LSBs of 'result', with the LSB being the last bit decoded. |
| 135 | + * Any remaining bits in 'result' are reset to 0. |
| 136 | + * If the decoded bitstring would be too long 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned ('result' may be modified). |
| 137 | + * If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned ('result' may be modified). |
| 138 | + * If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned ('result' may be modified). |
| 139 | + * |
| 140 | + * Precondition: NULL != result |
| 141 | + * NULL != stream |
| 142 | + */ |
| 143 | +static int32_t decodeUpto15Bits(int32_t* result, bitstream* stream) { |
| 144 | + int32_t bit = read1Bit(stream); |
| 145 | + if (bit < 0) return bit; |
| 146 | + |
| 147 | + *result = 0; |
| 148 | + if (0 == bit) { |
| 149 | + return 0; |
| 150 | + } else { |
| 151 | + int32_t n = decodeUpto15(stream); |
| 152 | + if (0 <= n) { |
| 153 | + *result = readNBits(n, stream); |
| 154 | + if (*result < 0) return *result; |
| 155 | + } |
| 156 | + return n; |
| 157 | + } |
| 158 | +} |
| 159 | + |
| 160 | +/* Decode an encoded number between 1 and 65535 inclusive. |
| 161 | + * When successful returns the decoded result. |
| 162 | + * If the decoded value would be too large, 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned. |
| 163 | + * If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned. |
| 164 | + * If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned. |
| 165 | + * |
| 166 | + * Precondition: NULL != stream |
| 167 | + */ |
| 168 | +static int32_t decodeUpto65535(bitstream* stream) { |
| 169 | + int32_t result; |
| 170 | + int32_t len = decodeUpto15Bits(&result, stream); |
| 171 | + if (len < 0) return len; |
| 172 | + result |= 1 << len; |
| 173 | + return result; |
| 174 | +} |
| 175 | + |
| 176 | +/* Decode an encoded number between 1 and 2^31 - 1 inclusive. |
| 177 | + * When successful returns the decoded result. |
| 178 | + * If the decoded value would be too large, 'SIMPLICITY_ERR_DATA_OUT_OF_RANGE' is returned. |
| 179 | + * If more bits are needed than available in the 'stream', 'SIMPLICITY_ERR_BITSTRING_EOF' is returned. |
| 180 | + * If an I/O error occurs when reading from the 'stream', 'SIMPLICITY_ERR_BISTRING_ERROR' is returned. |
| 181 | + * |
| 182 | + * Precondition: NULL != stream |
| 183 | + */ |
| 184 | +int32_t decodeUptoMaxInt(bitstream* stream) { |
| 185 | + int32_t bit = read1Bit(stream); |
| 186 | + if (bit < 0) return bit; |
| 187 | + if (0 == bit) { |
| 188 | + return 1; |
| 189 | + } else { |
| 190 | + int32_t n = decodeUpto65535(stream); |
| 191 | + if (n < 0) return n; |
| 192 | + if (30 < n) return SIMPLICITY_ERR_DATA_OUT_OF_RANGE; |
| 193 | + { |
| 194 | + int32_t result = readNBits(n, stream); |
| 195 | + if (result < 0) return result; |
| 196 | + return ((1 << n) | result); |
| 197 | + } |
| 198 | + } |
| 199 | +} |
| 200 | + |
| 201 | +/* Fills a 'bitstring' containing 'n' bits from 'stream'. |
| 202 | + * Returns 'SIMPLICITY_ERR_BITSTREAM_EOF' if not enough bits are available. |
| 203 | + * If successful, '*result' is set to a bitstring with 'n' bits read from 'stream' and 0 is returned. |
| 204 | + * |
| 205 | + * If an error is returned '*result' might be modified. |
| 206 | + * |
| 207 | + * Precondition: NULL != result |
| 208 | + * n <= 2^31 |
| 209 | + * NULL != stream |
| 210 | + */ |
| 211 | +int32_t readBitstring(bitstring* result, size_t n, bitstream* stream) { |
| 212 | + static_assert(0x8000u + 2*(CHAR_BIT - 1) <= SIZE_MAX, "size_t needs to be at least 32-bits"); |
| 213 | + assert(n <= 0x8000u); |
| 214 | + size_t total_offset = n + stream->offset; |
| 215 | + /* |= stream->len * CHAR_BIT < total_offset iff stream->len < (total_offset + (CHAR_BIT - 1)) / CHAR_BIT */ |
| 216 | + if (stream->len < (total_offset + (CHAR_BIT - 1)) / CHAR_BIT) return SIMPLICITY_ERR_BITSTREAM_EOF; |
| 217 | + /* total_offset <= stream->len * CHAR_BIT */ |
| 218 | + *result = (bitstring) |
| 219 | + { .arr = stream->arr |
| 220 | + , .offset = stream->offset |
| 221 | + , .len = n |
| 222 | + }; |
| 223 | + { |
| 224 | + size_t delta = total_offset / CHAR_BIT; |
| 225 | + stream->arr += delta; stream->len -= delta; |
| 226 | + stream->offset = total_offset % CHAR_BIT; |
| 227 | + /* Note that if 0 == stream->len then 0 == stream->offset. */ |
| 228 | + } |
| 229 | + return 0; |
| 230 | +} |
0 commit comments