~ubuntu-branches/ubuntu/trusty/pdfmod/trusty

« back to all changes in this revision

Viewing changes to lib/PdfSharp/PdfSharp.SharpZipLib/Zip/Compression/Inflater.cs

  • Committer: Bazaar Package Importer
  • Author(s): Chow Loong Jin
  • Date: 2010-06-18 03:44:46 UTC
  • Revision ID: james.westby@ubuntu.com-20100618034446-bogifrsscpayp361
Tags: upstream-0.8.3
ImportĀ upstreamĀ versionĀ 0.8.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Inflater.cs
 
2
//
 
3
// Copyright (C) 2001 Mike Krueger
 
4
// Copyright (C) 2004 John Reilly
 
5
//
 
6
// This file was translated from java, it was part of the GNU Classpath
 
7
// Copyright (C) 2001 Free Software Foundation, Inc.
 
8
//
 
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.
 
13
//
 
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.
 
18
//
 
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.
 
22
//
 
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
 
26
// combination.
 
27
// 
 
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.
 
39
 
 
40
using System;
 
41
 
 
42
using PdfSharp.SharpZipLib.Checksums;
 
43
using PdfSharp.SharpZipLib.Zip.Compression.Streams;
 
44
 
 
45
namespace PdfSharp.SharpZipLib.Zip.Compression 
 
46
{
 
47
        
 
48
        /// <summary>
 
49
        /// Inflater is used to decompress data that has been compressed according
 
50
        /// to the "deflate" standard described in rfc1951.
 
51
        /// 
 
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
 
55
        ///
 
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:
 
59
        /// <ul>
 
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.
 
63
        /// </li>
 
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>
 
67
        /// </ul>
 
68
        /// Once the first output byte is produced, a dictionary will not be
 
69
        /// needed at a later stage.
 
70
        ///
 
71
        /// author of the original java version : John Leuner, Jochen Hoenicke
 
72
        /// </summary>
 
73
        internal class Inflater
 
74
        {
 
75
                /// <summary>
 
76
                /// Copy lengths for literal codes 257..285
 
77
                /// </summary>
 
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
 
81
                                                          };
 
82
                
 
83
                /// <summary>
 
84
                /// Extra bits for literal codes 257..285
 
85
                /// </summary>
 
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
 
89
                                                          };
 
90
                
 
91
                /// <summary>
 
92
                /// Copy offsets for distance codes 0..29
 
93
                /// </summary>
 
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
 
98
                                                          };
 
99
                
 
100
                /// <summary>
 
101
                /// Extra bits for distance codes
 
102
                /// </summary>
 
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,
 
106
                                                                12, 12, 13, 13
 
107
                                                          };
 
108
                
 
109
                /// <summary>
 
110
                /// These are the possible states for an inflater
 
111
                /// </summary>
 
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;
 
125
                
 
126
                /// <summary>
 
127
                /// This variable contains the current state.
 
128
                /// </summary>
 
129
                int mode;
 
130
                
 
131
                /// <summary>
 
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.
 
136
                /// </summary>
 
137
                int readAdler;
 
138
                
 
139
                /// <summary>
 
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.
 
143
                /// </summary>
 
144
                int neededBits;
 
145
                int repLength;
 
146
                int repDist;
 
147
                int uncomprLen;
 
148
                
 
149
                /// <summary>
 
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
 
152
                /// current block.
 
153
                /// </summary>
 
154
                bool isLastBlock;
 
155
                
 
156
                /// <summary>
 
157
                /// The total number of inflated bytes.
 
158
                /// </summary>
 
159
                int totalOut;
 
160
                
 
161
                /// <summary>
 
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.
 
165
                /// </summary>
 
166
                int totalIn;
 
167
                
 
168
                /// <summary>
 
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 
 
171
                /// footer.
 
172
                /// </summary>
 
173
                bool noHeader;
 
174
                
 
175
                StreamManipulator input;
 
176
                OutputWindow outputWindow;
 
177
                InflaterDynHeader dynHeader;
 
178
                InflaterHuffmanTree litlenTree, distTree;
 
179
                Adler32 adler;
 
180
                
 
181
                /// <summary>
 
182
                /// Creates a new inflater or RFC1951 decompressor
 
183
                /// RFC1950/Zlib headers and footers will be expected in the input data
 
184
                /// </summary>
 
185
                public Inflater() : this(false)
 
186
                {
 
187
                }
 
188
                
 
189
                /// <summary>
 
190
                /// Creates a new inflater.
 
191
                /// </summary>
 
192
                /// <param name="noHeader">
 
193
                /// True if no RFC1950/Zlib header and footer fields are expected in the input data
 
194
                /// 
 
195
                /// This is used for GZIPed/Zipped input.
 
196
                /// 
 
197
                /// For compatibility with
 
198
                /// Sun JDK you should provide one byte of input more than needed in
 
199
                /// this case.
 
200
                /// </param>
 
201
                public Inflater(bool noHeader)
 
202
                {
 
203
                        this.noHeader = noHeader;
 
204
                        this.adler = new Adler32();
 
205
                        input = new StreamManipulator();
 
206
                        outputWindow = new OutputWindow();
 
207
                        mode = noHeader ? DECODE_BLOCKS : DECODE_HEADER;
 
208
                }
 
209
                
 
210
                /// <summary>
 
211
                /// Resets the inflater so that a new stream can be decompressed.  All
 
212
                /// pending input and output will be discarded.
 
213
                /// </summary>
 
214
                public void Reset()
 
215
                {
 
216
                        mode = noHeader ? DECODE_BLOCKS : DECODE_HEADER;
 
217
                        totalIn = totalOut = 0;
 
218
                        input.Reset();
 
219
                        outputWindow.Reset();
 
220
                        dynHeader = null;
 
221
                        litlenTree = null;
 
222
                        distTree = null;
 
223
                        isLastBlock = false;
 
224
                        adler.Reset();
 
225
                }
 
226
                
 
227
                /// <summary>
 
228
                /// Decodes a zlib/RFC1950 header.
 
229
                /// </summary>
 
230
                /// <returns>
 
231
                /// False if more input is needed.
 
232
                /// </returns>
 
233
                /// <exception cref="SharpZipBaseException">
 
234
                /// The header is invalid.
 
235
                /// </exception>
 
236
                private bool DecodeHeader()
 
237
                {
 
238
                        int header = input.PeekBits(16);
 
239
                        if (header < 0) {
 
240
                                return false;
 
241
                        }
 
242
                        input.DropBits(16);
 
243
                        
 
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");
 
248
                        }
 
249
                        
 
250
                        if ((header & 0x0f00) != (Deflater.DEFLATED << 8)) {
 
251
                                throw new SharpZipBaseException("Compression Method unknown");
 
252
                        }
 
253
                        
 
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;
 
259
                        */
 
260
                        
 
261
                        if ((header & 0x0020) == 0) { // Dictionary flag?
 
262
                                mode = DECODE_BLOCKS;
 
263
                        } else {
 
264
                                mode = DECODE_DICT;
 
265
                                neededBits = 32;
 
266
                        }
 
267
                        return true;
 
268
                }
 
269
                
 
270
                /// <summary>
 
271
                /// Decodes the dictionary checksum after the deflate header.
 
272
                /// </summary>
 
273
                /// <returns>
 
274
                /// False if more input is needed.
 
275
                /// </returns>
 
276
                private bool DecodeDict()
 
277
                {
 
278
                        while (neededBits > 0) {
 
279
                                int dictByte = input.PeekBits(8);
 
280
                                if (dictByte < 0) {
 
281
                                        return false;
 
282
                                }
 
283
                                input.DropBits(8);
 
284
                                readAdler = (readAdler << 8) | dictByte;
 
285
                                neededBits -= 8;
 
286
                        }
 
287
                        return false;
 
288
                }
 
289
                
 
290
                /// <summary>
 
291
                /// Decodes the huffman encoded symbols in the input stream.
 
292
                /// </summary>
 
293
                /// <returns>
 
294
                /// false if more input is needed, true if output window is
 
295
                /// full or the current block ends.
 
296
                /// </returns>
 
297
                /// <exception cref="SharpZipBaseException">
 
298
                /// if deflated stream is invalid.
 
299
                /// </exception>
 
300
                private bool DecodeHuffman()
 
301
                {
 
302
                        int free = outputWindow.GetFreeSpace();
 
303
                        while (free >= 258) {
 
304
                                int symbol;
 
305
                                switch (mode) {
 
306
                                        case DECODE_HUFFMAN:
 
307
                                                /* This is the inner loop so it is optimized a bit */
 
308
                                                while (((symbol = litlenTree.GetSymbol(input)) & ~0xff) == 0) {
 
309
                                                        outputWindow.Write(symbol);
 
310
                                                        if (--free < 258) {
 
311
                                                                return true;
 
312
                                                        }
 
313
                                                }
 
314
                                                
 
315
                                                if (symbol < 257) {
 
316
                                                        if (symbol < 0) {
 
317
                                                                return false;
 
318
                                                        } else {
 
319
                                                                /* symbol == 256: end of block */
 
320
                                                                distTree = null;
 
321
                                                                litlenTree = null;
 
322
                                                                mode = DECODE_BLOCKS;
 
323
                                                                return true;
 
324
                                                        }
 
325
                                                }
 
326
                                                
 
327
                                                try {
 
328
                                                        repLength = CPLENS[symbol - 257];
 
329
                                                        neededBits = CPLEXT[symbol - 257];
 
330
                                                } catch (Exception) {
 
331
                                                        throw new SharpZipBaseException("Illegal rep length code");
 
332
                                                }
 
333
                                                goto case DECODE_HUFFMAN_LENBITS; /* fall through */
 
334
                                                
 
335
                                        case DECODE_HUFFMAN_LENBITS:
 
336
                                                if (neededBits > 0) {
 
337
                                                        mode = DECODE_HUFFMAN_LENBITS;
 
338
                                                        int i = input.PeekBits(neededBits);
 
339
                                                        if (i < 0) {
 
340
                                                                return false;
 
341
                                                        }
 
342
                                                        input.DropBits(neededBits);
 
343
                                                        repLength += i;
 
344
                                                }
 
345
                                                mode = DECODE_HUFFMAN_DIST;
 
346
                                                goto case DECODE_HUFFMAN_DIST;/* fall through */
 
347
                                                
 
348
                                        case DECODE_HUFFMAN_DIST:
 
349
                                                symbol = distTree.GetSymbol(input);
 
350
                                                if (symbol < 0) {
 
351
                                                        return false;
 
352
                                                }
 
353
                                                
 
354
                                                try {
 
355
                                                        repDist = CPDIST[symbol];
 
356
                                                        neededBits = CPDEXT[symbol];
 
357
                                                } catch (Exception) {
 
358
                                                        throw new SharpZipBaseException("Illegal rep dist code");
 
359
                                                }
 
360
                                                
 
361
                                                goto case DECODE_HUFFMAN_DISTBITS;/* fall through */
 
362
                                                
 
363
                                        case DECODE_HUFFMAN_DISTBITS:
 
364
                                                if (neededBits > 0) {
 
365
                                                        mode = DECODE_HUFFMAN_DISTBITS;
 
366
                                                        int i = input.PeekBits(neededBits);
 
367
                                                        if (i < 0) {
 
368
                                                                return false;
 
369
                                                        }
 
370
                                                        input.DropBits(neededBits);
 
371
                                                        repDist += i;
 
372
                                                }
 
373
                                                
 
374
                                                outputWindow.Repeat(repLength, repDist);
 
375
                                                free -= repLength;
 
376
                                                mode = DECODE_HUFFMAN;
 
377
                                                break;
 
378
                                        
 
379
                                        default:
 
380
                                                throw new SharpZipBaseException("Inflater unknown mode");
 
381
                                }
 
382
                        }
 
383
                        return true;
 
384
                }
 
385
                
 
386
                /// <summary>
 
387
                /// Decodes the adler checksum after the deflate stream.
 
388
                /// </summary>
 
389
                /// <returns>
 
390
                /// false if more input is needed.
 
391
                /// </returns>
 
392
                /// <exception cref="SharpZipBaseException">
 
393
                /// If checksum doesn't match.
 
394
                /// </exception>
 
395
                private bool DecodeChksum()
 
396
                {
 
397
                        while (neededBits > 0) {
 
398
                                int chkByte = input.PeekBits(8);
 
399
                                if (chkByte < 0) {
 
400
                                        return false;
 
401
                                }
 
402
                                input.DropBits(8);
 
403
                                readAdler = (readAdler << 8) | chkByte;
 
404
                                neededBits -= 8;
 
405
                        }
 
406
 
 
407
                        if ((int) adler.Value != readAdler) {
 
408
                                throw new SharpZipBaseException("Adler chksum doesn't match: " + (int)adler.Value + " vs. " + readAdler);
 
409
                        }
 
410
                        mode = FINISHED;
 
411
                        return false;
 
412
                }
 
413
                
 
414
                /// <summary>
 
415
                /// Decodes the deflated stream.
 
416
                /// </summary>
 
417
                /// <returns>
 
418
                /// false if more input is needed, or if finished.
 
419
                /// </returns>
 
420
                /// <exception cref="SharpZipBaseException">
 
421
                /// if deflated stream is invalid.
 
422
                /// </exception>
 
423
                private bool Decode()
 
424
                {
 
425
                        switch (mode) {
 
426
                                case DECODE_HEADER:
 
427
                                        return DecodeHeader();
 
428
                                case DECODE_DICT:
 
429
                                        return DecodeDict();
 
430
                                case DECODE_CHKSUM:
 
431
                                        return DecodeChksum();
 
432
                                
 
433
                                case DECODE_BLOCKS:
 
434
                                        if (isLastBlock) {
 
435
                                                if (noHeader) {
 
436
                                                        mode = FINISHED;
 
437
                                                        return false;
 
438
                                                } else {
 
439
                                                        input.SkipToByteBoundary();
 
440
                                                        neededBits = 32;
 
441
                                                        mode = DECODE_CHKSUM;
 
442
                                                        return true;
 
443
                                                }
 
444
                                        }
 
445
                                        
 
446
                                        int type = input.PeekBits(3);
 
447
                                        if (type < 0) {
 
448
                                                return false;
 
449
                                        }
 
450
                                        input.DropBits(3);
 
451
                                        
 
452
                                        if ((type & 1) != 0) {
 
453
                                                isLastBlock = true;
 
454
                                        }
 
455
                                        switch (type >> 1){
 
456
                                                case DeflaterConstants.STORED_BLOCK:
 
457
                                                        input.SkipToByteBoundary();
 
458
                                                        mode = DECODE_STORED_LEN1;
 
459
                                                        break;
 
460
                                                case DeflaterConstants.STATIC_TREES:
 
461
                                                        litlenTree = InflaterHuffmanTree.defLitLenTree;
 
462
                                                        distTree = InflaterHuffmanTree.defDistTree;
 
463
                                                        mode = DECODE_HUFFMAN;
 
464
                                                        break;
 
465
                                                case DeflaterConstants.DYN_TREES:
 
466
                                                        dynHeader = new InflaterDynHeader();
 
467
                                                        mode = DECODE_DYN_HEADER;
 
468
                                                        break;
 
469
                                                default:
 
470
                                                        throw new SharpZipBaseException("Unknown block type " + type);
 
471
                                        }
 
472
                                        return true;
 
473
                                
 
474
                                case DECODE_STORED_LEN1: 
 
475
                                {
 
476
                                        if ((uncomprLen = input.PeekBits(16)) < 0) {
 
477
                                                return false;
 
478
                                        }
 
479
                                        input.DropBits(16);
 
480
                                        mode = DECODE_STORED_LEN2;
 
481
                                }
 
482
                                        goto case DECODE_STORED_LEN2; /* fall through */
 
483
                                        
 
484
                                case DECODE_STORED_LEN2: 
 
485
                                {
 
486
                                        int nlen = input.PeekBits(16);
 
487
                                        if (nlen < 0) {
 
488
                                                return false;
 
489
                                        }
 
490
                                        input.DropBits(16);
 
491
                                        if (nlen != (uncomprLen ^ 0xffff)) {
 
492
                                                throw new SharpZipBaseException("broken uncompressed block");
 
493
                                        }
 
494
                                        mode = DECODE_STORED;
 
495
                                }
 
496
                                        goto case DECODE_STORED;/* fall through */
 
497
                                        
 
498
                                case DECODE_STORED: 
 
499
                                {
 
500
                                        int more = outputWindow.CopyStored(input, uncomprLen);
 
501
                                        uncomprLen -= more;
 
502
                                        if (uncomprLen == 0) {
 
503
                                                mode = DECODE_BLOCKS;
 
504
                                                return true;
 
505
                                        }
 
506
                                        return !input.IsNeedingInput;
 
507
                                }
 
508
                                
 
509
                                case DECODE_DYN_HEADER:
 
510
                                        if (!dynHeader.Decode(input)) {
 
511
                                                return false;
 
512
                                        }
 
513
                                        
 
514
                                        litlenTree = dynHeader.BuildLitLenTree();
 
515
                                        distTree = dynHeader.BuildDistTree();
 
516
                                        mode = DECODE_HUFFMAN;
 
517
                                        goto case DECODE_HUFFMAN; /* fall through */
 
518
                                        
 
519
                                case DECODE_HUFFMAN:
 
520
                                case DECODE_HUFFMAN_LENBITS:
 
521
                                case DECODE_HUFFMAN_DIST:
 
522
                                case DECODE_HUFFMAN_DISTBITS:
 
523
                                        return DecodeHuffman();
 
524
                                
 
525
                                case FINISHED:
 
526
                                        return false;
 
527
                                
 
528
                                default:
 
529
                                        throw new SharpZipBaseException("Inflater.Decode unknown mode");
 
530
                        }
 
531
                }
 
532
                        
 
533
                /// <summary>
 
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.
 
538
                /// </summary>
 
539
                /// <param name="buffer">
 
540
                /// The dictionary.
 
541
                /// </param>
 
542
                public void SetDictionary(byte[] buffer)
 
543
                {
 
544
                        SetDictionary(buffer, 0, buffer.Length);
 
545
                }
 
546
                
 
547
                /// <summary>
 
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.
 
552
                /// </summary>
 
553
                /// <param name="buffer">
 
554
                /// The dictionary.
 
555
                /// </param>
 
556
                /// <param name="offset">
 
557
                /// The offset into buffer where the dictionary starts.
 
558
                /// </param>
 
559
                /// <param name="len">
 
560
                /// The length of the dictionary.
 
561
                /// </param>
 
562
                /// <exception cref="System.InvalidOperationException">
 
563
                /// No dictionary is needed.
 
564
                /// </exception>
 
565
                /// <exception cref="SharpZipBaseException">
 
566
                /// The adler checksum for the buffer is invalid
 
567
                /// </exception>
 
568
                public void SetDictionary(byte[] buffer, int offset, int len)
 
569
                {
 
570
                        if (!IsNeedingDictionary) {
 
571
                                throw new InvalidOperationException();
 
572
                        }
 
573
                        
 
574
                        adler.Update(buffer, offset, len);
 
575
                        if ((int)adler.Value != readAdler) {
 
576
                                throw new SharpZipBaseException("Wrong adler checksum");
 
577
                        }
 
578
                        adler.Reset();
 
579
                        outputWindow.CopyDict(buffer, offset, len);
 
580
                        mode = DECODE_BLOCKS;
 
581
                }
 
582
                
 
583
                /// <summary>
 
584
                /// Sets the input.  This should only be called, if needsInput()
 
585
                /// returns true.
 
586
                /// </summary>
 
587
                /// <param name="buf">
 
588
                /// the input.
 
589
                /// </param>
 
590
                public void SetInput(byte[] buf)
 
591
                {
 
592
                        SetInput(buf, 0, buf.Length);
 
593
                }
 
594
                
 
595
                /// <summary>
 
596
                /// Sets the input.  This should only be called, if needsInput()
 
597
                /// returns true.
 
598
                /// </summary>
 
599
                /// <param name="buffer">
 
600
                /// The source of input data
 
601
                /// </param>
 
602
                /// <param name="offset">
 
603
                /// The offset into buffer where the input starts.
 
604
                /// </param>
 
605
                /// <param name="length">
 
606
                /// The number of bytes of input to use.
 
607
                /// </param>
 
608
                /// <exception cref="System.InvalidOperationException">
 
609
                /// No input is needed.
 
610
                /// </exception>
 
611
                /// <exception cref="System.ArgumentOutOfRangeException">
 
612
                /// The off and/or len are wrong.
 
613
                /// </exception>
 
614
                public void SetInput(byte[] buffer, int offset, int length)
 
615
                {
 
616
                        input.SetInput(buffer, offset, length);
 
617
                        totalIn += length;
 
618
                }
 
619
                
 
620
                /// <summary>
 
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.
 
625
                /// </summary>
 
626
                /// <param name = "buf">
 
627
                /// the output buffer.
 
628
                /// </param>
 
629
                /// <returns>
 
630
                /// the number of bytes written to the buffer, 0 if no further
 
631
                /// output can be produced.
 
632
                /// </returns>
 
633
                /// <exception cref="System.ArgumentOutOfRangeException">
 
634
                /// if buf has length 0.
 
635
                /// </exception>
 
636
                /// <exception cref="System.FormatException">
 
637
                /// if deflated stream is invalid.
 
638
                /// </exception>
 
639
                public int Inflate(byte[] buf)
 
640
                {
 
641
                        return Inflate(buf, 0, buf.Length);
 
642
                }
 
643
                
 
644
                /// <summary>
 
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.
 
649
                /// </summary>
 
650
                /// <param name = "buf">
 
651
                /// the output buffer.
 
652
                /// </param>
 
653
                /// <param name = "offset">
 
654
                /// the offset into buffer where the output should start.
 
655
                /// </param>
 
656
                /// <param name = "len">
 
657
                /// the maximum length of the output.
 
658
                /// </param>
 
659
                /// <returns>
 
660
                /// the number of bytes written to the buffer, 0 if no further output can be produced.
 
661
                /// </returns>
 
662
                /// <exception cref="System.ArgumentOutOfRangeException">
 
663
                /// if len is &lt;= 0.
 
664
                /// </exception>
 
665
                /// <exception cref="System.ArgumentOutOfRangeException">
 
666
                /// if the offset and/or len are wrong.
 
667
                /// </exception>
 
668
                /// <exception cref="System.FormatException">
 
669
                /// if deflated stream is invalid.
 
670
                /// </exception>
 
671
                public int Inflate(byte[] buf, int offset, int len)
 
672
                {
 
673
                        if (len < 0) {
 
674
                                throw new ArgumentOutOfRangeException("len < 0");
 
675
                        }
 
676
                        
 
677
                        // Special case: len may be zero
 
678
                        if (len == 0) {
 
679
                                if (IsFinished == false) {// -jr- 08-Nov-2003 INFLATE_BUG fix..
 
680
                                        Decode();
 
681
                                }
 
682
                                return 0;
 
683
                        }
 
684
/*
 
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");
 
688
                        }
 
689
*/
 
690
                        int count = 0;
 
691
                        int more;
 
692
                        do {
 
693
                                if (mode != DECODE_CHKSUM) {
 
694
                                        /* Don't give away any output, if we are waiting for the
 
695
                                        * checksum in the input stream.
 
696
                                        *
 
697
                                        * With this trick we have always:
 
698
                                        *   needsInput() and not finished()
 
699
                                        *   implies more output can be produced.
 
700
                                        */
 
701
                                        more = outputWindow.CopyOutput(buf, offset, len);
 
702
                                        adler.Update(buf, offset, more);
 
703
                                        offset += more;
 
704
                                        count += more;
 
705
                                        totalOut += more;
 
706
                                        len -= more;
 
707
                                        if (len == 0) {
 
708
                                                return count;
 
709
                                        }
 
710
                                }
 
711
                        } while (Decode() || (outputWindow.GetAvailable() > 0 && mode != DECODE_CHKSUM));
 
712
                        return count;
 
713
                }
 
714
                
 
715
                /// <summary>
 
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.
 
719
                /// </summary>
 
720
                public bool IsNeedingInput {
 
721
                        get {
 
722
                                return input.IsNeedingInput;
 
723
                        }
 
724
                }
 
725
                
 
726
                /// <summary>
 
727
                /// Returns true, if a preset dictionary is needed to inflate the input.
 
728
                /// </summary>
 
729
                public bool IsNeedingDictionary {
 
730
                        get {
 
731
                                return mode == DECODE_DICT && neededBits == 0;
 
732
                        }
 
733
                }
 
734
                
 
735
                /// <summary>
 
736
                /// Returns true, if the inflater has finished.  This means, that no
 
737
                /// input is needed and no output can be produced.
 
738
                /// </summary>
 
739
                public bool IsFinished {
 
740
                        get {
 
741
                                return mode == FINISHED && outputWindow.GetAvailable() == 0;
 
742
                        }
 
743
                }
 
744
                
 
745
                /// <summary>
 
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.
 
750
                /// </summary>
 
751
                /// <returns>
 
752
                /// the adler checksum.
 
753
                /// </returns>
 
754
                public int Adler {
 
755
                        get {
 
756
                                return IsNeedingDictionary ? readAdler : (int) adler.Value;
 
757
                        }
 
758
                }
 
759
                
 
760
                /// <summary>
 
761
                /// Gets the total number of output bytes returned by inflate().
 
762
                /// </summary>
 
763
                /// <returns>
 
764
                /// the total number of output bytes.
 
765
                /// </returns>
 
766
                public int TotalOut {
 
767
                        get {
 
768
                                return totalOut;
 
769
                        }
 
770
                }
 
771
                
 
772
                /// <summary>
 
773
                /// Gets the total number of processed compressed input bytes.
 
774
                /// </summary>
 
775
                /// <returns>
 
776
                /// The total number of bytes of processed input bytes.
 
777
                /// </returns>
 
778
                public int TotalIn {
 
779
                        get {
 
780
                                return totalIn - RemainingInput;
 
781
                        }
 
782
                }
 
783
                
 
784
#if TEST_HAK            
 
785
                /// <summary>
 
786
                /// -jr test hak trying to figure out a bug
 
787
                ///</summary>
 
788
                public int UnseenInput {
 
789
                        get {
 
790
                                return totalIn - ((input.AvailableBits + 7) >> 3);
 
791
                        }
 
792
                }
 
793
                
 
794
                /// <summary>
 
795
                /// -jr test hak trying to figure out a bug
 
796
                ///</summary>
 
797
                public int PlainTotalIn {
 
798
                        get {
 
799
                                return totalIn;
 
800
                        }
 
801
                }
 
802
#endif
 
803
                
 
804
                /// <summary>
 
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.
 
808
                /// </summary>
 
809
                /// <returns>
 
810
                /// The number of bytes of the input which have not been processed.
 
811
                /// </returns>
 
812
                public int RemainingInput {
 
813
                        get {
 
814
                                return input.AvailableBytes;
 
815
                        }
 
816
                }
 
817
        }
 
818
}