diff options
Diffstat (limited to 'lib/rbcodec/codecs/libayumi/lzh.c')
-rw-r--r-- | lib/rbcodec/codecs/libayumi/lzh.c | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libayumi/lzh.c b/lib/rbcodec/codecs/libayumi/lzh.c new file mode 100644 index 0000000000..786d3bbafe --- /dev/null +++ b/lib/rbcodec/codecs/libayumi/lzh.c | |||
@@ -0,0 +1,420 @@ | |||
1 | #include "lzh.h" | ||
2 | |||
3 | #include <string.h> | ||
4 | |||
5 | #define BUFSIZE (1024 * 4) | ||
6 | |||
7 | typedef unsigned char uchar; | ||
8 | typedef unsigned short ushort; | ||
9 | typedef unsigned int uint; | ||
10 | typedef unsigned long ulong; | ||
11 | |||
12 | #ifndef CHAR_BIT | ||
13 | #define CHAR_BIT 8 | ||
14 | #endif | ||
15 | |||
16 | #ifndef UCHAR_MAX | ||
17 | #define UCHAR_MAX 255 | ||
18 | #endif | ||
19 | |||
20 | typedef ushort BITBUFTYPE; | ||
21 | |||
22 | #define BITBUFSIZ (CHAR_BIT * sizeof(BITBUFTYPE)) | ||
23 | #define DICBIT 13 /* 12(-lh4-) or 13(-lh5-) */ | ||
24 | #define DICSIZ (1U << DICBIT) | ||
25 | #define MAXMATCH 256 /* formerly F (not more than UCHAR_MAX + 1) */ | ||
26 | #define THRESHOLD 3 /* choose optimal value */ | ||
27 | #define NC (UCHAR_MAX + MAXMATCH + 2 - THRESHOLD) /* alphabet = {0, 1, 2, ..., NC - 1} */ | ||
28 | #define CBIT 9 /* $\lfloor \log_2 NC \rfloor + 1$ */ | ||
29 | #define CODE_BIT 16 /* codeword length */ | ||
30 | |||
31 | #define MAX_HASH_VAL (3 * DICSIZ + (DICSIZ / 512 + 1) * UCHAR_MAX) | ||
32 | |||
33 | #define NP (DICBIT + 1) | ||
34 | #define NT (CODE_BIT + 3) | ||
35 | #define PBIT 4 /* smallest integer such that (1U << PBIT) > NP */ | ||
36 | #define TBIT 5 /* smallest integer such that (1U << TBIT) > NT */ | ||
37 | #if NT > NP | ||
38 | #define NPT NT | ||
39 | #else | ||
40 | #define NPT NP | ||
41 | #endif | ||
42 | |||
43 | uchar *m_pSrc; | ||
44 | int m_srcSize; | ||
45 | uchar *m_pDst; | ||
46 | int m_dstSize; | ||
47 | |||
48 | int DataIn(void *pBuffer, int nBytes); | ||
49 | int DataOut(void *pOut, int nBytes); | ||
50 | |||
51 | void fillbuf(int n); | ||
52 | ushort getbits(int n); | ||
53 | void init_getbits(void); | ||
54 | int make_table(int nchar, uchar *bitlen, int tablebits, ushort *table); | ||
55 | void read_pt_len(int nn, int nbit, int i_special); | ||
56 | void read_c_len(void); | ||
57 | ushort decode_c(void); | ||
58 | ushort decode_p(void); | ||
59 | void huf_decode_start(void); | ||
60 | void decode_start(void); | ||
61 | void decode(uint count, uchar buffer[]); | ||
62 | |||
63 | int fillbufsize; | ||
64 | uchar buf[BUFSIZE]; | ||
65 | uchar outbuf[DICSIZ]; | ||
66 | ushort left[2 * NC - 1]; | ||
67 | ushort right[2 * NC - 1]; | ||
68 | BITBUFTYPE bitbuf; | ||
69 | uint subbitbuf; | ||
70 | int bitcount; | ||
71 | int decode_j; /* remaining bytes to copy */ | ||
72 | uchar c_len[NC]; | ||
73 | uchar pt_len[NPT]; | ||
74 | uint blocksize; | ||
75 | ushort c_table[4096]; | ||
76 | ushort pt_table[256]; | ||
77 | int with_error; | ||
78 | |||
79 | uint fillbuf_i; /* NOTE: these ones are not initialized at constructor time but inside the fillbuf and decode func. */ | ||
80 | uint decode_i; | ||
81 | |||
82 | /* Additions */ | ||
83 | |||
84 | int DataIn(void *pBuffer, int nBytes) | ||
85 | { | ||
86 | const int np = (nBytes <= m_srcSize) ? nBytes : m_srcSize; | ||
87 | if (np > 0) { | ||
88 | memcpy(pBuffer, m_pSrc, np); | ||
89 | m_pSrc += np; | ||
90 | m_srcSize -= np; | ||
91 | } | ||
92 | return np; | ||
93 | } | ||
94 | |||
95 | int DataOut(void *pBuffer, int nBytes) | ||
96 | { | ||
97 | const int np = (nBytes <= m_dstSize) ? nBytes : m_dstSize; | ||
98 | if (np > 0) { | ||
99 | memcpy(m_pDst, pBuffer, np); | ||
100 | m_pDst += np; | ||
101 | m_dstSize -= np; | ||
102 | } | ||
103 | return np; | ||
104 | } | ||
105 | |||
106 | /* io.c */ | ||
107 | |||
108 | /* Shift bitbuf n bits left, read n bits */ | ||
109 | void fillbuf(int n) | ||
110 | { | ||
111 | bitbuf = (bitbuf << n) & 0xffff; | ||
112 | while (n > bitcount) { | ||
113 | bitbuf |= subbitbuf << (n -= bitcount); | ||
114 | if (fillbufsize == 0) { | ||
115 | fillbuf_i = 0; | ||
116 | fillbufsize = DataIn(buf, BUFSIZE - 32); | ||
117 | } | ||
118 | if (fillbufsize > 0) | ||
119 | fillbufsize--, subbitbuf = buf[fillbuf_i++]; | ||
120 | else | ||
121 | subbitbuf = 0; | ||
122 | bitcount = CHAR_BIT; | ||
123 | } | ||
124 | bitbuf |= subbitbuf >> (bitcount -= n); | ||
125 | } | ||
126 | |||
127 | ushort getbits(int n) | ||
128 | { | ||
129 | ushort x; | ||
130 | x = bitbuf >> (BITBUFSIZ - n); | ||
131 | fillbuf(n); | ||
132 | return x; | ||
133 | } | ||
134 | |||
135 | void init_getbits(void) | ||
136 | { | ||
137 | bitbuf = 0; | ||
138 | subbitbuf = 0; | ||
139 | bitcount = 0; | ||
140 | fillbuf(BITBUFSIZ); | ||
141 | } | ||
142 | |||
143 | /* maketbl.c */ | ||
144 | |||
145 | int make_table(int nchar, uchar * bitlen, int tablebits, ushort * table) | ||
146 | { | ||
147 | ushort count[17], weight[17], start[18], *p; | ||
148 | uint jutbits, avail, mask; | ||
149 | int i, ch, len, nextcode; | ||
150 | |||
151 | for (i = 1; i <= 16; i++) | ||
152 | count[i] = 0; | ||
153 | for (i = 0; i < nchar; i++) | ||
154 | count[bitlen[i]]++; | ||
155 | |||
156 | start[1] = 0; | ||
157 | for (i = 1; i <= 16; i++) | ||
158 | start[i + 1] = start[i] + (count[i] << (16 - i)); | ||
159 | if (start[17] != (ushort) (1U << 16)) | ||
160 | return (1); /* error: bad table */ | ||
161 | |||
162 | jutbits = 16 - tablebits; | ||
163 | for (i = 1; i <= tablebits; i++) { | ||
164 | start[i] >>= jutbits; | ||
165 | weight[i] = 1U << (tablebits - i); | ||
166 | } | ||
167 | while (i <= 16) { | ||
168 | weight[i] = 1U << (16 - i); | ||
169 | i++; | ||
170 | } | ||
171 | |||
172 | i = start[tablebits + 1] >> jutbits; | ||
173 | if (i != (ushort) (1U << 16)) { | ||
174 | int k = 1U << tablebits; | ||
175 | while (i != k) | ||
176 | table[i++] = 0; | ||
177 | } | ||
178 | |||
179 | avail = nchar; | ||
180 | mask = 1U << (15 - tablebits); | ||
181 | for (ch = 0; ch < nchar; ch++) { | ||
182 | if ((len = bitlen[ch]) == 0) | ||
183 | continue; | ||
184 | nextcode = start[len] + weight[len]; | ||
185 | if (len <= tablebits) { | ||
186 | for (i = start[len]; i < nextcode; i++) | ||
187 | table[i] = ch; | ||
188 | } else { | ||
189 | uint k = start[len]; | ||
190 | p = &table[k >> jutbits]; | ||
191 | i = len - tablebits; | ||
192 | while (i != 0) { | ||
193 | if (*p == 0) { | ||
194 | right[avail] = left[avail] = 0; | ||
195 | *p = avail++; | ||
196 | } | ||
197 | if (k & mask) | ||
198 | p = &right[*p]; | ||
199 | else | ||
200 | p = &left[*p]; | ||
201 | k <<= 1; | ||
202 | i--; | ||
203 | } | ||
204 | *p = ch; | ||
205 | } | ||
206 | start[len] = nextcode; | ||
207 | } | ||
208 | return (0); | ||
209 | } | ||
210 | |||
211 | /* huf.c */ | ||
212 | |||
213 | void read_pt_len(int nn, int nbit, int i_special) | ||
214 | { | ||
215 | int i, n; | ||
216 | short c; | ||
217 | ushort mask; | ||
218 | |||
219 | n = getbits(nbit); | ||
220 | if (n == 0) { | ||
221 | c = getbits(nbit); | ||
222 | for (i = 0; i < nn; i++) | ||
223 | pt_len[i] = 0; | ||
224 | for (i = 0; i < 256; i++) | ||
225 | pt_table[i] = c; | ||
226 | } else { | ||
227 | i = 0; | ||
228 | while (i < n) { | ||
229 | c = bitbuf >> (BITBUFSIZ - 3); | ||
230 | if (c == 7) { | ||
231 | mask = 1U << (BITBUFSIZ - 1 - 3); | ||
232 | while (mask & bitbuf) { | ||
233 | mask >>= 1; | ||
234 | c++; | ||
235 | } | ||
236 | } | ||
237 | fillbuf((c < 7) ? 3 : c - 3); | ||
238 | pt_len[i++] = (unsigned char) (c); | ||
239 | if (i == i_special) { | ||
240 | c = getbits(2); | ||
241 | while (--c >= 0) | ||
242 | pt_len[i++] = 0; | ||
243 | } | ||
244 | } | ||
245 | while (i < nn) | ||
246 | pt_len[i++] = 0; | ||
247 | make_table(nn, pt_len, 8, pt_table); | ||
248 | } | ||
249 | } | ||
250 | |||
251 | void read_c_len(void) | ||
252 | { | ||
253 | short i, c, n; | ||
254 | ushort mask; | ||
255 | |||
256 | n = getbits(CBIT); | ||
257 | if (n == 0) { | ||
258 | c = getbits(CBIT); | ||
259 | for (i = 0; i < NC; i++) | ||
260 | c_len[i] = 0; | ||
261 | for (i = 0; i < 4096; i++) | ||
262 | c_table[i] = c; | ||
263 | } else { | ||
264 | i = 0; | ||
265 | while (i < n) { | ||
266 | c = pt_table[bitbuf >> (BITBUFSIZ - 8)]; | ||
267 | if (c >= NT) { | ||
268 | mask = 1U << (BITBUFSIZ - 1 - 8); | ||
269 | do { | ||
270 | if (bitbuf & mask) | ||
271 | c = right[c]; | ||
272 | else | ||
273 | c = left[c]; | ||
274 | mask >>= 1; | ||
275 | } while (c >= NT); | ||
276 | } | ||
277 | fillbuf(pt_len[c]); | ||
278 | if (c <= 2) { | ||
279 | if (c == 0) | ||
280 | c = 1; | ||
281 | else if (c == 1) | ||
282 | c = getbits(4) + 3; | ||
283 | else | ||
284 | c = getbits(CBIT) + 20; | ||
285 | while (--c >= 0) | ||
286 | c_len[i++] = 0; | ||
287 | } else | ||
288 | c_len[i++] = c - 2; | ||
289 | } | ||
290 | while (i < NC) | ||
291 | c_len[i++] = 0; | ||
292 | make_table(NC, c_len, 12, c_table); | ||
293 | } | ||
294 | } | ||
295 | |||
296 | ushort decode_c(void) | ||
297 | { | ||
298 | ushort j, mask; | ||
299 | |||
300 | if (blocksize == 0) { | ||
301 | blocksize = getbits(16); | ||
302 | read_pt_len(NT, TBIT, 3); | ||
303 | read_c_len(); | ||
304 | read_pt_len(NP, PBIT, -1); | ||
305 | } | ||
306 | blocksize--; | ||
307 | j = c_table[bitbuf >> (BITBUFSIZ - 12)]; | ||
308 | if (j >= NC) { | ||
309 | mask = 1U << (BITBUFSIZ - 1 - 12); | ||
310 | do { | ||
311 | if (bitbuf & mask) | ||
312 | j = right[j]; | ||
313 | else | ||
314 | j = left[j]; | ||
315 | mask >>= 1; | ||
316 | } | ||
317 | while (j >= NC); | ||
318 | } | ||
319 | fillbuf(c_len[j]); | ||
320 | return j; | ||
321 | } | ||
322 | |||
323 | ushort decode_p(void) | ||
324 | { | ||
325 | ushort j, mask; | ||
326 | |||
327 | j = pt_table[bitbuf >> (BITBUFSIZ - 8)]; | ||
328 | if (j >= NP) { | ||
329 | mask = 1U << (BITBUFSIZ - 1 - 8); | ||
330 | do { | ||
331 | if (bitbuf & mask) | ||
332 | j = right[j]; | ||
333 | else | ||
334 | j = left[j]; | ||
335 | mask >>= 1; | ||
336 | } while (j >= NP); | ||
337 | } | ||
338 | fillbuf(pt_len[j]); | ||
339 | if (j != 0) | ||
340 | j = (1U << (j - 1)) + getbits(j - 1); | ||
341 | return j; | ||
342 | } | ||
343 | |||
344 | void huf_decode_start(void) | ||
345 | { | ||
346 | init_getbits(); | ||
347 | blocksize = 0; | ||
348 | } | ||
349 | |||
350 | /* decode.c */ | ||
351 | |||
352 | void decode_start(void) | ||
353 | { | ||
354 | fillbufsize = 0; | ||
355 | huf_decode_start(); | ||
356 | decode_j = 0; | ||
357 | } | ||
358 | |||
359 | /* | ||
360 | * The calling function must keep the number of bytes to be processed. This | ||
361 | * function decodes either 'count' bytes or 'DICSIZ' bytes, whichever is | ||
362 | * smaller, into the array 'buffer[]' of size 'DICSIZ' or more. Call | ||
363 | * decode_start() once for each new file before calling this function. | ||
364 | */ | ||
365 | void decode(uint count, uchar buffer[]) | ||
366 | { | ||
367 | uint r, c; | ||
368 | |||
369 | r = 0; | ||
370 | while (--decode_j >= 0) { | ||
371 | buffer[r] = buffer[decode_i]; | ||
372 | decode_i = (decode_i + 1) & (DICSIZ - 1); | ||
373 | if (++r == count) | ||
374 | return; | ||
375 | } | ||
376 | for (;;) { | ||
377 | c = decode_c(); | ||
378 | if (c <= UCHAR_MAX) { | ||
379 | buffer[r] = c; | ||
380 | if (++r == count) | ||
381 | return; | ||
382 | } else { | ||
383 | decode_j = c - (UCHAR_MAX + 1 - THRESHOLD); | ||
384 | decode_i = (r - decode_p() - 1) & (DICSIZ - 1); | ||
385 | while (--decode_j >= 0) { | ||
386 | buffer[r] = buffer[decode_i]; | ||
387 | decode_i = (decode_i + 1) & (DICSIZ - 1); | ||
388 | if (++r == count) | ||
389 | return; | ||
390 | } | ||
391 | } | ||
392 | } | ||
393 | } | ||
394 | |||
395 | int LzUnpack(void *pSrc, int srcSize, void *pDst, int dstSize) | ||
396 | { | ||
397 | with_error = 0; | ||
398 | |||
399 | m_pSrc = (uchar *) pSrc; | ||
400 | m_srcSize = srcSize; | ||
401 | m_pDst = (uchar *) pDst; | ||
402 | m_dstSize = dstSize; | ||
403 | |||
404 | decode_start(); | ||
405 | |||
406 | unsigned int origsize = dstSize; | ||
407 | while (origsize != 0) { | ||
408 | int n = (uint) ((origsize > DICSIZ) ? DICSIZ : origsize); | ||
409 | decode(n, outbuf); | ||
410 | if (with_error) | ||
411 | break; | ||
412 | |||
413 | DataOut(outbuf, n); | ||
414 | origsize -= n; | ||
415 | if (with_error) | ||
416 | break; | ||
417 | } | ||
418 | |||
419 | return (with_error); | ||
420 | } | ||