#include <stdlib.h>
#include <assert.h>
+#include "bytesource.h"
#include "dehuff.h"
+#include "input.h"
-void reliable_read(raw_input_func_t* input_func, void* userdata, uint8_t* buf, size_t len)
-{
- while (len > 0) {
- ssize_t bytes_read = input_func(userdata, buf, len);
- assert(bytes_read <= len);
-
- // TODO: We need better error handling here. setjmp()/longjmp()
- // should hopefully do the trick, but we need to take care for
- // suspension.
- if (bytes_read == (ssize_t)-1) {
- fprintf(stderr, "Input function returned error\n");
- exit(1);
- }
- if (bytes_read == 0) {
- fprintf(stderr, "Premature EOF\n");
- exit(1);
- }
-
- buf += bytes_read;
- len -= bytes_read;
- }
-}
-
-uint16_t read_length(raw_input_func_t* input_func, void* userdata)
-{
- uint8_t buf[2];
- reliable_read(input_func, userdata, buf, 2);
- return (buf[0] << 8) | buf[1];
-}
-
-void read_huffman_tables(huffman_tables_t* dst, raw_input_func_t* input_func, void* userdata)
+void read_huffman_tables(huffman_tables_t* dst, input_func_t* input_func, void* userdata)
{
size_t len = read_length(input_func, userdata);
assert(len > 2);
j += tbl->num_codes[i];
tbl->maxcode[i] = tbl->huffcode[j - 1];
}
+
+ // Generate the lookup tables
+ for (unsigned i = 0; i < DEHUF_TABLE_SIZE; ++i) {
+ tbl->lookup_table_codes[i] = DEHUF_SLOW_PATH;
+ tbl->lookup_table_length[i] = DEHUF_SLOW_PATH;
+ }
+
+ unsigned k = 0;
+ for (unsigned i = 0; i < 16; ++i) {
+ for (unsigned j = 0; j < tbl->num_codes[i]; ++j, ++k) {
+ const unsigned code = tbl->huffcode[k];
+ const unsigned length = tbl->huffsize[k];
+ if (length > DEHUF_TABLE_BITS) {
+ continue;
+ }
+ const unsigned prefix_min = code << (DEHUF_TABLE_BITS - length);
+ const unsigned prefix_max = ((code + 1) << (DEHUF_TABLE_BITS - length));
+
+ for (unsigned elem = prefix_min; elem < prefix_max; ++elem) {
+ assert(tbl->lookup_table_codes[elem] == DEHUF_SLOW_PATH);
+ assert(tbl->lookup_table_length[elem] == DEHUF_SLOW_PATH);
+ tbl->lookup_table_codes[elem] = k;
+ tbl->lookup_table_length[elem] = length;
+ }
+ }
+ }
}
free(buf);
}
+
+unsigned read_huffman_symbol_slow_path(const struct huffman_table* table,
+ struct bit_source* source) {
+ possibly_refill(source, 1);
+ unsigned code = read_bits(source, 1);
+ int i = 0;
+
+ while (table->maxcode[i] == -1 || code > (unsigned)table->maxcode[i]) {
+ possibly_refill(source, 1);
+ code = (code << 1) | read_bits(source, 1);
+ ++i;
+
+ if (i > 15) {
+ fprintf(stderr, "Error in Huffman decoding: Too long code (%x)\n", code);
+ exit(1);
+ }
+ }
+
+ return table->codes[table->valptr[i] + code - table->mincode[i]];
+}