1 /**
2  * @file test_huff_code.c Test Huffman coding
3  * @author David Huggins-Daines <dhuggins@cs.cmu.edu>
4  */
5 
6 #include "huff_code.h"
7 #include "test_macros.h"
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 
13 int32 const ivalues[10] = {
14 	1, 2, 3, 5, 7, 11, 13, 17, 19, 23
15 };
16 int32 const frequencies[10] = {
17 	42, 4, 5, 6, 225, 15001, 3, 2, 87, 1003
18 };
19 char * const svalues[10] = {
20 	"foo", "bar", "baz", "quux", "argh",
21 	"hurf", "burf", "blatz", "unf", "woof"
22 };
23 char * const svalues2[10] = {
24 	"1","2","3","4","5","6","7","8","9","10"
25 };
26 char const cdata[7] = { 0x08, 0x30, 0x40, 0x4c, 0x00, 0x04, 0x50 };
27 
28 void
29 test_intcode(huff_code_t *hc)
30 {
31 	FILE *fh;
32 	char const *dptr;
33 	int i, offset;
34 	size_t dlen;
35 	int32 val;
36 
37 	fh = fopen("hufftest.out", "wb");
38 	huff_code_attach(hc, fh, "wb");
39 	for (i = 0; i < 10; ++i) {
40 		huff_code_encode_int(hc, ivalues[i], NULL);
41 	}
42 	huff_code_detach(hc);
43 	fclose(fh);
44 	fh = fopen("hufftest.out", "rb");
45 	huff_code_attach(hc, fh, "rb");
46 	for (i = 0; i < 10; ++i) {
47 		int32 val;
48 		huff_code_decode_int(hc, &val, NULL, NULL, 0);
49 		printf("%d ", val);
50 		TEST_EQUAL(val, ivalues[i]);
51 	}
52 	printf("\n");
53 	huff_code_detach(hc);
54 	fclose(fh);
55 
56 	dptr = cdata;
57 	dlen = 7;
58 	offset = 0;
59 	for (i = 0; i < 10; ++i) {
60 		huff_code_decode_int(hc, &val, &dptr, &dlen, &offset);
61 		printf("%d ", val);
62 		TEST_EQUAL(val, ivalues[i]);
63 	}
64 	TEST_EQUAL(dlen, 1);
65 	TEST_EQUAL(offset, 4);
66 	printf("\n");
67 
68 	dptr = cdata;
69 	dlen = 7;
70 	offset = 0;
71 	i = 0;
72 	while (huff_code_decode_int(hc, &val, &dptr, &dlen, &offset) != -1) {
73 		printf("%d ", val);
74 		TEST_EQUAL(val, ivalues[i++]);
75 	}
76 	TEST_EQUAL(dlen, 1);
77 	TEST_EQUAL(offset, 4);
78 	printf("\n");
79 }
80 
81 void
82 test_strcode(huff_code_t *hc, char * const *svalues)
83 {
84 	FILE *fh;
85 	char const *dptr;
86 	int i, offset;
87 	size_t dlen;
88 
89 	fh = fopen("hufftest.out", "wb");
90 	huff_code_attach(hc, fh, "wb");
91 	for (i = 9; i >= 0; --i) {
92 		huff_code_encode_str(hc, svalues[i], NULL);
93 	}
94 	huff_code_detach(hc);
95 	fclose(fh);
96 	fh = fopen("hufftest.out", "rb");
97 	huff_code_attach(hc, fh, "rb");
98 	for (i = 9; i >= 0; --i) {
99 		char const *val = huff_code_decode_str(hc, NULL, NULL, 0);
100 		printf("%s ", val);
101 		TEST_EQUAL(0, strcmp(val, svalues[i]));
102 	}
103 	printf("\n");
104 	huff_code_detach(hc);
105 	fclose(fh);
106 
107 	dptr = cdata;
108 	dlen = 7;
109 	offset = 0;
110 	for (i = 0; i < 10; ++i) {
111 		char const *val = huff_code_decode_str(hc, &dptr, &dlen, &offset);
112 		printf("%s ", val);
113 		TEST_EQUAL(0, strcmp(val, svalues[i]));
114 	}
115 	TEST_EQUAL(dlen, 1);
116 	TEST_EQUAL(offset, 4);
117 	printf("\n");
118 }
119 
120 int
121 main(int argc, char *argv[])
122 {
123 	huff_code_t *hc;
124 	FILE *fh;
125 
126 	hc = huff_code_build_int(ivalues, frequencies, 10);
127 	huff_code_dump(hc, stdout);
128 	test_intcode(hc);
129 	fh = fopen("huffcode.out", "wb");
130 	huff_code_write(hc, fh);
131 	fclose(fh);
132 	huff_code_free(hc);
133 
134 	fh = fopen("huffcode.out", "rb");
135 	hc = huff_code_read(fh);
136 	fclose(fh);
137 	test_intcode(hc);
138 	huff_code_free(hc);
139 
140 	hc = huff_code_build_str(svalues, frequencies, 10);
141 	huff_code_dump(hc, stdout);
142 	test_strcode(hc, svalues);
143 	fh = fopen("huffcode.out", "wb");
144 	huff_code_write(hc, fh);
145 	fclose(fh);
146 	huff_code_free(hc);
147 
148 	fh = fopen("huffcode.out", "rb");
149 	hc = huff_code_read(fh);
150 	fclose(fh);
151 	test_strcode(hc, svalues);
152 	huff_code_free(hc);
153 
154 	hc = huff_code_build_str(svalues2, frequencies, 10);
155 	huff_code_dump(hc, stdout);
156 	test_strcode(hc, svalues2);
157 	huff_code_free(hc);
158 
159 	return 0;
160 }
161 
162