in source/huffman.c [213:285]
int aws_huffman_decode(
struct aws_huffman_decoder *decoder,
struct aws_byte_cursor *to_decode,
struct aws_byte_buf *output) {
AWS_ASSERT(decoder);
AWS_ASSERT(decoder->coder);
AWS_ASSERT(to_decode);
AWS_ASSERT(output);
struct decoder_state state;
state.decoder = decoder;
state.input_cursor = to_decode;
/* Measures how much of the input was read */
size_t bits_left = decoder->num_bits + to_decode->len * 8;
while (1) {
decode_fill_working_bits(&state);
uint8_t symbol;
uint8_t bits_read = decoder->coder->decode(
(uint32_t)(decoder->working_bits >> (BITSIZEOF(decoder->working_bits) - MAX_PATTERN_BITS)),
&symbol,
decoder->coder->userdata);
if (bits_read == 0) {
if (bits_left < MAX_PATTERN_BITS) {
/* More input is needed to continue */
return AWS_OP_SUCCESS;
}
/* Unknown symbol found */
return aws_raise_error(AWS_ERROR_COMPRESSION_UNKNOWN_SYMBOL);
}
if (bits_read > bits_left) {
/* Check if the buffer has been overrun.
Note: because of the check in decode_fill_working_bits,
the buffer won't actually overrun, instead there will
be 0's in the bottom of working_bits. */
return AWS_OP_SUCCESS;
}
if (output->len == output->capacity) {
/* Check if we've hit the end of the output buffer.
* Grow buffer, or raise error, depending on settings */
if (decoder->allow_growth) {
/* Double the capacity */
if (aws_byte_buf_reserve_relative(output, output->capacity)) {
return AWS_OP_ERR;
}
} else {
return aws_raise_error(AWS_ERROR_SHORT_BUFFER);
}
}
bits_left -= bits_read;
decoder->working_bits <<= bits_read;
decoder->num_bits -= bits_read;
/* Store the found symbol */
aws_byte_buf_write_u8(output, symbol);
/* Successfully decoded whole buffer */
if (bits_left == 0) {
return AWS_OP_SUCCESS;
}
}
/* This case is unreachable */
AWS_ASSERT(0);
}