Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
att
GitHub Repository: att/ast
Path: blob/master/src/cmd/pack/huffdecode.c
1808 views
1
/***********************************************************************
2
* *
3
* This software is part of the ast package *
4
* Copyright (c) 1993-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
* David Korn <[email protected]> *
18
* *
19
***********************************************************************/
20
#pragma prototyped
21
/*
22
* huffman coding decoding
23
*
24
* David Korn
25
* AT&T Laboratories
26
*/
27
28
#include "huffman.h"
29
30
#define CHUNK 9
31
#define END (1<<CHAR_BIT)
32
#define fillbuff(b,left,bit,inp) while(left<(bit))\
33
{\
34
if(inp>=inend && !(inp=getbuff())) \
35
return(-1); \
36
left+=CHAR_BIT;\
37
b = (b<<CHAR_BIT)|*inp++; \
38
}
39
/* read <n> bits from buffer <b> */
40
#define getbits(b,left,n) (((b)>>(left-=(n)))&((1L<<(n))-1))
41
/* return <n> bits */
42
#define putbits(b,left,n) (left+=(n))
43
44
static long lastid = 1;
45
static long id = 1;
46
static unsigned char outchar[(1<<CHUNK)];
47
static char numbits[(1<<CHUNK)];
48
static short intnodes[HUFFLEV+1];
49
static char *tree[HUFFLEV+1];
50
static char characters[END];
51
static char *eof;
52
static unsigned char *inbuff,*inend;
53
static Sfio_t *infile;
54
static void decode_header(Huff_t *);
55
static unsigned char *getbuff(void);
56
57
/*
58
* decode <input> using huffman tree defined in <hp> onto <output>
59
* if size>0, then decode until size bytes have been decoded
60
* otherwise, the complete file is decoded.
61
* The number of bytes written is returned or -1 on error
62
*/
63
64
Sfoff_t huffdecode(register Huff_t *hp,Sfio_t *input,Sfio_t *output,int size)
65
{
66
register long buffer;
67
register int left, i, n;
68
register int lev = 0;
69
register unsigned char *outp;
70
register unsigned char *inp;
71
unsigned char *outend;
72
unsigned char *outbuff;
73
Sfoff_t insize = hp->outsize;
74
/* decode the header if called with different hp */
75
if(lastid!=hp->id)
76
{
77
decode_header(hp);
78
if(!hp->id)
79
hp->id = id++;
80
lastid = hp->id;
81
}
82
/* set up output buffers for faster access */
83
if(!(outp=outbuff=(unsigned char*)sfreserve(output,SF_UNBOUND,SF_LOCKR)))
84
return(sfvalue(output));
85
n = sfvalue(output);
86
if(size>=0)
87
{
88
if(n > size)
89
n = size;
90
size -= n;
91
}
92
outend = outp+n;
93
/* set up input buffers for faster access */
94
infile = input;
95
if(!(inp=inbuff=(unsigned char*)sfreserve(infile,SF_UNBOUND,0)))
96
return(sfvalue(infile));
97
inend = inp + sfvalue(infile);
98
buffer = hp->buffer;
99
left = hp->left;
100
/* main decoding loop */
101
while (1)
102
{
103
if(lev==0)
104
{
105
fillbuff(buffer,left,hp->maxlev,inp);
106
i = getbits(buffer,left,CHUNK);
107
if((n=(numbits[i]-1)) >= 0)
108
{
109
putbits(buffer,left,n);
110
*outp++ = outchar[i];
111
goto pout;
112
}
113
if(hp->excess)
114
{
115
putbits(buffer,left,hp->excess);
116
i >>= hp->excess;
117
}
118
lev = CHUNK-hp->excess;
119
}
120
i <<= 1;
121
i += getbits(buffer,left,1);
122
if ((n = i - intnodes[lev+1]) >= 0)
123
{
124
{
125
register char *p = &tree[lev+1][n];
126
if (p == eof)
127
{
128
size = 0;
129
outend = outp;
130
}
131
else
132
*outp++ = *p;
133
}
134
pout:
135
if(outp >= outend)
136
{
137
n = outp - outbuff;
138
hp->outsize +=n;
139
if(sfwrite(output,outbuff,n)<0)
140
return(-1);
141
if(size==0)
142
{
143
hp->buffer = buffer;
144
hp->left = left;
145
sfread(infile, inbuff,inp-inbuff);
146
return(hp->outsize-insize);
147
}
148
if(!(outp=outbuff=(unsigned char*)sfreserve(output,SF_UNBOUND,SF_LOCKR)))
149
return(-1);
150
n = sfvalue(output);
151
if(size>0)
152
{
153
if(n > size)
154
n = size;
155
size -= n;
156
}
157
outp = outbuff;
158
outend = outp + n;
159
}
160
lev = 0;
161
}
162
else
163
lev++;
164
}
165
}
166
167
static void decode_header(register Huff_t *hp)
168
{
169
register int c, i, n, k;
170
eof = &characters[0];
171
for (i=1; i<=hp->maxlev; i++)
172
{
173
intnodes[i] = hp->levcount[i];
174
tree[i] = eof;
175
for (c=0; c < (1<<CHAR_BIT); c++)
176
{
177
if (hp->length[c] == i)
178
*eof++ = c;
179
}
180
}
181
intnodes[hp->maxlev] += 2;
182
/*
183
* convert intnodes[i] to be number of
184
* internal nodes possessed by level i
185
*/
186
for (n=0, i=hp->maxlev; i>=1; i--)
187
{
188
c = intnodes[i];
189
intnodes[i] = n /= 2;
190
n += c;
191
}
192
/* compute output char and number of bits used for each CHUNK of bits */
193
c = (1<<CHUNK) -1;
194
for (i=1; i<=CHUNK; i++)
195
{
196
for(k = tree[i+1] - tree[i];--k>=0;)
197
{
198
for(n=0; n < 1<<(CHUNK-i); n++)
199
{
200
numbits[c] = CHUNK+1-i;
201
outchar[c--] = tree[i][k];
202
}
203
}
204
}
205
if(hp->maxlev <= CHUNK)
206
{
207
hp->excess = CHUNK+1-hp->maxlev;
208
hp->maxlev = CHUNK;
209
}
210
while(c >=0)
211
numbits[c--] = 0;
212
}
213
214
static unsigned char *getbuff(void)
215
{
216
register int n;
217
register unsigned char *cp;
218
if(cp=(unsigned char*)sfreserve(infile,SF_UNBOUND,0))
219
inbuff = cp;
220
n = sfvalue(infile);
221
if(!cp && n<0)
222
return(cp);
223
inend = inbuff + n;
224
return(inbuff);
225
}
226
227