1 /*
2  * tinflate  -  tiny inflate
3  *
4  * Copyright (c) 2003 by Joergen Ibsen / Jibz
5  * All Rights Reserved
6  *
7  * http://www.ibsensoftware.com/
8  *
9  * This software is provided 'as-is', without any express
10  * or implied warranty.  In no event will the authors be
11  * held liable for any damages arising from the use of
12  * this software.
13  *
14  * Permission is granted to anyone to use this software
15  * for any purpose, including commercial applications,
16  * and to alter it and redistribute it freely, subject to
17  * the following restrictions:
18  *
19  * 1. The origin of this software must not be
20  *    misrepresented; you must not claim that you
21  *    wrote the original software. If you use this
22  *    software in a product, an acknowledgment in
23  *    the product documentation would be appreciated
24  *    but is not required.
25  *
26  * 2. Altered source versions must be plainly marked
27  *    as such, and must not be misrepresented as
28  *    being the original software.
29  *
30  * 3. This notice may not be removed or altered from
31  *    any source distribution.
32  */
33 module npp_mimetools.tinflate;
34 
35 
36 //#ifdef __WATCOMC__
37 //	enum TINFCC = __cdecl;
38 //#else
39 //	#define TINFCC
40 //#endif
41 
42 extern(C):
43 
44 enum TINF_OK = 0;
45 enum TINF_DATA_ERROR = -3;
46 
47 /* ------------------------------ *
48  * -- internal data structures -- *
49  * ------------------------------ */
50 
51 struct TINF_TREE
52 {
53 	/**
54 	 * table of code length counts
55 	 */
56 	ushort[16] table;
57 
58 	/**
59 	 * code -> symbol translation table
60 	 */
61 	ushort[288] trans;
62 }
63 
64 struct TINF_DATA
65 {
66 	const (ubyte)* source;
67 	uint tag;
68 	uint bitcount;
69 
70 	ubyte* dest;
71 	uint destLen;
72 
73 	/**
74 	 * dynamic length/symbol tree
75 	 */
76 	.TINF_TREE ltree;
77 
78 	/**
79 	 * dynamic distance tree
80 	 */
81 	.TINF_TREE dtree;
82 }
83 
84 /* --------------------------------------------------- *
85  * -- uninitialized global data (static structures) -- *
86  * --------------------------------------------------- */
87 
88 /**
89  * fixed length/symbol tree
90  */
91 .TINF_TREE sltree;
92 
93 /**
94  * fixed distance tree
95  */
96 .TINF_TREE sdtree;
97 
98 /* extra bits and base tables for length codes */
99 ubyte[30] length_bits;
100 ushort[30] length_base;
101 
102 /* extra bits and base tables for distance codes */
103 ubyte[30] dist_bits;
104 ushort[30] dist_base;
105 
106 /**
107  * special ordering of code length codes
108  */
109 private static immutable ubyte[] clcidx =
110 [
111 	16, 17, 18, 0, 8, 7, 9, 6,
112 	10, 5, 11, 4, 12, 3, 13, 2,
113 	14, 1, 15,
114 ];
115 
116 /* ----------------------- *
117  * -- utility functions -- *
118  * ----------------------- */
119 
120 /**
121  * build extra bits and base tables
122  */
123 pure nothrow @safe @nogc
124 private void tinf_build_bits_base(ref ubyte[30] bits, ref ushort[30] base, int delta, int first)
125 
126 	do
127 	{
128 		size_t i;
129 		int sum;
130 
131 		/* build bits table */
132 		for (i = 0; i < delta; ++i) {
133 			bits[i] = 0;
134 		}
135 
136 		for (i = 0; i < 30 - delta; ++i) {
137 			bits[i + delta] = cast(char)(cast(int)(i) / delta);
138 		}
139 
140 		/* build base table */
141 		for (sum = first, i = 0; i < 30; ++i) {
142 			base[i] = cast(char)(sum);
143 			sum += 1 << bits[i];
144 		}
145 	}
146 
147 /**
148  * build the fixed huffman trees
149  */
150 pure nothrow @safe @nogc
151 private void tinf_build_fixed_trees(ref .TINF_TREE lt, ref .TINF_TREE dt)
152 
153 	do
154 	{
155 		size_t i;
156 
157 		/* build fixed length tree */
158 		for (i = 0; i < 7; ++i) {
159 			lt.table[i] = 0;
160 		}
161 
162 		lt.table[7] = 24;
163 		lt.table[8] = 152;
164 		lt.table[9] = 112;
165 
166 		for (i = 0; i < 24; ++i) {
167 			lt.trans[i] = cast(ushort)(256 + i);
168 		}
169 
170 		for (i = 0; i < 144; ++i) {
171 			lt.trans[24 + i] = cast(ushort)(i);
172 		}
173 
174 		for (i = 0; i < 8; ++i) {
175 			lt.trans[24 + 144 + i] = cast(ushort)(280 + i);
176 		}
177 
178 		for (i = 0; i < 112; ++i) {
179 			lt.trans[24 + 144 + 8 + i] = cast(ushort)(144 + i);
180 		}
181 
182 		/* build fixed distance tree */
183 		for (i = 0; i < 5; ++i) {
184 			dt.table[i] = 0;
185 		}
186 
187 		dt.table[5] = 32;
188 
189 		for (i = 0; i < 32; ++i) {
190 			dt.trans[i] = cast(ushort)(i);
191 		}
192 	}
193 
194 /**
195  * given an array of code lengths, build a tree
196  */
197 pure nothrow @safe @nogc
198 private void tinf_build_tree(ref .TINF_TREE t, const ubyte[] lengths, uint num)
199 
200 	do
201 	{
202 		ushort[16] offs;
203 		size_t i;
204 		uint sum;
205 
206 		/* clear code length count table */
207 		for (i = 0; i < 16; ++i) {
208 			t.table[i] = 0;
209 		}
210 
211 		/* scan symbol lengths, and sum code length counts */
212 		for (i = 0; i < num; ++i) {
213 			t.table[lengths[i]]++;
214 		}
215 
216 		t.table[0] = 0;
217 
218 		/* compute offset table for distribution sort */
219 		for (sum = 0, i = 0; i < 16; ++i) {
220 			offs[i] = cast(ushort)(sum);
221 			sum += t.table[i];
222 		}
223 
224 		/* create code->symbol translation table (symbols sorted by code) */
225 		for (i = 0; i < num; ++i) {
226 			if (lengths[i]) {
227 				t.trans[offs[lengths[i]]++] = cast(ushort)(i);
228 			}
229 		}
230 	}
231 
232 /* ---------------------- *
233  * -- decode functions -- *
234  * ---------------------- */
235 
236 /**
237  * get one bit from source stream
238  */
239 pure nothrow @nogc
240 private int tinf_getbit(ref .TINF_DATA d)
241 
242 	do
243 	{
244 		uint bit;
245 
246 		/* check if tag is empty */
247 		if (!d.bitcount--) {
248 			/* load next tag */
249 			d.tag = *d.source++;
250 			d.bitcount = 7;
251 		}
252 
253 		/* shift bit out of tag */
254 		bit = d.tag & 0x01;
255 		d.tag >>= 1;
256 
257 		return bit;
258 	}
259 
260 /**
261  * read a num bit value from a stream and add base
262  */
263 pure nothrow @nogc
264 private uint tinf_read_bits(ref .TINF_DATA d, int num, int base)
265 
266 	do
267 	{
268 		uint val = 0;
269 
270 		/* read num bits */
271 		if (num) {
272 			uint limit = 1 << (num);
273 			uint mask;
274 
275 			for (mask = 1; mask < limit; mask *= 2)
276 				if (.tinf_getbit(d)) {
277 					val += mask;
278 				}
279 		}
280 
281 		return val + base;
282 	}
283 
284 /**
285  * given a data stream and a tree, decode a symbol
286  */
287 pure nothrow @nogc
288 private int tinf_decode_symbol(ref .TINF_DATA d, ref .TINF_TREE t)
289 
290 	do
291 	{
292 		int sum = 0;
293 		int cur = 0;
294 		int len = 0;
295 
296 		/* get more bits while code value is above sum */
297 		do {
298 			cur = 2 * cur + .tinf_getbit(d);
299 
300 			++len;
301 
302 			sum += t.table[len];
303 			cur -= t.table[len];
304 		} while (cur >= 0);
305 
306 		return t.trans[sum + cur];
307 	}
308 
309 /**
310  * given a data stream, decode dynamic trees from it
311  */
312 nothrow @nogc
313 private void tinf_decode_trees(ref .TINF_DATA d, ref .TINF_TREE lt, ref .TINF_TREE dt)
314 
315 	do
316 	{
317 		.TINF_TREE code_tree;
318 		ubyte[288 + 32] lengths;
319 		uint hlit;
320 		uint hdist;
321 		uint hclen;
322 		size_t i;
323 		uint num;
324 		uint length;
325 
326 		/* get 5 bits HLIT (257-286) */
327 		hlit = .tinf_read_bits(d, 5, 257);
328 
329 		/* get 5 bits HDIST (1-32) */
330 		hdist = .tinf_read_bits(d, 5, 1);
331 
332 		/* get 4 bits HCLEN (4-19) */
333 		hclen = .tinf_read_bits(d, 4, 4);
334 
335 		for (i = 0; i < 19; ++i) {
336 			lengths[i] = 0;
337 		}
338 
339 		/* read code lengths for code length alphabet */
340 		for (i = 0; i < hclen; ++i) {
341 			/* get 3 bits code length (0-7) */
342 			uint clen = .tinf_read_bits(d, 3, 0);
343 
344 			lengths[.clcidx[i]] = cast(ubyte)(clen);
345 		}
346 
347 		/* build code length tree */
348 		.tinf_build_tree(code_tree, lengths, 19);
349 
350 		/* decode code lengths for the dynamic trees */
351 		for (num = 0; num < hlit + hdist; ) {
352 			int sym = .tinf_decode_symbol(d, code_tree);
353 
354 			switch (sym) {
355 				case 16:
356 					/* copy previous code length 3-6 times (read 2 bits) */
357 					{
358 						ubyte prev = lengths[num - 1];
359 
360 						for (length = .tinf_read_bits(d, 2, 3); length; --length) {
361 							lengths[num++] = prev;
362 						}
363 					}
364 
365 					break;
366 
367 				case 17:
368 					/* repeat code length 0 for 3-10 times (read 3 bits) */
369 					for (length = .tinf_read_bits(d, 3, 3); length; --length) {
370 						lengths[num++] = 0;
371 					}
372 
373 					break;
374 
375 				case 18:
376 					/* repeat code length 0 for 11-138 times (read 7 bits) */
377 					for (length = .tinf_read_bits(d, 7, 11); length; --length) {
378 						lengths[num++] = 0;
379 					}
380 
381 					break;
382 
383 				default:
384 					/* values 0-15 represent the actual code lengths */
385 					lengths[num++] = cast(char)(sym);
386 
387 					break;
388 			}
389 		}
390 
391 		/* build dynamic trees */
392 		.tinf_build_tree(lt, lengths[0 .. $], hlit);
393 		.tinf_build_tree(dt, lengths[hlit .. $], hdist);
394 	}
395 
396 /* ----------------------------- *
397  * -- block inflate functions -- *
398  * ----------------------------- */
399 
400 /**
401  * given a stream and two trees, inflate a block of data
402  */
403 nothrow @nogc
404 private int tinf_inflate_block_data(ref .TINF_DATA d, ref .TINF_TREE lt, ref .TINF_TREE dt)
405 
406 	do
407 	{
408 		/* remember current output position */
409 		ubyte* start = d.dest;
410 
411 		for (;;) {
412 			int sym = .tinf_decode_symbol(d, lt);
413 
414 			/* check for end of block */
415 			if (sym == 256) {
416 				d.destLen += cast(uint)(d.dest - start);
417 
418 				return .TINF_OK;
419 			}
420 
421 			if (sym < 256) {
422 				*d.dest++ = cast(char)(sym);
423 			} else {
424 				int length;
425 				int dist;
426 				int offs;
427 				int i;
428 
429 				sym -= 257;
430 
431 				/* possibly get more bits from length code */
432 				length = .tinf_read_bits(d, .length_bits[sym], .length_base[sym]);
433 
434 				dist = .tinf_decode_symbol(d, dt);
435 
436 				/* possibly get more bits from distance code */
437 				offs = .tinf_read_bits(d, .dist_bits[dist], .dist_base[dist]);
438 
439 				/* copy match */
440 				for (i = 0; i < length; ++i) {
441 					d.dest[i] = d.dest[i - offs];
442 				}
443 
444 				d.dest += length;
445 			}
446 		}
447 	}
448 
449 /**
450  * inflate an uncompressed block of data
451  */
452 pure nothrow @nogc
453 private int tinf_inflate_uncompressed_block(ref .TINF_DATA d)
454 
455 	do
456 	{
457 		uint length;
458 		uint invlength;
459 		uint i;
460 
461 		/* get length */
462 		length = d.source[1];
463 		length = 256 * length + d.source[0];
464 
465 		/* get one's complement of length */
466 		invlength = d.source[3];
467 		invlength = 256 * invlength + d.source[2];
468 
469 		/* check length */
470 		if (length != (~invlength & 0x0000FFFF)) {
471 			return .TINF_DATA_ERROR;
472 		}
473 
474 		d.source += 4;
475 
476 		/* copy block */
477 		for (i = length; i; --i) {
478 			*d.dest++ = *d.source++;
479 		}
480 
481 		/* make sure we start next block on a byte boundary */
482 		d.bitcount = 0;
483 
484 		d.destLen += length;
485 
486 		return .TINF_OK;
487 	}
488 
489 /**
490  * inflate a block of data compressed with fixed huffman trees
491  */
492 nothrow @nogc
493 private int tinf_inflate_fixed_block(ref .TINF_DATA d)
494 
495 	do
496 	{
497 		/* decode block using fixed trees */
498 		return .tinf_inflate_block_data(d, .sltree, .sdtree);
499 	}
500 
501 /**
502  * inflate a block of data compressed with dynamic huffman trees
503  */
504 nothrow @nogc
505 private int tinf_inflate_dynamic_block(ref .TINF_DATA d)
506 
507 	do
508 	{
509 		/* decode trees from stream */
510 		.tinf_decode_trees(d, d.ltree, d.dtree);
511 
512 		/* decode block using decoded trees */
513 		return .tinf_inflate_block_data(d, d.ltree, d.dtree);
514 	}
515 
516 /* ---------------------- *
517  * -- public functions -- *
518  * ---------------------- */
519 
520 /**
521  * initialize global (static) data
522  */
523 nothrow @nogc
524 void tinf_init()
525 
526 	do
527 	{
528 		/* build fixed huffman trees */
529 		.tinf_build_fixed_trees(.sltree, .sdtree);
530 
531 		/* build extra bits and base tables */
532 		.tinf_build_bits_base(.length_bits, .length_base, 4, 3);
533 		.tinf_build_bits_base(.dist_bits, .dist_base, 2, 1);
534 
535 		/* fix a special case */
536 		.length_bits[28] = 0;
537 		.length_base[28] = 258;
538 	}
539 
540 /**
541  * inflate stream from source to dest
542  */
543 nothrow @nogc
544 int tinf_uncompress(void[] dest, ref uint destLen, const void[] source)
545 
546 	do
547 	{
548 		.TINF_DATA d;
549 		int bfinal;
550 
551 		/* initialise data */
552 		d.source = cast(const (ubyte)*)(&(source[0]));
553 		d.bitcount = 0;
554 
555 		d.dest = cast(ubyte*)(&(dest[0]));
556 		d.destLen = destLen;
557 
558 		destLen = 0;
559 
560 		do {
561 			uint btype;
562 			int res;
563 
564 			/* read final block flag */
565 			bfinal = .tinf_getbit(d);
566 
567 			/* read block type (2 bits) */
568 			btype = .tinf_read_bits(d, 2, 0);
569 
570 			/* decompress block */
571 			switch (btype) {
572 				case 0:
573 					/* decompress uncompressed block */
574 					res = .tinf_inflate_uncompressed_block(d);
575 
576 					break;
577 
578 				case 1:
579 					/* decompress block with fixed huffman trees */
580 					res = .tinf_inflate_fixed_block(d);
581 
582 					break;
583 
584 				case 2:
585 					/* decompress block with dynamic huffman trees */
586 					res = .tinf_inflate_dynamic_block(d);
587 
588 					break;
589 
590 				default:
591 					return .TINF_DATA_ERROR;
592 			}
593 
594 			if (res != .TINF_OK) {
595 				return .TINF_DATA_ERROR;
596 			}
597 		} while (!bfinal);
598 
599 		return .TINF_OK;
600 	}