diff --git a/deflated.original b/deflated.original index 0892b339f7276bf3488c14cf51327f5c15c843e0..5666cb41916c6b3ac8878666871ad350b696aeb1 100644 Binary files a/deflated.original and b/deflated.original differ diff --git a/include/inflate.h b/include/inflate.h index 5c6611792c12d5459d30988073107810d80e3cb8..9cb5705806447ff4864568316c847224277be278 100644 --- a/include/inflate.h +++ b/include/inflate.h @@ -25,8 +25,11 @@ typedef struct huffman { /* Reset the position state variable */ void reset_pos(); -/* Create a Huffman mapping from a sequence of lengths. */ -huffman_t *make_huffman(int *lens, int *alphabet, int n_symbols); +/* + * Create a Huffman mapping from a sequence of lengths. + * The alphabet used is (0, 1, ..., n_symbols - 1) + */ +huffman_t *make_huffman(int *lens, int n_symbols); /* Clean up a heap allocated Huffman map */ void destroy_huffman(huffman_t *hf); diff --git a/tests/inflate_test.cpp b/tests/inflate_test.cpp index 4d5df583da8938443d56ffe3d53cd1a7085ed895..53fbf797d3aba71d0fd761a03a274ac20bffa92b 100644 --- a/tests/inflate_test.cpp +++ b/tests/inflate_test.cpp @@ -78,10 +78,79 @@ TEST (BufferTests, RevStreamOrderTest) { ASSERT_EQ (get_n_bits((char *) buf, 6, true), 36); } +/* Test making a huffman tree from a sequence of lengths */ +TEST (HuffmanTests, TestMakeHuffman) { + int n_symbols = 8; + int lens[8] = {3, 3, 3, 3, 3, 2, 4, 4}; + + huffman_t *hf = make_huffman(lens, n_symbols); + + int bl_counts[MAX_LENGTH + 1] = {0, 0, 1, 5, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + /* Check bl_counts */ + for (int i = 0; i < MAX_LENGTH + 1; i++) { + ASSERT_EQ (hf->bl_counts[i], bl_counts[i]); + } + + /* + * Check min_codes for entries with non-zero bl_count + * It doesn't really matter what the other entries are. + */ + ASSERT_EQ (hf->min_codes[2], 0); + ASSERT_EQ (hf->min_codes[3], 2); + ASSERT_EQ (hf->min_codes[4], 14); + + /* Check that the alphabet arrays were populated correctly. */ + ASSERT_EQ (hf->alphabet[2][0], 5); + for (int i = 0; i < 5; i++) ASSERT_EQ (hf->alphabet[3][i], i); + ASSERT_EQ (hf->alphabet[4][0], 6); + ASSERT_EQ (hf->alphabet[4][1], 7); + + destroy_huffman(hf); +} + +/* + * Test that make_huffman does not assign a code to symbols with + * a length of 0. + */ +TEST (HuffmanTests, TestMakeHuffmanZeroLens) { + int n_symbols = 8; + int lens[8] = {1, 0, 2, 3, 3, 0, 4, 3}; + + huffman_t *hf = make_huffman(lens, n_symbols); + + int bl_counts[MAX_LENGTH + 1] = {0, 1, 1, 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + + /* Check bl_counts */ + for (int i = 0; i < MAX_LENGTH + 1; i++) { + ASSERT_EQ (hf->bl_counts[i], bl_counts[i]); + } + + /* Check min_codes */ + ASSERT_EQ (hf->min_codes[1], 0); + ASSERT_EQ (hf->min_codes[2], 2); + ASSERT_EQ (hf->min_codes[3], 6); + ASSERT_EQ (hf->min_codes[4], 18); + + /* Check alphabet. */ + ASSERT_EQ (hf->alphabet[1][0], 0); + + /* 1 and 5 are not used! (length = 0) */ + ASSERT_EQ (hf->alphabet[2][0], 2); + + ASSERT_EQ (hf->alphabet[3][0], 3); + ASSERT_EQ (hf->alphabet[3][1], 4); + ASSERT_EQ (hf->alphabet[3][2], 7); + + ASSERT_EQ (hf->alphabet[4][0], 6); + + destroy_huffman(hf); +} + // TODO -TEST (HuffmanTests, TestMakeHuffman) {} +TEST (HuffmanTests, TestReadChunk) { -TEST (HuffmanTests, TestReadChunk) {} +} TEST (HuffmanTests, TestReadLens) {}