diff options
Diffstat (limited to 'rbutil/rbutilqt/mspack/kwajd.c')
-rw-r--r-- | rbutil/rbutilqt/mspack/kwajd.c | 555 |
1 files changed, 555 insertions, 0 deletions
diff --git a/rbutil/rbutilqt/mspack/kwajd.c b/rbutil/rbutilqt/mspack/kwajd.c new file mode 100644 index 0000000000..d891b6a7e3 --- /dev/null +++ b/rbutil/rbutilqt/mspack/kwajd.c | |||
@@ -0,0 +1,555 @@ | |||
1 | /* This file is part of libmspack. | ||
2 | * (C) 2003-2010 Stuart Caie. | ||
3 | * | ||
4 | * KWAJ is a format very similar to SZDD. KWAJ method 3 (LZH) was | ||
5 | * written by Jeff Johnson. | ||
6 | * | ||
7 | * libmspack is free software; you can redistribute it and/or modify it under | ||
8 | * the terms of the GNU Lesser General Public License (LGPL) version 2.1 | ||
9 | * | ||
10 | * For further details, see the file COPYING.LIB distributed with libmspack | ||
11 | */ | ||
12 | |||
13 | /* KWAJ decompression implementation */ | ||
14 | |||
15 | #include <system.h> | ||
16 | #include <kwaj.h> | ||
17 | |||
18 | /* prototypes */ | ||
19 | static struct mskwajd_header *kwajd_open( | ||
20 | struct mskwaj_decompressor *base, const char *filename); | ||
21 | static void kwajd_close( | ||
22 | struct mskwaj_decompressor *base, struct mskwajd_header *hdr); | ||
23 | static int kwajd_read_headers( | ||
24 | struct mspack_system *sys, struct mspack_file *fh, | ||
25 | struct mskwajd_header *hdr); | ||
26 | static int kwajd_extract( | ||
27 | struct mskwaj_decompressor *base, struct mskwajd_header *hdr, | ||
28 | const char *filename); | ||
29 | static int kwajd_decompress( | ||
30 | struct mskwaj_decompressor *base, const char *input, const char *output); | ||
31 | static int kwajd_error( | ||
32 | struct mskwaj_decompressor *base); | ||
33 | |||
34 | static struct kwajd_stream *lzh_init( | ||
35 | struct mspack_system *sys, struct mspack_file *in, struct mspack_file *out); | ||
36 | static int lzh_decompress( | ||
37 | struct kwajd_stream *kwaj); | ||
38 | static void lzh_free( | ||
39 | struct kwajd_stream *kwaj); | ||
40 | static int lzh_read_lens( | ||
41 | struct kwajd_stream *kwaj, | ||
42 | unsigned int type, unsigned int numsyms, | ||
43 | unsigned char *lens, unsigned short *table); | ||
44 | static int lzh_read_input( | ||
45 | struct kwajd_stream *kwaj); | ||
46 | |||
47 | |||
48 | /*************************************** | ||
49 | * MSPACK_CREATE_KWAJ_DECOMPRESSOR | ||
50 | *************************************** | ||
51 | * constructor | ||
52 | */ | ||
53 | struct mskwaj_decompressor * | ||
54 | mspack_create_kwaj_decompressor(struct mspack_system *sys) | ||
55 | { | ||
56 | struct mskwaj_decompressor_p *self = NULL; | ||
57 | |||
58 | if (!sys) sys = mspack_default_system; | ||
59 | if (!mspack_valid_system(sys)) return NULL; | ||
60 | |||
61 | if ((self = (struct mskwaj_decompressor_p *) sys->alloc(sys, sizeof(struct mskwaj_decompressor_p)))) { | ||
62 | self->base.open = &kwajd_open; | ||
63 | self->base.close = &kwajd_close; | ||
64 | self->base.extract = &kwajd_extract; | ||
65 | self->base.decompress = &kwajd_decompress; | ||
66 | self->base.last_error = &kwajd_error; | ||
67 | self->system = sys; | ||
68 | self->error = MSPACK_ERR_OK; | ||
69 | } | ||
70 | return (struct mskwaj_decompressor *) self; | ||
71 | } | ||
72 | |||
73 | /*************************************** | ||
74 | * MSPACK_DESTROY_KWAJ_DECOMPRESSOR | ||
75 | *************************************** | ||
76 | * destructor | ||
77 | */ | ||
78 | void mspack_destroy_kwaj_decompressor(struct mskwaj_decompressor *base) | ||
79 | { | ||
80 | struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base; | ||
81 | if (self) { | ||
82 | struct mspack_system *sys = self->system; | ||
83 | sys->free(self); | ||
84 | } | ||
85 | } | ||
86 | |||
87 | /*************************************** | ||
88 | * KWAJD_OPEN | ||
89 | *************************************** | ||
90 | * opens a KWAJ file without decompressing, reads header | ||
91 | */ | ||
92 | static struct mskwajd_header *kwajd_open(struct mskwaj_decompressor *base, | ||
93 | const char *filename) | ||
94 | { | ||
95 | struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base; | ||
96 | struct mskwajd_header *hdr; | ||
97 | struct mspack_system *sys; | ||
98 | struct mspack_file *fh; | ||
99 | |||
100 | if (!self) return NULL; | ||
101 | sys = self->system; | ||
102 | |||
103 | fh = sys->open(sys, filename, MSPACK_SYS_OPEN_READ); | ||
104 | hdr = (struct mskwajd_header *) sys->alloc(sys, sizeof(struct mskwajd_header_p)); | ||
105 | if (fh && hdr) { | ||
106 | ((struct mskwajd_header_p *) hdr)->fh = fh; | ||
107 | self->error = kwajd_read_headers(sys, fh, hdr); | ||
108 | } | ||
109 | else { | ||
110 | if (!fh) self->error = MSPACK_ERR_OPEN; | ||
111 | if (!hdr) self->error = MSPACK_ERR_NOMEMORY; | ||
112 | } | ||
113 | |||
114 | if (self->error) { | ||
115 | if (fh) sys->close(fh); | ||
116 | if (hdr) sys->free(hdr); | ||
117 | hdr = NULL; | ||
118 | } | ||
119 | |||
120 | return hdr; | ||
121 | } | ||
122 | |||
123 | /*************************************** | ||
124 | * KWAJD_CLOSE | ||
125 | *************************************** | ||
126 | * closes a KWAJ file | ||
127 | */ | ||
128 | static void kwajd_close(struct mskwaj_decompressor *base, | ||
129 | struct mskwajd_header *hdr) | ||
130 | { | ||
131 | struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base; | ||
132 | struct mskwajd_header_p *hdr_p = (struct mskwajd_header_p *) hdr; | ||
133 | |||
134 | if (!self || !self->system) return; | ||
135 | |||
136 | /* close the file handle associated */ | ||
137 | self->system->close(hdr_p->fh); | ||
138 | |||
139 | /* free the memory associated */ | ||
140 | self->system->free(hdr); | ||
141 | |||
142 | self->error = MSPACK_ERR_OK; | ||
143 | } | ||
144 | |||
145 | /*************************************** | ||
146 | * KWAJD_READ_HEADERS | ||
147 | *************************************** | ||
148 | * reads the headers of a KWAJ format file | ||
149 | */ | ||
150 | static int kwajd_read_headers(struct mspack_system *sys, | ||
151 | struct mspack_file *fh, | ||
152 | struct mskwajd_header *hdr) | ||
153 | { | ||
154 | unsigned char buf[16]; | ||
155 | int i; | ||
156 | |||
157 | /* read in the header */ | ||
158 | if (sys->read(fh, &buf[0], kwajh_SIZEOF) != kwajh_SIZEOF) { | ||
159 | return MSPACK_ERR_READ; | ||
160 | } | ||
161 | |||
162 | /* check for "KWAJ" signature */ | ||
163 | if (((unsigned int) EndGetI32(&buf[kwajh_Signature1]) != 0x4A41574B) || | ||
164 | ((unsigned int) EndGetI32(&buf[kwajh_Signature2]) != 0xD127F088)) | ||
165 | { | ||
166 | return MSPACK_ERR_SIGNATURE; | ||
167 | } | ||
168 | |||
169 | /* basic header fields */ | ||
170 | hdr->comp_type = EndGetI16(&buf[kwajh_CompMethod]); | ||
171 | hdr->data_offset = EndGetI16(&buf[kwajh_DataOffset]); | ||
172 | hdr->headers = EndGetI16(&buf[kwajh_Flags]); | ||
173 | hdr->length = 0; | ||
174 | hdr->filename = NULL; | ||
175 | hdr->extra = NULL; | ||
176 | hdr->extra_length = 0; | ||
177 | |||
178 | /* optional headers */ | ||
179 | |||
180 | /* 4 bytes: length of unpacked file */ | ||
181 | if (hdr->headers & MSKWAJ_HDR_HASLENGTH) { | ||
182 | if (sys->read(fh, &buf[0], 4) != 4) return MSPACK_ERR_READ; | ||
183 | hdr->length = EndGetI32(&buf[0]); | ||
184 | } | ||
185 | |||
186 | /* 2 bytes: unknown purpose */ | ||
187 | if (hdr->headers & MSKWAJ_HDR_HASUNKNOWN1) { | ||
188 | if (sys->read(fh, &buf[0], 2) != 2) return MSPACK_ERR_READ; | ||
189 | } | ||
190 | |||
191 | /* 2 bytes: length of section, then [length] bytes: unknown purpose */ | ||
192 | if (hdr->headers & MSKWAJ_HDR_HASUNKNOWN2) { | ||
193 | if (sys->read(fh, &buf[0], 2) != 2) return MSPACK_ERR_READ; | ||
194 | i = EndGetI16(&buf[0]); | ||
195 | if (sys->seek(fh, (off_t)i, MSPACK_SYS_SEEK_CUR)) return MSPACK_ERR_SEEK; | ||
196 | } | ||
197 | |||
198 | /* filename and extension */ | ||
199 | if (hdr->headers & (MSKWAJ_HDR_HASFILENAME | MSKWAJ_HDR_HASFILEEXT)) { | ||
200 | off_t pos = sys->tell(fh); | ||
201 | char *fn = (char *) sys->alloc(sys, (size_t) 13); | ||
202 | |||
203 | /* allocate memory for maximum length filename */ | ||
204 | if (! fn) return MSPACK_ERR_NOMEMORY; | ||
205 | hdr->filename = fn; | ||
206 | |||
207 | /* copy filename if present */ | ||
208 | if (hdr->headers & MSKWAJ_HDR_HASFILENAME) { | ||
209 | if (sys->read(fh, &buf[0], 9) != 9) return MSPACK_ERR_READ; | ||
210 | for (i = 0; i < 9; i++, fn++) if (!(*fn = buf[i])) break; | ||
211 | pos += (i < 9) ? i+1 : 9; | ||
212 | if (sys->seek(fh, pos, MSPACK_SYS_SEEK_START)) | ||
213 | return MSPACK_ERR_SEEK; | ||
214 | } | ||
215 | |||
216 | /* copy extension if present */ | ||
217 | if (hdr->headers & MSKWAJ_HDR_HASFILEEXT) { | ||
218 | *fn++ = '.'; | ||
219 | if (sys->read(fh, &buf[0], 4) != 4) return MSPACK_ERR_READ; | ||
220 | for (i = 0; i < 4; i++, fn++) if (!(*fn = buf[i])) break; | ||
221 | pos += (i < 4) ? i+1 : 4; | ||
222 | if (sys->seek(fh, pos, MSPACK_SYS_SEEK_START)) | ||
223 | return MSPACK_ERR_SEEK; | ||
224 | } | ||
225 | *fn = '\0'; | ||
226 | } | ||
227 | |||
228 | /* 2 bytes: extra text length then [length] bytes of extra text data */ | ||
229 | if (hdr->headers & MSKWAJ_HDR_HASEXTRATEXT) { | ||
230 | if (sys->read(fh, &buf[0], 2) != 2) return MSPACK_ERR_READ; | ||
231 | i = EndGetI16(&buf[0]); | ||
232 | hdr->extra = (char *) sys->alloc(sys, (size_t)i+1); | ||
233 | if (! hdr->extra) return MSPACK_ERR_NOMEMORY; | ||
234 | if (sys->read(fh, hdr->extra, i) != i) return MSPACK_ERR_READ; | ||
235 | hdr->extra[i] = '\0'; | ||
236 | hdr->extra_length = i; | ||
237 | } | ||
238 | return MSPACK_ERR_OK; | ||
239 | } | ||
240 | |||
241 | /*************************************** | ||
242 | * KWAJD_EXTRACT | ||
243 | *************************************** | ||
244 | * decompresses a KWAJ file | ||
245 | */ | ||
246 | static int kwajd_extract(struct mskwaj_decompressor *base, | ||
247 | struct mskwajd_header *hdr, const char *filename) | ||
248 | { | ||
249 | struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base; | ||
250 | struct mspack_system *sys; | ||
251 | struct mspack_file *fh, *outfh; | ||
252 | |||
253 | if (!self) return MSPACK_ERR_ARGS; | ||
254 | if (!hdr) return self->error = MSPACK_ERR_ARGS; | ||
255 | |||
256 | sys = self->system; | ||
257 | fh = ((struct mskwajd_header_p *) hdr)->fh; | ||
258 | |||
259 | /* seek to the compressed data */ | ||
260 | if (sys->seek(fh, hdr->data_offset, MSPACK_SYS_SEEK_START)) { | ||
261 | return self->error = MSPACK_ERR_SEEK; | ||
262 | } | ||
263 | |||
264 | /* open file for output */ | ||
265 | if (!(outfh = sys->open(sys, filename, MSPACK_SYS_OPEN_WRITE))) { | ||
266 | return self->error = MSPACK_ERR_OPEN; | ||
267 | } | ||
268 | |||
269 | self->error = MSPACK_ERR_OK; | ||
270 | |||
271 | /* decompress based on format */ | ||
272 | if (hdr->comp_type == MSKWAJ_COMP_NONE || | ||
273 | hdr->comp_type == MSKWAJ_COMP_XOR) | ||
274 | { | ||
275 | /* NONE is a straight copy. XOR is a copy xored with 0xFF */ | ||
276 | unsigned char *buf = (unsigned char *) sys->alloc(sys, (size_t) KWAJ_INPUT_SIZE); | ||
277 | if (buf) { | ||
278 | int read, i; | ||
279 | while ((read = sys->read(fh, buf, KWAJ_INPUT_SIZE)) > 0) { | ||
280 | if (hdr->comp_type == MSKWAJ_COMP_XOR) { | ||
281 | for (i = 0; i < read; i++) buf[i] ^= 0xFF; | ||
282 | } | ||
283 | if (sys->write(outfh, buf, read) != read) { | ||
284 | self->error = MSPACK_ERR_WRITE; | ||
285 | break; | ||
286 | } | ||
287 | } | ||
288 | if (read < 0) self->error = MSPACK_ERR_READ; | ||
289 | sys->free(buf); | ||
290 | } | ||
291 | else { | ||
292 | self->error = MSPACK_ERR_NOMEMORY; | ||
293 | } | ||
294 | } | ||
295 | else if (hdr->comp_type == MSKWAJ_COMP_SZDD) { | ||
296 | self->error = lzss_decompress(sys, fh, outfh, KWAJ_INPUT_SIZE, | ||
297 | LZSS_MODE_EXPAND); | ||
298 | } | ||
299 | else if (hdr->comp_type == MSKWAJ_COMP_LZH) { | ||
300 | struct kwajd_stream *lzh = lzh_init(sys, fh, outfh); | ||
301 | self->error = (lzh) ? lzh_decompress(lzh) : MSPACK_ERR_NOMEMORY; | ||
302 | lzh_free(lzh); | ||
303 | } | ||
304 | else { | ||
305 | self->error = MSPACK_ERR_DATAFORMAT; | ||
306 | } | ||
307 | |||
308 | /* close output file */ | ||
309 | sys->close(outfh); | ||
310 | |||
311 | return self->error; | ||
312 | } | ||
313 | |||
314 | /*************************************** | ||
315 | * KWAJD_DECOMPRESS | ||
316 | *************************************** | ||
317 | * unpacks directly from input to output | ||
318 | */ | ||
319 | static int kwajd_decompress(struct mskwaj_decompressor *base, | ||
320 | const char *input, const char *output) | ||
321 | { | ||
322 | struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base; | ||
323 | struct mskwajd_header *hdr; | ||
324 | int error; | ||
325 | |||
326 | if (!self) return MSPACK_ERR_ARGS; | ||
327 | |||
328 | if (!(hdr = kwajd_open(base, input))) return self->error; | ||
329 | error = kwajd_extract(base, hdr, output); | ||
330 | kwajd_close(base, hdr); | ||
331 | return self->error = error; | ||
332 | } | ||
333 | |||
334 | /*************************************** | ||
335 | * KWAJD_ERROR | ||
336 | *************************************** | ||
337 | * returns the last error that occurred | ||
338 | */ | ||
339 | static int kwajd_error(struct mskwaj_decompressor *base) | ||
340 | { | ||
341 | struct mskwaj_decompressor_p *self = (struct mskwaj_decompressor_p *) base; | ||
342 | return (self) ? self->error : MSPACK_ERR_ARGS; | ||
343 | } | ||
344 | |||
345 | /*************************************** | ||
346 | * LZH_INIT, LZH_DECOMPRESS, LZH_FREE | ||
347 | *************************************** | ||
348 | * unpacks KWAJ method 3 files | ||
349 | */ | ||
350 | |||
351 | /* import bit-reading macros and code */ | ||
352 | #define BITS_TYPE struct kwajd_stream | ||
353 | #define BITS_VAR lzh | ||
354 | #define BITS_ORDER_MSB | ||
355 | #define BITS_NO_READ_INPUT | ||
356 | #define READ_BYTES do { \ | ||
357 | if (i_ptr >= i_end) { \ | ||
358 | if ((err = lzh_read_input(lzh))) return err; \ | ||
359 | i_ptr = lzh->i_ptr; \ | ||
360 | i_end = lzh->i_end; \ | ||
361 | } \ | ||
362 | INJECT_BITS(*i_ptr++, 8); \ | ||
363 | } while (0) | ||
364 | #include <readbits.h> | ||
365 | |||
366 | /* import huffman-reading macros and code */ | ||
367 | #define TABLEBITS(tbl) KWAJ_TABLEBITS | ||
368 | #define MAXSYMBOLS(tbl) KWAJ_##tbl##_SYMS | ||
369 | #define HUFF_TABLE(tbl,idx) lzh->tbl##_table[idx] | ||
370 | #define HUFF_LEN(tbl,idx) lzh->tbl##_len[idx] | ||
371 | #define HUFF_ERROR return MSPACK_ERR_DATAFORMAT | ||
372 | #include <readhuff.h> | ||
373 | |||
374 | /* In the KWAJ LZH format, there is no special 'eof' marker, it just | ||
375 | * ends. Depending on how many bits are left in the final byte when | ||
376 | * the stream ends, that might be enough to start another literal or | ||
377 | * match. The only easy way to detect that we've come to an end is to | ||
378 | * guard all bit-reading. We allow fake bits to be read once we reach | ||
379 | * the end of the stream, but we check if we then consumed any of | ||
380 | * those fake bits, after doing the READ_BITS / READ_HUFFSYM. This | ||
381 | * isn't how the default readbits.h read_input() works (it simply lets | ||
382 | * 2 fake bytes in then stops), so we implement our own. | ||
383 | */ | ||
384 | #define READ_BITS_SAFE(val, n) do { \ | ||
385 | READ_BITS(val, n); \ | ||
386 | if (lzh->input_end && bits_left < lzh->input_end) \ | ||
387 | return MSPACK_ERR_OK; \ | ||
388 | } while (0) | ||
389 | |||
390 | #define READ_HUFFSYM_SAFE(tbl, val) do { \ | ||
391 | READ_HUFFSYM(tbl, val); \ | ||
392 | if (lzh->input_end && bits_left < lzh->input_end) \ | ||
393 | return MSPACK_ERR_OK; \ | ||
394 | } while (0) | ||
395 | |||
396 | #define BUILD_TREE(tbl, type) \ | ||
397 | STORE_BITS; \ | ||
398 | err = lzh_read_lens(lzh, type, MAXSYMBOLS(tbl), \ | ||
399 | &HUFF_LEN(tbl,0), &HUFF_TABLE(tbl,0)); \ | ||
400 | if (err) return err; \ | ||
401 | RESTORE_BITS; \ | ||
402 | if (make_decode_table(MAXSYMBOLS(tbl), TABLEBITS(tbl), \ | ||
403 | &HUFF_LEN(tbl,0), &HUFF_TABLE(tbl,0))) \ | ||
404 | return MSPACK_ERR_DATAFORMAT; | ||
405 | |||
406 | #define WRITE_BYTE do { \ | ||
407 | if (lzh->sys->write(lzh->output, &lzh->window[pos], 1) != 1) \ | ||
408 | return MSPACK_ERR_WRITE; \ | ||
409 | } while (0) | ||
410 | |||
411 | static struct kwajd_stream *lzh_init(struct mspack_system *sys, | ||
412 | struct mspack_file *in, struct mspack_file *out) | ||
413 | { | ||
414 | struct kwajd_stream *lzh; | ||
415 | |||
416 | if (!sys || !in || !out) return NULL; | ||
417 | if (!(lzh = (struct kwajd_stream *) sys->alloc(sys, sizeof(struct kwajd_stream)))) return NULL; | ||
418 | |||
419 | lzh->sys = sys; | ||
420 | lzh->input = in; | ||
421 | lzh->output = out; | ||
422 | return lzh; | ||
423 | } | ||
424 | |||
425 | static int lzh_decompress(struct kwajd_stream *lzh) | ||
426 | { | ||
427 | register unsigned int bit_buffer; | ||
428 | register int bits_left, i; | ||
429 | register unsigned short sym; | ||
430 | unsigned char *i_ptr, *i_end, lit_run = 0; | ||
431 | int j, pos = 0, len, offset, err; | ||
432 | unsigned int types[6]; | ||
433 | |||
434 | /* reset global state */ | ||
435 | INIT_BITS; | ||
436 | RESTORE_BITS; | ||
437 | memset(&lzh->window[0], LZSS_WINDOW_FILL, (size_t) LZSS_WINDOW_SIZE); | ||
438 | |||
439 | /* read 6 encoding types (for byte alignment) but only 5 are needed */ | ||
440 | for (i = 0; i < 6; i++) READ_BITS_SAFE(types[i], 4); | ||
441 | |||
442 | /* read huffman table symbol lengths and build huffman trees */ | ||
443 | BUILD_TREE(MATCHLEN1, types[0]); | ||
444 | BUILD_TREE(MATCHLEN2, types[1]); | ||
445 | BUILD_TREE(LITLEN, types[2]); | ||
446 | BUILD_TREE(OFFSET, types[3]); | ||
447 | BUILD_TREE(LITERAL, types[4]); | ||
448 | |||
449 | while (!lzh->input_end) { | ||
450 | if (lit_run) READ_HUFFSYM_SAFE(MATCHLEN2, len); | ||
451 | else READ_HUFFSYM_SAFE(MATCHLEN1, len); | ||
452 | |||
453 | if (len > 0) { | ||
454 | len += 2; | ||
455 | lit_run = 0; /* not the end of a literal run */ | ||
456 | READ_HUFFSYM_SAFE(OFFSET, j); offset = j << 6; | ||
457 | READ_BITS_SAFE(j, 6); offset |= j; | ||
458 | |||
459 | /* copy match as output and into the ring buffer */ | ||
460 | while (len-- > 0) { | ||
461 | lzh->window[pos] = lzh->window[(pos+4096-offset) & 4095]; | ||
462 | WRITE_BYTE; | ||
463 | pos++; pos &= 4095; | ||
464 | } | ||
465 | } | ||
466 | else { | ||
467 | READ_HUFFSYM_SAFE(LITLEN, len); len++; | ||
468 | lit_run = (len == 32) ? 0 : 1; /* end of a literal run? */ | ||
469 | while (len-- > 0) { | ||
470 | READ_HUFFSYM_SAFE(LITERAL, j); | ||
471 | /* copy as output and into the ring buffer */ | ||
472 | lzh->window[pos] = j; | ||
473 | WRITE_BYTE; | ||
474 | pos++; pos &= 4095; | ||
475 | } | ||
476 | } | ||
477 | } | ||
478 | return MSPACK_ERR_OK; | ||
479 | } | ||
480 | |||
481 | static void lzh_free(struct kwajd_stream *lzh) | ||
482 | { | ||
483 | struct mspack_system *sys; | ||
484 | if (!lzh || !lzh->sys) return; | ||
485 | sys = lzh->sys; | ||
486 | sys->free(lzh); | ||
487 | } | ||
488 | |||
489 | static int lzh_read_lens(struct kwajd_stream *lzh, | ||
490 | unsigned int type, unsigned int numsyms, | ||
491 | unsigned char *lens, unsigned short *table) | ||
492 | { | ||
493 | register unsigned int bit_buffer; | ||
494 | register int bits_left; | ||
495 | unsigned char *i_ptr, *i_end; | ||
496 | unsigned int i, c, sel; | ||
497 | int err; | ||
498 | |||
499 | RESTORE_BITS; | ||
500 | switch (type) { | ||
501 | case 0: | ||
502 | i = numsyms; c = (i==16)?4: (i==32)?5: (i==64)?6: (i==256)?8 :0; | ||
503 | for (i = 0; i < numsyms; i++) lens[i] = c; | ||
504 | break; | ||
505 | |||
506 | case 1: | ||
507 | READ_BITS_SAFE(c, 4); lens[0] = c; | ||
508 | for (i = 1; i < numsyms; i++) { | ||
509 | READ_BITS_SAFE(sel, 1); if (sel == 0) lens[i] = c; | ||
510 | else { READ_BITS_SAFE(sel, 1); if (sel == 0) lens[i] = ++c; | ||
511 | else { READ_BITS_SAFE(c, 4); lens[i] = c; }} | ||
512 | } | ||
513 | break; | ||
514 | |||
515 | case 2: | ||
516 | READ_BITS_SAFE(c, 4); lens[0] = c; | ||
517 | for (i = 1; i < numsyms; i++) { | ||
518 | READ_BITS_SAFE(sel, 2); | ||
519 | if (sel == 3) READ_BITS_SAFE(c, 4); else c += (char) sel-1; | ||
520 | lens[i] = c; | ||
521 | } | ||
522 | break; | ||
523 | |||
524 | case 3: | ||
525 | for (i = 0; i < numsyms; i++) { | ||
526 | READ_BITS_SAFE(c, 4); lens[i] = c; | ||
527 | } | ||
528 | break; | ||
529 | } | ||
530 | STORE_BITS; | ||
531 | return MSPACK_ERR_OK; | ||
532 | } | ||
533 | |||
534 | static int lzh_read_input(struct kwajd_stream *lzh) { | ||
535 | int read; | ||
536 | if (lzh->input_end) { | ||
537 | lzh->input_end += 8; | ||
538 | lzh->inbuf[0] = 0; | ||
539 | read = 1; | ||
540 | } | ||
541 | else { | ||
542 | read = lzh->sys->read(lzh->input, &lzh->inbuf[0], KWAJ_INPUT_SIZE); | ||
543 | if (read < 0) return MSPACK_ERR_READ; | ||
544 | if (read == 0) { | ||
545 | lzh->input_end = 8; | ||
546 | lzh->inbuf[0] = 0; | ||
547 | read = 1; | ||
548 | } | ||
549 | } | ||
550 | |||
551 | /* update i_ptr and i_end */ | ||
552 | lzh->i_ptr = &lzh->inbuf[0]; | ||
553 | lzh->i_end = &lzh->inbuf[read]; | ||
554 | return MSPACK_ERR_OK; | ||
555 | } | ||