Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/lib/libvcodex/Vchuff/vchuffman.c
1810 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 2003-2011 AT&T Intellectual Property *
5
* and is licensed under the *
6
* Eclipse Public License, Version 1.0 *
7
* by AT&T Intellectual Property *
8
* *
9
* A copy of the License is available at *
10
* http://www.eclipse.org/org/documents/epl-v10.html *
11
* (with md5 checksum b35adb5213ca9657e911e9befb180842) *
12
* *
13
* Information and Software Systems Research *
14
* AT&T Research *
15
* Florham Park NJ *
16
* *
17
* Phong Vo <[email protected]> *
18
* *
19
***********************************************************************/
20
#include "vchhdr.h"
21
22
/* Static Huffman encoding.
23
**
24
** Written by Kiem-Phong Vo ([email protected])
25
*/
26
27
/* internal handle for Huffman coder and decoder */
28
typedef struct _vchuff_s
29
{ ssize_t freq[VCH_SIZE]; /* frequencies of bytes */
30
ssize_t size[VCH_SIZE]; /* encoding lengths */
31
Vcbit_t bits[VCH_SIZE]; /* encoding bits */
32
ssize_t maxs; /* max code size */
33
Vchtrie_t* trie; /* re-trie for decoding */
34
int type;
35
} Vchuff_t;
36
37
/* sentinels to tell that application has set these tables */
38
#define VCH_HASFREQ (1<<15)
39
#define VCH_HASSIZE (1<<14)
40
41
/* Copy frequencies, code sizes and code bits into a Vcodex handle. */
42
#if __STD_C
43
int vchcopy(Vcodex_t* vc, ssize_t* freq, ssize_t* size , ssize_t maxs)
44
#else
45
int vchcopy(vc, freq, size, maxs )
46
Vcodex_t* vc;
47
ssize_t* freq; /* byte frequency table */
48
ssize_t* size; /* code length table */
49
ssize_t maxs; /* max length of any code */
50
#endif
51
{
52
Vchuff_t *huff = vcgetmtdata(vc, Vchuff_t*);
53
54
huff->type = 0;
55
huff->maxs = 0;
56
if(freq)
57
{ memcpy(huff->freq, freq, VCH_SIZE*sizeof(freq[0]));
58
huff->type |= VCH_HASFREQ;
59
}
60
if(size && maxs >= 0 && maxs < 32)
61
{ memcpy(huff->size, size, VCH_SIZE*sizeof(size[0]));
62
huff->maxs = maxs;
63
huff->type |= VCH_HASSIZE;
64
}
65
66
return 0;
67
}
68
69
#if __STD_C
70
static ssize_t vchuff(Vcodex_t* vc, const Void_t* data, size_t dtsz, Void_t** out)
71
#else
72
static ssize_t vchuff(vc, data, dtsz, out)
73
Vcodex_t* vc;
74
Void_t* data; /* data to be encoded */
75
size_t dtsz;
76
Void_t** out; /* return encoded data */
77
#endif
78
{
79
reg Vcbit_t b;
80
reg ssize_t n;
81
ssize_t s;
82
Vcchar_t *output, *dt, *enddt;
83
Vcio_t io;
84
Vchuff_t *huff = vcgetmtdata(vc, Vchuff_t*);
85
ssize_t *freq = huff->freq;
86
ssize_t *size = huff->size;
87
Vcbit_t *bits = huff->bits;
88
89
if(dtsz == 0) /* no data to compress */
90
return 0;
91
92
/* compute code frequencies and lengths */
93
if(!(huff->type&VCH_HASFREQ) )
94
{ CLRTABLE(freq, VCH_SIZE);
95
ADDFREQ(freq, Vcchar_t*, data, dtsz);
96
huff->type = 0;
97
}
98
if(!(huff->type&VCH_HASSIZE) &&
99
(huff->maxs = vchsize(VCH_SIZE,freq,size,NIL(int*))) < 0)
100
return -1;
101
huff->type = 0;
102
103
/* estimate compressed size */
104
if(huff->maxs > 0)
105
{ DOTPRODUCT(s, freq, size, VCH_SIZE);
106
s = (s+7)/8; /* round up to byte count */
107
}
108
else s = 1;
109
s += vcsizeu(dtsz) + 1;
110
111
/* set up buffer for output */
112
s += VCH_SIZE;
113
if(!(output = vcbuffer(vc, NIL(Vcchar_t*), s, 0)) )
114
return -1;
115
vcioinit(&io, output, s);
116
117
huff->maxs = vchbits(VCH_SIZE, size, bits); /* compute bits per byte */
118
vcioputu(&io, dtsz); /* size of raw data */
119
vcioputc(&io, huff->maxs); /* the control code */
120
121
/**/DEBUG_PRINT(2,"Vchuff: inputsz=%d ",dtsz);
122
enddt = (dt = (Vcchar_t*)data) + dtsz;
123
if(huff->maxs == 0) /* a single run */
124
vcioputc(&io, *dt);
125
else
126
{ /* output the code tree */
127
if((s = vchputcode(VCH_SIZE, size, huff->maxs, vcionext(&io), vciomore(&io))) <= 0)
128
return -1;
129
else vcioskip(&io,s);
130
/**/DEBUG_PRINT(2,"headsz=%d ",vciosize(&io));
131
132
vciosetb(io, b, n, VC_ENCODE);
133
for(; dt < enddt; ++dt)
134
vcioaddb(&io, b, n, bits[*dt], size[*dt]);
135
vcioendb(&io, b, n, VC_ENCODE); /* flush any remaining bits */
136
}
137
138
dt = output;
139
s = vciosize(&io); /**/DEBUG_PRINT(2,"cmpsz=%d\n",s);
140
if(vcrecode(vc, &output, &s, 0, 0) < 0 )
141
return -1;
142
if(dt != output)
143
vcbuffer(vc, dt, -1, -1);
144
145
if(out)
146
*out = output;
147
return s;
148
}
149
150
#if __STD_C
151
static ssize_t vcunhuff(Vcodex_t* vc, const Void_t* orig, size_t dtsz, Void_t** out)
152
#else
153
static ssize_t vcunhuff(vc, orig, dtsz, out)
154
Vcodex_t* vc;
155
Void_t* orig; /* data to be decoded */
156
size_t dtsz;
157
Void_t** out; /* return decoded data */
158
#endif
159
{
160
reg Vcbit_t b;
161
ssize_t n, p, sz, ntop;
162
short *node, *size;
163
Vcchar_t *o, *endo, *output, *data;
164
Vcio_t io;
165
Vchuff_t *huff = vcgetmtdata(vc, Vchuff_t*);
166
167
if(dtsz == 0)
168
return 0;
169
170
data = (Vcchar_t*)orig; sz = (ssize_t)dtsz;
171
if(vcrecode(vc, &data, &sz, 0, 0) < 0 )
172
return -1;
173
dtsz = sz;
174
175
vcioinit(&io, data, dtsz);
176
sz = (ssize_t)vciogetu(&io);
177
178
if(!(output = vcbuffer(vc, NIL(Vcchar_t*), sz, 0)) )
179
return -1;
180
endo = (o = output)+sz;
181
182
if((sz = vciogetc(&io)) == 0 )
183
{ n = vciogetc(&io);
184
while(o < endo)
185
*o++ = n;
186
}
187
else
188
{ if((n = vchgetcode(VCH_SIZE, huff->size, sz, vcionext(&io), vciomore(&io))) < 0)
189
return -1;
190
else vcioskip(&io,n);
191
192
if(vchbits(VCH_SIZE, huff->size, huff->bits) < 0)
193
return -1;
194
if(huff->trie)
195
vchdeltrie(huff->trie);
196
if(!(huff->trie = vchbldtrie(VCH_SIZE, huff->size, huff->bits)) )
197
return -1;
198
node = huff->trie->node;
199
size = huff->trie->size;
200
ntop = huff->trie->ntop;
201
202
vciosetb(&io, b, n, VC_DECODE); /* associate b,n as bit vector */
203
for(sz = ntop, p = 0;; )
204
{ vciofilb(&io, b, n, sz);
205
206
p += (b >> (VC_BITSIZE-sz)); /* slot to look into */
207
if(size[p] > 0) /* byte is found */
208
{ vciodelb(&io, b, n, size[p]); /* consume bits */
209
*o = (Vcchar_t)node[p]; /* decode the byte */
210
if((o += 1) >= endo)
211
break;
212
sz = ntop; p = 0; /* restart at trie top */
213
}
214
else if(size[p] == 0) /* corrupted data */
215
return -1;
216
else
217
{ vciodelb(&io, b, n, sz); /* consume bits */
218
sz = -size[p]; p = node[p]; /* trie recursion */
219
}
220
}
221
vcioendb(&io, b, n, VC_DECODE);
222
}
223
224
if(data != orig)
225
vcbuffer(vc, data, -1, -1);
226
227
if(out)
228
*out = output;
229
return o-output;
230
}
231
232
#if __STD_C
233
static int huffevent(Vcodex_t* vc, int type, Void_t* params)
234
#else
235
static int huffevent(vc, type, params)
236
Vcodex_t* vc;
237
int type;
238
Void_t* params;
239
#endif
240
{
241
Vchuff_t *huff;
242
243
if(type == VC_OPENING)
244
{ if(!(huff = (Vchuff_t*)malloc(sizeof(Vchuff_t))) )
245
return -1;
246
huff->trie = NIL(Vchtrie_t*);
247
huff->maxs = 0;
248
huff->type = 0;
249
vcsetmtdata(vc, huff);
250
return 0;
251
}
252
else if(type == VC_CLOSING)
253
{ if((huff = vcgetmtdata(vc, Vchuff_t*)) )
254
{ if(huff->trie)
255
vchdeltrie(huff->trie);
256
free(huff);
257
}
258
vcsetmtdata(vc, NIL(Vchuff_t*));
259
return 0;
260
}
261
else return 0;
262
}
263
264
Vcmethod_t _Vchuffman =
265
{ vchuff,
266
vcunhuff,
267
huffevent,
268
"huffman", "Huffman encoding.",
269
"[-version?huffman (AT&T Research) 2003-01-01]" USAGE_LICENSE,
270
NIL(Vcmtarg_t*),
271
1024*1024,
272
0
273
};
274
275
VCLIB(Vchuffman)
276
277