9
9
#include "bit_reader.h"
10
10
#include "huff_dec.h"
11
11
12
- struct huff_dec {
13
- uint8_t max_bits ; /* num_entries = 1 << num_bits; */
14
- uint8_t min_bits ;
15
-
16
- /* high byte: symbol; low byte: num_bits; invalid code if num_bits = 0 */
17
- uint16_t * entries ;
18
- };
19
-
20
- struct huff_dec * huff_gen_dec (uint8_t code_len [restrict 16 ], uint8_t symbols [restrict])
12
+ bool huff_gen_dec (uint8_t code_len [restrict 16 ], uint8_t symbols [restrict],
13
+ struct huff_dec * restrict decoder )
21
14
{
22
15
assert (code_len != NULL );
23
16
assert (symbols != NULL );
17
+ assert (decoder != NULL );
24
18
25
- uint8_t num_sym = 0 ;
19
+ uint16_t num_sym = 0 ;
26
20
uint8_t max_bits = 0 ;
27
21
uint8_t min_bits = 0 ;
28
22
29
23
for (int i = 0 ; i < 16 ; i ++ ) {
30
24
num_sym += code_len [i ];
31
25
max_bits = (code_len [i ] != 0 ) ? i + 1 : max_bits ;
32
- min_bits = (min_bits == 0 && code_len [i ] != 0 ) ? i + 1 : min_bits ;
26
+ min_bits = (min_bits == 0 ) ? i + 1 : min_bits ;
27
+ }
28
+
29
+ if (num_sym > 256 && num_sym == 0 ) {
30
+ fprintf (stderr , "Invalid number of symbols\n" );
31
+ return false;
33
32
}
34
33
35
- uint8_t num_entries = 1 << max_bits ;
34
+ assert (min_bits <= max_bits );
35
+ assert (0 < max_bits && max_bits <= 16 );
36
+ assert (0 < min_bits && min_bits <= 16 );
36
37
37
- struct huff_dec * dec = calloc (1 , sizeof (* dec ));
38
- dec -> max_bits = max_bits ;
39
- dec -> min_bits = min_bits ;
40
- dec -> entries = malloc (sizeof (uint16_t ) * num_entries );
38
+ uint16_t num_entries = 1 << max_bits ;
39
+ assert (num_entries != 0 );
40
+
41
+ decoder -> max_bits = max_bits ;
42
+ decoder -> min_bits = min_bits ;
43
+ decoder -> entries = malloc (sizeof (uint16_t ) * num_entries );
44
+
45
+ if (decoder -> entries == NULL ) {
46
+ perror ("Couldn't allocate memory for decode table\n" );
47
+ return false;
48
+ }
41
49
42
50
uint8_t sym_index = 0 ;
43
51
size_t index = 0 ;
44
52
45
- uint16_t times = 1 << max_bits ;
53
+ uint32_t times = 1 << max_bits ;
46
54
for (int i = 0 ; i < 16 ; i ++ ) {
47
55
times >>= 1 ;
48
56
@@ -51,46 +59,123 @@ struct huff_dec *huff_gen_dec(uint8_t code_len[restrict 16], uint8_t symbols[res
51
59
sym_index ++ ;
52
60
53
61
for (uint16_t t = 0 ; t < times ; t ++ ) {
54
- dec -> entries [index ] = (symbol << 8 ) | (i + 1 );
62
+ decoder -> entries [index ] = (symbol << 8 ) | (i + 1 );
55
63
index ++ ;
64
+ assert (index <= num_entries );
56
65
}
57
66
}
58
67
}
59
68
60
- return dec ;
69
+ if (index != num_entries ) {
70
+ fprintf (stderr , "Invalid decode header. Missing entries in decode table\n" );
71
+ free (decoder -> entries );
72
+ return false;
73
+ }
74
+
75
+ return true;
61
76
}
62
77
63
- bool huff_decode_all (struct huff_dec * dec , struct bit_reader * reader , FILE * out , uint32_t num_sym )
78
+ bool huff_decode (const struct huff_dec * restrict decoder , size_t num_sym ,
79
+ struct bit_reader * restrict reader ,
80
+ uint8_t out_buf [restrict])
64
81
{
65
- assert (dec != NULL );
66
- assert (reader != NULL );
67
- assert (out != NULL );
68
-
69
- uint16_t sym ;
70
- if (!bit_reader_next_bits (reader , & sym , dec -> max_bits )) {
82
+ assert (decoder != NULL );
83
+ assert (reader != NULL );
84
+ assert (out_buf != NULL );
85
+
86
+ if (num_sym == 0 )
87
+ return true;
88
+
89
+ /* FIXME this only works when decoding starts at byte boundary. Add functions
90
+ to push back bits in bit_reader and extend decoding to decode at any bit
91
+ position. */
92
+
93
+ uint16_t code ;
94
+ uint8_t max_bits = decoder -> max_bits ;
95
+ const uint16_t mask = (1 << max_bits ) - 1 ;
96
+ uint16_t * table = decoder -> entries ;
97
+
98
+ /* FIXME special case with less than max_bits in the data stream. */
99
+ if (!bit_reader_next_bits (reader , & code , max_bits )) {
71
100
fprintf (stderr , "Error while reading input\n" );
72
101
return false;
73
102
}
74
103
75
- const uint16_t mask = (1 << dec -> max_bits ) - 1 ;
104
+ for (size_t i = 0 ; i < num_sym ; i ++ ) {
105
+ code &= mask ;
106
+ uint16_t entry = table [code ];
107
+ uint8_t symbol = (entry >> 8 ) & 0xFF ;
108
+ uint8_t length = entry & 0xFF ;
109
+
110
+ assert (length != 0 );
111
+ assert (length <= max_bits );
112
+
113
+ out_buf [i ] = symbol ;
114
+
115
+ if (i == num_sym - 1 )
116
+ break ;
76
117
77
- for (uint32_t i = 0 ; i < num_sym ; i ++ ) {
78
- uint16_t entry = dec -> entries [sym & mask ];
118
+ uint16_t tmp = 0 ;
119
+ if (!bit_reader_next_bits (reader , & tmp , length )) {
120
+ fprintf (stderr , "Error while reading input\n" );
121
+ return false;
122
+ }
123
+
124
+ code = (code << length ) | tmp ;
125
+ }
126
+
127
+ return true;
128
+ }
129
+
130
+ bool huff_decode_file (const struct huff_dec * restrict decoder , size_t num_sym ,
131
+ struct bit_reader * restrict reader , FILE * out )
132
+ {
133
+ assert (decoder != NULL );
134
+ assert (reader != NULL );
135
+ assert (out != NULL );
136
+
137
+ if (num_sym == 0 )
138
+ return true;
139
+
140
+ /* FIXME this only works when decoding starts at byte boundary. Add functions
141
+ to push back bits in bit_reader and extend decoding to decode at any bit
142
+ position. */
143
+
144
+ uint16_t code ;
145
+ uint8_t max_bits = decoder -> max_bits ;
146
+ const uint16_t mask = (1 << max_bits ) - 1 ;
147
+ uint16_t * table = decoder -> entries ;
148
+
149
+ /* FIXME special case with less than max_bits in the data stream. */
150
+ if (!bit_reader_next_bits (reader , & code , max_bits )) {
151
+ fprintf (stderr , "Error while reading input\n" );
152
+ return false;
153
+ }
154
+
155
+ for (size_t i = 0 ; i < num_sym ; i ++ ) {
156
+ code &= mask ;
157
+ uint16_t entry = table [code ];
79
158
uint8_t symbol = (entry >> 8 ) & 0xFF ;
80
- uint8_t len = entry & 0xFF ;
81
- assert (len <= dec -> max_bits );
159
+ uint8_t length = entry & 0xFF ;
160
+
161
+ assert (length != 0 );
162
+ assert (length <= max_bits );
82
163
83
- fwrite (& symbol , 1 , 1 , out );
164
+ if (fwrite (& symbol , 1 , 1 , out ) != 1 ) {
165
+ fprintf (stderr , "Error while writing output symbols\n" );
166
+ return false;
167
+ }
84
168
85
169
if (i == num_sym - 1 )
86
170
break ;
87
171
88
- uint16_t tmp ;
89
- if (!bit_reader_next_bits (reader , & tmp , len )) {
172
+ uint16_t tmp = 0 ;
173
+ if (!bit_reader_next_bits (reader , & tmp , length )) {
90
174
fprintf (stderr , "Error while reading input\n" );
91
175
return false;
92
176
}
93
- sym = ((sym << len ) | tmp ) & mask ;
177
+
178
+ code = (code << length ) | tmp ;
94
179
}
95
180
96
181
return true;
@@ -99,8 +184,6 @@ bool huff_decode_all(struct huff_dec *dec, struct bit_reader *reader, FILE *out,
99
184
void huff_destroy (struct huff_dec * dec )
100
185
{
101
186
assert (dec != NULL );
102
-
103
187
free (dec -> entries );
104
- free (dec );
105
188
}
106
189
0 commit comments