2 * tinf - tiny inflate library (inflate, gzip, zlib)
5 * Copyright (c) 2003 by Joergen Ibsen / Jibz
8 * http://www.ibsensoftware.com/
10 * This software is provided 'as-is', without any express
11 * or implied warranty. In no event will the authors be
12 * held liable for any damages arising from the use of
15 * Permission is granted to anyone to use this software
16 * for any purpose, including commercial applications,
17 * and to alter it and redistribute it freely, subject to
18 * the following restrictions:
20 * 1. The origin of this software must not be
21 * misrepresented; you must not claim that you
22 * wrote the original software. If you use this
23 * software in a product, an acknowledgment in
24 * the product documentation would be appreciated
25 * but is not required.
27 * 2. Altered source versions must be plainly marked
28 * as such, and must not be misrepresented as
29 * being the original software.
31 * 3. This notice may not be removed or altered from
32 * any source distribution.
35 * This D port was made by Ketmar // Invisible Vector
36 * ketmar@ketmar.no-ip.org
38 module iv
.inflate
/*is aliced*/;
41 // ////////////////////////////////////////////////////////////////////////// //
45 mixin(NewExceptionClass
!"InflateError");
46 mixin(NewExceptionClass
!("InflateEOF", "InflateError"));
49 ////////////////////////////////////////////////////////////////////////////////
51 * Adler-32 algorithm taken from the zlib source, which is
52 * Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
54 /// Adler-32 checksum computer
58 enum { BASE
= 65521, NMAX
= 5552 }
59 enum normS1S2
= `s1 %= BASE; s2 %= BASE;`;
61 template genByteProcessors(int count
) {
63 enum genByteProcessors
= `s1 += *dta++;s2 += s1;`~genByteProcessors
!(count
-1);
65 enum genByteProcessors
= "";
73 * Computes the Adler-32 checksum. We can do `Adler32(buf)`.
81 static uint opCall(T
) (T
[] data
) {
94 /// get current Adler-32 sum
95 @property uint result () const pure { pragma(inline
, true); return ((s2
<<16)|s1
); }
98 void doBuffer(T
) (T
[] data
) @trusted {
99 if (data
.length
== 0) return;
100 usize len
= data
.length
*data
[0].sizeof
; // length in bytes
101 const(ubyte)* dta
= cast(const(ubyte)*)data
.ptr
;
102 foreach (immutable _
; 0..len
/NMAX
) {
103 foreach (immutable _
; 0..NMAX
/16) { mixin(genByteProcessors
!(16)); }
108 foreach (immutable _
; 0..len
) { mixin(genByteProcessors
!(1)); }
114 void doByte(T
) (T
bt)
116 if (is(T
== char) ||
is(T
== byte) ||
is(T
== ubyte) ||
117 is(T
== const char) ||
is(T
== const byte) ||
is(T
== const ubyte) ||
118 is(T
== immutable char) ||
is(T
== immutable byte) ||
is(T
== immutable ubyte))
128 * Computes the Adler-32 checksum.
136 alias adler32
= Adler32
;
139 // -----------------------------------------------------------------------------
140 // internal data structures
142 private struct Tree
{
143 ushort[16] table
; // table of code length counts
144 ushort[288] trans
; // code -> symbol translation table
146 @disable this (this); /* disable copying */
148 // given an array of code lengths, build a tree
149 void buildTree (const(ubyte)[] lengths
) @trusted {
150 if (lengths
.length
< 1) throw new InflateError("invalid lengths");
151 ushort[16] offs
= void;
153 // clear code length count table
155 // scan symbol lengths, and sum code length counts
156 foreach (immutable l
; lengths
) {
157 if (l
>= 16) throw new InflateError("invalid lengths");
161 // compute offset table for distribution sort
162 foreach (immutable i
, immutable n
; table
) {
166 // create code->symbol translation table (symbols sorted by code)
167 foreach (ushort i
, immutable l
; lengths
) {
169 auto n
= offs
.ptr
[l
]++;
170 if (n
>= 288) throw new InflateError("invalid lengths");
178 // -----------------------------------------------------------------------------
179 // stream of unpacked data
183 bool delegate (out ubyte bt) readOneByte
= null;
186 uint bytesLeft
= void; // bytes to copy both for compressed and for uncompressed blocks
187 uint matchOfs
= void; // match offset for inflated block
188 const(Tree
)* lt
= void; // dynamic length/symbol tree
189 const(Tree
)* dt = void; // dynamic distance tree
190 bool doingFinalBlock
= false; // stop on next processBlockHeader()
194 ExpectZLibHeader
, // expecting ZLib header
195 ExpectBlock
, // expecting new block
196 RawBlock
, // uncompressed block
198 EOF
, // readOneByte() returns false before block header
199 Dead
, // some error occured, throw exception on any read
201 State state
= State
.ExpectZLibHeader
;
202 Mode mode
= Mode
.ZLib
;
209 Tree ltree
; // dynamic length/symbol tree
210 Tree dtree
; // dynamic distance tree
214 uint nmaxLeft
= Adler32
.NMAX
;
218 ubyte[65536] dict
= void;
219 uint dictEnd
; // current dict free byte
221 void dictPutByte (ubyte bt) nothrow @trusted @nogc {
222 if (dictEnd
== dict
.length
) {
223 import core
.stdc
.string
: memmove
;
225 memmove(dict
.ptr
, dict
.ptr
+dictEnd
-32768, 32768);
228 dict
.ptr
[dictEnd
++] = bt;
229 if (mode
== Mode
.ZLib
) {
232 if (--nmaxLeft
== 0) {
233 nmaxLeft
= Adler32
.NMAX
;
234 a32s1
%= Adler32
.BASE
;
235 a32s2
%= Adler32
.BASE
;
240 uint finishAdler32 () nothrow @safe @nogc {
241 a32s1
%= Adler32
.BASE
;
242 a32s2
%= Adler32
.BASE
;
243 return (a32s2
<<16)|a32s1
;
247 void setErrorState () nothrow @safe @nogc {
249 lt
= dt = null; // just in case
250 doingFinalBlock
= false; // just in case too
253 void error (string msg
, string file
=__FILE__
, usize line
=__LINE__
) @safe {
255 throw new InflateError(msg
, file
, line
);
258 void processZLibHeader () @trusted {
261 // compression parameters
262 if (!readOneByte(cmf
)) error("out of input data");
264 if (!readOneByte(flg
)) error("out of input data");
267 if ((256*cmf
+flg
)%31) error("invalid zlib checksum");
268 // check method (only deflate allowed)
269 if ((cmf
&0x0f) != 8) error("invalid compression method");
271 if ((cmf
>>4) > 7) error("invalid window size");
272 // there must be no preset dictionary
273 if (flg
&0x20) error("preset dictionaries are not supported");
274 // FYI: flg>>6 will give you compression level:
275 // 0 - compressor used fastest algorithm
276 // 1 - compressor used fast algorithm
277 // 2 - compressor used default algorithm
278 // 3 - compressor used maximum compression, slowest algorithm
279 // not that you can make any sane use of that info though...
280 // note that last 4 bytes is Adler32 checksum in big-endian format
281 // init Adler32 counters
284 nmaxLeft
= Adler32
.NMAX
;
286 state
= State
.ExpectBlock
;
289 void finishZLibData () {
291 uint a32
; // autoinit
293 foreach_reverse (immutable n
; 0..4) {
295 if (!readOneByte(bt)) error("out of input data");
296 } catch (Exception e
) {
300 a32 |
= (cast(uint)bt)<<(n
*8);
302 if (a32
!= finishAdler32()) error("invalid checksum");
305 // get one bit from source stream
310 try { ok
= readOneByte(bt); } catch (Exception e
) { setErrorState(); throw e
; }
311 if (!ok
) error("out of input data");
320 // read a num bit value from a stream and add base
321 uint readBits (ubyte num
, uint base
) {
324 immutable uint limit
= 1<<num
;
325 for (uint mask
= 1; mask
< limit
; mask
<<= 1) if (getBit()) val
+= mask
;
330 // given a data stream and a tree, decode a symbol
331 uint decodeSymbol (const(Tree
*) t
) {
332 int cur
, sum
, len
; // autoinit
333 // get more bits while code value is above sum
336 cur
= 2*cur
+getBit();
338 if (len
>= 16) error("invalid symbol");
339 sl
= t
.table
.ptr
[len
];
344 if (sum
< 0 || sum
>= 288) error("invalid symbol");
345 return t
.trans
.ptr
[sum
];
348 // given a data stream, decode dynamic trees from it
349 void decodeTrees () {
350 // special ordering of code length codes
351 static immutable ubyte[19] clcidx
= [16,17,18,0,8,7,9,6,10,5,11,4,12,3,13,2,14,1,15];
353 ubyte[288+32] lengths
;
354 uint hlit
, hdist
, hclen
;
356 // get 5 bits HLIT (257-286)
357 hlit
= readBits(5, 257);
358 // get 5 bits HDIST (1-32)
359 hdist
= readBits(5, 1);
360 if (hlit
+hdist
> 288+32) error("invalid tree");
361 // get 4 bits HCLEN (4-19)
362 hclen
= readBits(4, 4);
363 if (hclen
> 19) error("invalid tree");
365 // read code lengths for code length alphabet
366 foreach (immutable i
; 0..hclen
) lengths
[clcidx
[i
]] = cast(ubyte)readBits(3, 0); // get 3 bits code length (0-7)
367 // build code length tree
368 try { codeTree
.buildTree(lengths
[0..19]); } catch (Exception e
) { setErrorState(); throw e
; }
369 // decode code lengths for the dynamic trees
370 for (num
= 0; num
< hlit
+hdist
; ) {
372 uint sym
= decodeSymbol(&codeTree
);
374 case 16: // copy previous code length 3-6 times (read 2 bits)
375 if (num
== 0) error("invalid tree");
377 length
= readBits(2, 3);
379 case 17: // repeat code length 0 for 3-10 times (read 3 bits)
381 length
= readBits(3, 3);
383 case 18: // repeat code length 0 for 11-138 times (read 7 bits)
385 length
= readBits(7, 11);
387 default: // values 0-15 represent the actual code lengths
388 if (sym
>= 19) error("invalid tree symbol");
394 if (num
+length
> 288+32) error("invalid tree");
395 while (length
-- > 0) lengths
[num
++] = bt;
397 // build dynamic trees
399 ltree
.buildTree(lengths
[0..hlit
]);
400 dtree
.buildTree(lengths
[hlit
..hlit
+hdist
]);
401 } catch (Exception e
) {
407 // return true if char was read
408 bool processInflatedBlock (out ubyte bt) {
410 // copying match; all checks already done
412 bt = dict
[dictEnd
-matchOfs
];
414 uint sym
= decodeSymbol(lt
);
416 // end of block, fix state
417 state
= State
.ExpectBlock
;
425 uint dist
, length
, offs
;
427 // possibly get more bits from length code
428 if (sym
>= 30) error("invalid symbol");
429 length
= readBits(lengthBits
[sym
], lengthBase
[sym
]);
430 dist
= decodeSymbol(dt);
431 if (dist
>= 30) error("invalid distance");
432 // possibly get more bits from distance code
433 offs
= readBits(distBits
[dist
], distBase
[dist
]);
434 if (offs
> dictEnd
) error("invalid distance");
438 return false; // no byte read yet
444 // return true if char was read
445 bool processUncompressedBlock (out ubyte bt) {
449 try { ok
= readOneByte(bt); } catch (Exception e
) { setErrorState(); throw e
; }
450 if (!ok
) error("out of input data");
454 // end of block, fix state
455 state
= State
.ExpectBlock
;
462 if (readOneByte(b0
) && readOneByte(b1
)) return cast(ushort)(b0|
(b1
<<8));
463 } catch (Exception e
) {
467 error("out of input data");
471 void processRawHeader () {
472 ushort length
= readU16();
473 ushort invlength
= readU16(); // one's complement of length
475 if (length
!= cast(ushort)(~invlength
)) error("invalid uncompressed block length");
476 bitcount
= 0; // make sure we start next block on a byte boundary
478 state
= State
.RawBlock
;
481 void processFixedHeader () nothrow @safe @nogc {
484 bytesLeft
= 0; // force reading of symbol (just in case)
485 state
= State
.CompressedBlock
;
488 void processDynamicHeader () {
489 // decode trees from stream
493 bytesLeft
= 0; // force reading of symbol (just in case)
494 state
= State
.CompressedBlock
;
497 // set state to State.EOF on correct EOF
498 void processBlockHeader () {
499 if (doingFinalBlock
) {
500 if (mode
== Mode
.ZLib
) finishZLibData();
501 doingFinalBlock
= false;
505 doingFinalBlock
= (getBit() != 0); // final block flag
506 // read block type (2 bits) and fix state
507 switch (readBits(2, 0)) {
508 case 0: processRawHeader(); break; // uncompressed block
509 case 1: processFixedHeader(); break; // block with fixed huffman trees
510 case 2: processDynamicHeader(); break; // block with dynamic huffman trees
511 default: error("invalid input block type");
516 bool getOneByte (out ubyte bt) {
517 bool gotbyte
= false;
519 final switch (state
) {
520 case State
.ExpectZLibHeader
: processZLibHeader(); break;
521 case State
.ExpectBlock
: processBlockHeader(); break;
522 case State
.RawBlock
: gotbyte
= processUncompressedBlock(bt); break;
523 case State
.CompressedBlock
: gotbyte
= processInflatedBlock(bt); break;
524 case State
.EOF
: return false;
525 case State
.Dead
: error("dead stream"); break;
534 enum Mode
{ ZLib
, Deflate
};
537 @disable this (this);
540 * Initialize decompression stream.
544 * must either set bt to next byte and return true or return false on EOF;
545 * note that it will not be called anymoer after EOF or error;
547 * mode = stream format; either headerless 'deflate' stream or 'zlib' stream
550 * InflateError on error
552 this (bool delegate (out ubyte bt) dgb
, Mode mode
=Mode
.ZLib
) {
553 if (dgb
is null) dgb
= (out ubyte bt) => false;
558 this (Mode mode
) @trusted {
563 void reinit (bool delegate (out ubyte bt) dgb
=null, Mode mode
=Mode
.ZLib
) {
564 if (dgb
!is null) readOneByte
= dgb
;
565 state
= State
.ExpectBlock
;
570 state
= (mode
== Mode
.ZLib ? State
.ExpectZLibHeader
: State
.ExpectBlock
);
571 doingFinalBlock
= false;
572 if (readOneByte
is null) readOneByte
= (out ubyte bt) => false;
576 * Check stream header. Can be called after this() or reinit().
582 * InflateError on error
584 void checkStreamHeader () {
585 if (mode
== Mode
.ZLib
&& state
== State
.ExpectZLibHeader
) processZLibHeader();
589 * Get another byte from stream.
592 * one decompressed byte
596 * InflateError on error
600 if (!getOneByte(res
)) throw new InflateEOF("no more data");
605 * Read bytes from stream. Almost similar to File.rawRead().
608 * buf = destination buffer
611 * destination buffer or slice of destination buffer if EOF encountered
614 * InflateError on error
616 T
[] rawRead(T
) (T
[] buf
) {
617 auto len
= buf
.length
*T
.sizeof
;
618 auto dst
= cast(ubyte*)buf
.ptr
;
621 if (!getOneByte(*dst
)) {
622 // check if the last 'dest' item is fully decompressed
623 static if (T
.sizeof
> 1) { if ((cast(usize
)dst
-buf
.ptr
)%T
.sizeof
) error("partial data"); }
624 return buf
[0..cast(usize
)(dst
-buf
.ptr
)];
631 @property bool eof () const pure nothrow @safe @nogc { pragma(inline
, true); return (state
== State
.EOF
); }
632 @property bool invalid () const pure nothrow @safe @nogc { pragma(inline
, true); return (state
== State
.Dead
); }
636 // -----------------------------------------------------------------------------
638 // private global data
639 // build it using CTFE
641 // fixed length/symbol tree
642 immutable Tree sltree
= {
647 foreach (immutable i
; 0..24) sl
.trans
[i
] = cast(ushort)(256+i
);
648 foreach (immutable ushort i
; 0..144) sl
.trans
[24+i
] = i
;
649 foreach (immutable i
; 0..8) sl
.trans
[24+144+i
] = cast(ushort)(280+i
);
650 foreach (immutable i
; 0..112) sl
.trans
[24+144+8+i
] = cast(ushort)(144+i
);
654 // fixed distance tree
655 immutable Tree sdtree
= {
658 foreach (immutable ushort i
; 0..32) sd
.trans
[i
] = i
;
662 void fillBits (ubyte[] bits
, uint delta
) @safe nothrow {
664 foreach (immutable i
; 0..30-delta
) bits
[i
+delta
] = cast(ubyte)(i
/delta
);
667 void fillBase (ushort[] base
, immutable(ubyte[30]) bits
, ushort first
) @safe nothrow {
669 foreach (immutable i
; 0..30) {
675 // extra bits and base tables for length codes
676 immutable ubyte[30] lengthBits
= {
679 bits
[28] = 0; // fix a special case
683 immutable ushort[30] lengthBase
= {
687 fillBase(base
, bits
, 3);
688 base
[28] = 258; // fix a special case
692 // extra bits and base tables for distance codes
693 immutable ubyte[30] distBits
= {
699 immutable ushort[30] distBase
= {
700 enum bits
= distBits
;
702 fillBase(base
, bits
, 1);