Skip to content

Commit 640ede2

Browse files
committed
decoder: improved redesign
1 parent 774b8ce commit 640ede2

File tree

4 files changed

+163
-53
lines changed

4 files changed

+163
-53
lines changed

decoder.c

+28-12
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ static const char *prog_name = "hufdec";
1818

1919
void usage(void)
2020
{
21-
fprintf(stderr, "USAGE: %s FILE_IN FILE_OUT\n", prog_name);
21+
fprintf(stderr, "USAGE: %s FILE_IN [FILE_OUT]\n", prog_name);
2222
exit(EXIT_FAILURE);
2323
}
2424

@@ -62,21 +62,33 @@ void decode(FILE *in, FILE *out)
6262
}
6363

6464
/* how many bytes for the output or how many symbols to read */
65-
uint8_t tmp[sizeof(uint32_t)];
66-
if (fread(tmp, sizeof(uint32_t), 1, in) != 1) {
65+
uint8_t tmp[4];
66+
if (fread(tmp, 4, 1, in) != 1) {
6767
fprintf(stderr, "Couldn't read number of data\n");
6868
exit(EXIT_FAILURE);
6969
}
7070

7171
uint32_t num_sym = (tmp[0] << 24) | (tmp[1] << 16) | (tmp[2] << 8) | tmp[3];
7272

73-
struct huff_dec *dec = huff_gen_dec(&header[5], symbols);
73+
struct huff_dec dec;
74+
if (!huff_gen_dec(&header[5], symbols, &dec)) {
75+
fprintf(stderr, "Couldn't create decoder\n");
76+
exit(EXIT_FAILURE);
77+
}
7478
struct bit_reader *reader = bit_reader_create(in);
7579

76-
huff_decode_all(dec, reader, out, num_sym);
80+
if (reader == NULL) {
81+
fprintf(stderr, "Couldn't create bit reader\n");
82+
exit(EXIT_FAILURE);
83+
}
84+
85+
if (!huff_decode_file(&dec, num_sym, reader, out)) {
86+
fprintf(stderr, "Error while decoding\n");
87+
exit(EXIT_FAILURE);
88+
}
7789

7890
bit_reader_destroy(reader);
79-
huff_destroy(dec);
91+
huff_destroy(&dec);
8092
}
8193

8294
int main(int argc, char *argv[])
@@ -86,7 +98,7 @@ int main(int argc, char *argv[])
8698
if (argc > 1)
8799
prog_name = argv[0];
88100

89-
if (argc != 3)
101+
if (argc != 3 && argc != 2)
90102
usage();
91103

92104
FILE *in = fopen(argv[1], "rb");
@@ -95,15 +107,19 @@ int main(int argc, char *argv[])
95107
return EXIT_FAILURE;
96108
}
97109

98-
FILE *out = fopen(argv[2], "wb");
99-
if (out == NULL) {
100-
perror("Couldn't open output file");
101-
return EXIT_FAILURE;
110+
FILE *out;
111+
if (argc == 3) {
112+
out = fopen(argv[2], "wb");
113+
if (out == NULL) {
114+
perror("Couldn't open output file");
115+
return EXIT_FAILURE;
116+
}
117+
} else {
118+
out = stdout;
102119
}
103120

104121
decode(in, out);
105122

106-
107123
fclose(in);
108124
fclose(out);
109125

File renamed without changes.

huff_dec.c

+120-37
Original file line numberDiff line numberDiff line change
@@ -9,40 +9,48 @@
99
#include "bit_reader.h"
1010
#include "huff_dec.h"
1111

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)
2114
{
2215
assert(code_len != NULL);
2316
assert(symbols != NULL);
17+
assert(decoder != NULL);
2418

25-
uint8_t num_sym = 0;
19+
uint16_t num_sym = 0;
2620
uint8_t max_bits = 0;
2721
uint8_t min_bits = 0;
2822

2923
for (int i = 0; i < 16; i++) {
3024
num_sym += code_len[i];
3125
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;
3332
}
3433

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);
3637

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+
}
4149

4250
uint8_t sym_index = 0;
4351
size_t index = 0;
4452

45-
uint16_t times = 1 << max_bits;
53+
uint32_t times = 1 << max_bits;
4654
for (int i = 0; i < 16; i++) {
4755
times >>= 1;
4856

@@ -51,46 +59,123 @@ struct huff_dec *huff_gen_dec(uint8_t code_len[restrict 16], uint8_t symbols[res
5159
sym_index++;
5260

5361
for (uint16_t t = 0; t < times; t++) {
54-
dec->entries[index] = (symbol << 8) | (i + 1);
62+
decoder->entries[index] = (symbol << 8) | (i + 1);
5563
index++;
64+
assert(index <= num_entries);
5665
}
5766
}
5867
}
5968

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;
6176
}
6277

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])
6481
{
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)) {
71100
fprintf(stderr, "Error while reading input\n");
72101
return false;
73102
}
74103

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;
76117

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];
79158
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);
82163

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+
}
84168

85169
if (i == num_sym - 1)
86170
break;
87171

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)) {
90174
fprintf(stderr, "Error while reading input\n");
91175
return false;
92176
}
93-
sym = ((sym << len) | tmp) & mask;
177+
178+
code = (code << length) | tmp;
94179
}
95180

96181
return true;
@@ -99,8 +184,6 @@ bool huff_decode_all(struct huff_dec *dec, struct bit_reader *reader, FILE *out,
99184
void huff_destroy(struct huff_dec *dec)
100185
{
101186
assert(dec != NULL);
102-
103187
free(dec->entries);
104-
free(dec);
105188
}
106189

huff_dec.h

+15-4
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,22 @@
1313
#include <stdio.h>
1414
#include "bit_reader.h"
1515

16-
struct huff_dec;
16+
struct huff_dec {
17+
uint8_t max_bits; /* num_entries = 1 << num_bits; */
18+
uint8_t min_bits;
1719

18-
struct huff_dec *huff_gen_dec(uint8_t code_len[restrict 16], uint8_t symbols[restrict]);
19-
bool huff_decode_all(struct huff_dec *tree, struct bit_reader *reader, FILE *out, uint32_t num_sym);
20-
void huff_destroy(struct huff_dec *tree);
20+
/* high byte: symbol; low byte: num_bits; invalid code if num_bits = 0 */
21+
uint16_t *entries;
22+
};
23+
24+
bool huff_gen_dec(uint8_t code_len[restrict 16], uint8_t symbols[restrict],
25+
struct huff_dec * restrict decoder);
26+
bool huff_decode_file(const struct huff_dec * restrict decoder, size_t num_sym,
27+
struct bit_reader * restrict reader, FILE *out);
28+
bool huff_decode(const struct huff_dec * restrict decoder, size_t num_sym,
29+
struct bit_reader * restrict reader,
30+
uint8_t out_buf[restrict]);
31+
void huff_destroy(struct huff_dec *dec);
2132

2233
#endif
2334

0 commit comments

Comments
 (0)