3
// Copyright (C) 2001 Mike Krueger
4
// Copyright (C) 2004 John Reilly
6
// This file was translated from java, it was part of the GNU Classpath
7
// Copyright (C) 2001 Free Software Foundation, Inc.
9
// This program is free software; you can redistribute it and/or
10
// modify it under the terms of the GNU General Public License
11
// as published by the Free Software Foundation; either version 2
12
// of the License, or (at your option) any later version.
14
// This program is distributed in the hope that it will be useful,
15
// but WITHOUT ANY WARRANTY; without even the implied warranty of
16
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
// GNU General Public License for more details.
19
// You should have received a copy of the GNU General Public License
20
// along with this program; if not, write to the Free Software
21
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
23
// Linking this library statically or dynamically with other modules is
24
// making a combined work based on this library. Thus, the terms and
25
// conditions of the GNU General Public License cover the whole
28
// As a special exception, the copyright holders of this library give you
29
// permission to link this library with independent modules to produce an
30
// executable, regardless of the license terms of these independent
31
// modules, and to copy and distribute the resulting executable under
32
// terms of your choice, provided that you also meet, for each linked
33
// independent module, the terms and conditions of the license of that
34
// module. An independent module is a module which is not derived from
35
// or based on this library. If you modify this library, you may extend
36
// this exception to your version of the library, but you are not
37
// obligated to do so. If you do not wish to do so, delete this
38
// exception statement from your version.
42
using PdfSharp.SharpZipLib.Checksums;
43
using PdfSharp.SharpZipLib.Zip.Compression.Streams;
45
namespace PdfSharp.SharpZipLib.Zip.Compression
49
/// Inflater is used to decompress data that has been compressed according
50
/// to the "deflate" standard described in rfc1951.
52
/// By default Zlib (rfc1950) headers and footers are expected in the input.
53
/// You can use constructor <code> public Inflater(bool noHeader)</code> passing true
54
/// if there is no Zlib header information
56
/// The usage is as following. First you have to set some input with
57
/// <code>setInput()</code>, then inflate() it. If inflate doesn't
58
/// inflate any bytes there may be three reasons:
60
/// <li>needsInput() returns true because the input buffer is empty.
61
/// You have to provide more input with <code>setInput()</code>.
62
/// NOTE: needsInput() also returns true when, the stream is finished.
64
/// <li>needsDictionary() returns true, you have to provide a preset
65
/// dictionary with <code>setDictionary()</code>.</li>
66
/// <li>finished() returns true, the inflater has finished.</li>
68
/// Once the first output byte is produced, a dictionary will not be
69
/// needed at a later stage.
71
/// author of the original java version : John Leuner, Jochen Hoenicke
73
internal class Inflater
76
/// Copy lengths for literal codes 257..285
78
static int[] CPLENS = {
79
3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
80
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258
84
/// Extra bits for literal codes 257..285
86
static int[] CPLEXT = {
87
0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
88
3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0
92
/// Copy offsets for distance codes 0..29
94
static int[] CPDIST = {
95
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
96
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
97
8193, 12289, 16385, 24577
101
/// Extra bits for distance codes
103
static int[] CPDEXT = {
104
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
105
7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
110
/// These are the possible states for an inflater
112
const int DECODE_HEADER = 0;
113
const int DECODE_DICT = 1;
114
const int DECODE_BLOCKS = 2;
115
const int DECODE_STORED_LEN1 = 3;
116
const int DECODE_STORED_LEN2 = 4;
117
const int DECODE_STORED = 5;
118
const int DECODE_DYN_HEADER = 6;
119
const int DECODE_HUFFMAN = 7;
120
const int DECODE_HUFFMAN_LENBITS = 8;
121
const int DECODE_HUFFMAN_DIST = 9;
122
const int DECODE_HUFFMAN_DISTBITS = 10;
123
const int DECODE_CHKSUM = 11;
124
const int FINISHED = 12;
127
/// This variable contains the current state.
132
/// The adler checksum of the dictionary or of the decompressed
133
/// stream, as it is written in the header resp. footer of the
134
/// compressed stream.
135
/// Only valid if mode is DECODE_DICT or DECODE_CHKSUM.
140
/// The number of bits needed to complete the current state. This
141
/// is valid, if mode is DECODE_DICT, DECODE_CHKSUM,
142
/// DECODE_HUFFMAN_LENBITS or DECODE_HUFFMAN_DISTBITS.
150
/// True, if the last block flag was set in the last block of the
151
/// inflated stream. This means that the stream ends after the
157
/// The total number of inflated bytes.
162
/// The total number of bytes set with setInput(). This is not the
163
/// value returned by the TotalIn property, since this also includes the
164
/// unprocessed input.
169
/// This variable stores the noHeader flag that was given to the constructor.
170
/// True means, that the inflated stream doesn't contain a Zlib header or
175
StreamManipulator input;
176
OutputWindow outputWindow;
177
InflaterDynHeader dynHeader;
178
InflaterHuffmanTree litlenTree, distTree;
182
/// Creates a new inflater or RFC1951 decompressor
183
/// RFC1950/Zlib headers and footers will be expected in the input data
185
public Inflater() : this(false)
190
/// Creates a new inflater.
192
/// <param name="noHeader">
193
/// True if no RFC1950/Zlib header and footer fields are expected in the input data
195
/// This is used for GZIPed/Zipped input.
197
/// For compatibility with
198
/// Sun JDK you should provide one byte of input more than needed in
201
public Inflater(bool noHeader)
203
this.noHeader = noHeader;
204
this.adler = new Adler32();
205
input = new StreamManipulator();
206
outputWindow = new OutputWindow();
207
mode = noHeader ? DECODE_BLOCKS : DECODE_HEADER;
211
/// Resets the inflater so that a new stream can be decompressed. All
212
/// pending input and output will be discarded.
216
mode = noHeader ? DECODE_BLOCKS : DECODE_HEADER;
217
totalIn = totalOut = 0;
219
outputWindow.Reset();
228
/// Decodes a zlib/RFC1950 header.
231
/// False if more input is needed.
233
/// <exception cref="SharpZipBaseException">
234
/// The header is invalid.
236
private bool DecodeHeader()
238
int header = input.PeekBits(16);
244
/* The header is written in "wrong" byte order */
245
header = ((header << 8) | (header >> 8)) & 0xffff;
246
if (header % 31 != 0) {
247
throw new SharpZipBaseException("Header checksum illegal");
250
if ((header & 0x0f00) != (Deflater.DEFLATED << 8)) {
251
throw new SharpZipBaseException("Compression Method unknown");
254
/* Maximum size of the backwards window in bits.
255
* We currently ignore this, but we could use it to make the
256
* inflater window more space efficient. On the other hand the
257
* full window (15 bits) is needed most times, anyway.
258
int max_wbits = ((header & 0x7000) >> 12) + 8;
261
if ((header & 0x0020) == 0) { // Dictionary flag?
262
mode = DECODE_BLOCKS;
271
/// Decodes the dictionary checksum after the deflate header.
274
/// False if more input is needed.
276
private bool DecodeDict()
278
while (neededBits > 0) {
279
int dictByte = input.PeekBits(8);
284
readAdler = (readAdler << 8) | dictByte;
291
/// Decodes the huffman encoded symbols in the input stream.
294
/// false if more input is needed, true if output window is
295
/// full or the current block ends.
297
/// <exception cref="SharpZipBaseException">
298
/// if deflated stream is invalid.
300
private bool DecodeHuffman()
302
int free = outputWindow.GetFreeSpace();
303
while (free >= 258) {
307
/* This is the inner loop so it is optimized a bit */
308
while (((symbol = litlenTree.GetSymbol(input)) & ~0xff) == 0) {
309
outputWindow.Write(symbol);
319
/* symbol == 256: end of block */
322
mode = DECODE_BLOCKS;
328
repLength = CPLENS[symbol - 257];
329
neededBits = CPLEXT[symbol - 257];
330
} catch (Exception) {
331
throw new SharpZipBaseException("Illegal rep length code");
333
goto case DECODE_HUFFMAN_LENBITS; /* fall through */
335
case DECODE_HUFFMAN_LENBITS:
336
if (neededBits > 0) {
337
mode = DECODE_HUFFMAN_LENBITS;
338
int i = input.PeekBits(neededBits);
342
input.DropBits(neededBits);
345
mode = DECODE_HUFFMAN_DIST;
346
goto case DECODE_HUFFMAN_DIST;/* fall through */
348
case DECODE_HUFFMAN_DIST:
349
symbol = distTree.GetSymbol(input);
355
repDist = CPDIST[symbol];
356
neededBits = CPDEXT[symbol];
357
} catch (Exception) {
358
throw new SharpZipBaseException("Illegal rep dist code");
361
goto case DECODE_HUFFMAN_DISTBITS;/* fall through */
363
case DECODE_HUFFMAN_DISTBITS:
364
if (neededBits > 0) {
365
mode = DECODE_HUFFMAN_DISTBITS;
366
int i = input.PeekBits(neededBits);
370
input.DropBits(neededBits);
374
outputWindow.Repeat(repLength, repDist);
376
mode = DECODE_HUFFMAN;
380
throw new SharpZipBaseException("Inflater unknown mode");
387
/// Decodes the adler checksum after the deflate stream.
390
/// false if more input is needed.
392
/// <exception cref="SharpZipBaseException">
393
/// If checksum doesn't match.
395
private bool DecodeChksum()
397
while (neededBits > 0) {
398
int chkByte = input.PeekBits(8);
403
readAdler = (readAdler << 8) | chkByte;
407
if ((int) adler.Value != readAdler) {
408
throw new SharpZipBaseException("Adler chksum doesn't match: " + (int)adler.Value + " vs. " + readAdler);
415
/// Decodes the deflated stream.
418
/// false if more input is needed, or if finished.
420
/// <exception cref="SharpZipBaseException">
421
/// if deflated stream is invalid.
423
private bool Decode()
427
return DecodeHeader();
431
return DecodeChksum();
439
input.SkipToByteBoundary();
441
mode = DECODE_CHKSUM;
446
int type = input.PeekBits(3);
452
if ((type & 1) != 0) {
456
case DeflaterConstants.STORED_BLOCK:
457
input.SkipToByteBoundary();
458
mode = DECODE_STORED_LEN1;
460
case DeflaterConstants.STATIC_TREES:
461
litlenTree = InflaterHuffmanTree.defLitLenTree;
462
distTree = InflaterHuffmanTree.defDistTree;
463
mode = DECODE_HUFFMAN;
465
case DeflaterConstants.DYN_TREES:
466
dynHeader = new InflaterDynHeader();
467
mode = DECODE_DYN_HEADER;
470
throw new SharpZipBaseException("Unknown block type " + type);
474
case DECODE_STORED_LEN1:
476
if ((uncomprLen = input.PeekBits(16)) < 0) {
480
mode = DECODE_STORED_LEN2;
482
goto case DECODE_STORED_LEN2; /* fall through */
484
case DECODE_STORED_LEN2:
486
int nlen = input.PeekBits(16);
491
if (nlen != (uncomprLen ^ 0xffff)) {
492
throw new SharpZipBaseException("broken uncompressed block");
494
mode = DECODE_STORED;
496
goto case DECODE_STORED;/* fall through */
500
int more = outputWindow.CopyStored(input, uncomprLen);
502
if (uncomprLen == 0) {
503
mode = DECODE_BLOCKS;
506
return !input.IsNeedingInput;
509
case DECODE_DYN_HEADER:
510
if (!dynHeader.Decode(input)) {
514
litlenTree = dynHeader.BuildLitLenTree();
515
distTree = dynHeader.BuildDistTree();
516
mode = DECODE_HUFFMAN;
517
goto case DECODE_HUFFMAN; /* fall through */
520
case DECODE_HUFFMAN_LENBITS:
521
case DECODE_HUFFMAN_DIST:
522
case DECODE_HUFFMAN_DISTBITS:
523
return DecodeHuffman();
529
throw new SharpZipBaseException("Inflater.Decode unknown mode");
534
/// Sets the preset dictionary. This should only be called, if
535
/// needsDictionary() returns true and it should set the same
536
/// dictionary, that was used for deflating. The getAdler()
537
/// function returns the checksum of the dictionary needed.
539
/// <param name="buffer">
542
public void SetDictionary(byte[] buffer)
544
SetDictionary(buffer, 0, buffer.Length);
548
/// Sets the preset dictionary. This should only be called, if
549
/// needsDictionary() returns true and it should set the same
550
/// dictionary, that was used for deflating. The getAdler()
551
/// function returns the checksum of the dictionary needed.
553
/// <param name="buffer">
556
/// <param name="offset">
557
/// The offset into buffer where the dictionary starts.
559
/// <param name="len">
560
/// The length of the dictionary.
562
/// <exception cref="System.InvalidOperationException">
563
/// No dictionary is needed.
565
/// <exception cref="SharpZipBaseException">
566
/// The adler checksum for the buffer is invalid
568
public void SetDictionary(byte[] buffer, int offset, int len)
570
if (!IsNeedingDictionary) {
571
throw new InvalidOperationException();
574
adler.Update(buffer, offset, len);
575
if ((int)adler.Value != readAdler) {
576
throw new SharpZipBaseException("Wrong adler checksum");
579
outputWindow.CopyDict(buffer, offset, len);
580
mode = DECODE_BLOCKS;
584
/// Sets the input. This should only be called, if needsInput()
587
/// <param name="buf">
590
public void SetInput(byte[] buf)
592
SetInput(buf, 0, buf.Length);
596
/// Sets the input. This should only be called, if needsInput()
599
/// <param name="buffer">
600
/// The source of input data
602
/// <param name="offset">
603
/// The offset into buffer where the input starts.
605
/// <param name="length">
606
/// The number of bytes of input to use.
608
/// <exception cref="System.InvalidOperationException">
609
/// No input is needed.
611
/// <exception cref="System.ArgumentOutOfRangeException">
612
/// The off and/or len are wrong.
614
public void SetInput(byte[] buffer, int offset, int length)
616
input.SetInput(buffer, offset, length);
621
/// Inflates the compressed stream to the output buffer. If this
622
/// returns 0, you should check, whether needsDictionary(),
623
/// needsInput() or finished() returns true, to determine why no
624
/// further output is produced.
626
/// <param name = "buf">
627
/// the output buffer.
630
/// the number of bytes written to the buffer, 0 if no further
631
/// output can be produced.
633
/// <exception cref="System.ArgumentOutOfRangeException">
634
/// if buf has length 0.
636
/// <exception cref="System.FormatException">
637
/// if deflated stream is invalid.
639
public int Inflate(byte[] buf)
641
return Inflate(buf, 0, buf.Length);
645
/// Inflates the compressed stream to the output buffer. If this
646
/// returns 0, you should check, whether needsDictionary(),
647
/// needsInput() or finished() returns true, to determine why no
648
/// further output is produced.
650
/// <param name = "buf">
651
/// the output buffer.
653
/// <param name = "offset">
654
/// the offset into buffer where the output should start.
656
/// <param name = "len">
657
/// the maximum length of the output.
660
/// the number of bytes written to the buffer, 0 if no further output can be produced.
662
/// <exception cref="System.ArgumentOutOfRangeException">
663
/// if len is <= 0.
665
/// <exception cref="System.ArgumentOutOfRangeException">
666
/// if the offset and/or len are wrong.
668
/// <exception cref="System.FormatException">
669
/// if deflated stream is invalid.
671
public int Inflate(byte[] buf, int offset, int len)
674
throw new ArgumentOutOfRangeException("len < 0");
677
// Special case: len may be zero
679
if (IsFinished == false) {// -jr- 08-Nov-2003 INFLATE_BUG fix..
685
// Check for correct buff, off, len triple
686
if (off < 0 || off + len >= buf.Length) {
687
throw new ArgumentException("off/len outside buf bounds");
693
if (mode != DECODE_CHKSUM) {
694
/* Don't give away any output, if we are waiting for the
695
* checksum in the input stream.
697
* With this trick we have always:
698
* needsInput() and not finished()
699
* implies more output can be produced.
701
more = outputWindow.CopyOutput(buf, offset, len);
702
adler.Update(buf, offset, more);
711
} while (Decode() || (outputWindow.GetAvailable() > 0 && mode != DECODE_CHKSUM));
716
/// Returns true, if the input buffer is empty.
717
/// You should then call setInput().
718
/// NOTE: This method also returns true when the stream is finished.
720
public bool IsNeedingInput {
722
return input.IsNeedingInput;
727
/// Returns true, if a preset dictionary is needed to inflate the input.
729
public bool IsNeedingDictionary {
731
return mode == DECODE_DICT && neededBits == 0;
736
/// Returns true, if the inflater has finished. This means, that no
737
/// input is needed and no output can be produced.
739
public bool IsFinished {
741
return mode == FINISHED && outputWindow.GetAvailable() == 0;
746
/// Gets the adler checksum. This is either the checksum of all
747
/// uncompressed bytes returned by inflate(), or if needsDictionary()
748
/// returns true (and thus no output was yet produced) this is the
749
/// adler checksum of the expected dictionary.
752
/// the adler checksum.
756
return IsNeedingDictionary ? readAdler : (int) adler.Value;
761
/// Gets the total number of output bytes returned by inflate().
764
/// the total number of output bytes.
766
public int TotalOut {
773
/// Gets the total number of processed compressed input bytes.
776
/// The total number of bytes of processed input bytes.
780
return totalIn - RemainingInput;
786
/// -jr test hak trying to figure out a bug
788
public int UnseenInput {
790
return totalIn - ((input.AvailableBits + 7) >> 3);
795
/// -jr test hak trying to figure out a bug
797
public int PlainTotalIn {
805
/// Gets the number of unprocessed input bytes. Useful, if the end of the
806
/// stream is reached and you want to further process the bytes after
807
/// the deflate stream.
810
/// The number of bytes of the input which have not been processed.
812
public int RemainingInput {
814
return input.AvailableBytes;