Free cookie consent management tool by TermsFeed Policy Generator

source: trunk/sources/HeuristicLab.ExtLibs/HeuristicLab.EPPlus/4.0.3/EPPlus-4.0.3/Packaging/DotNetZip/Zlib/Inflate.cs @ 12074

Last change on this file since 12074 was 12074, checked in by sraggl, 9 years ago

#2341: Added EPPlus-4.0.3 to ExtLibs

File size: 72.8 KB
Line 
1// Inflate.cs
2// ------------------------------------------------------------------
3//
4// Copyright (c) 2009 Dino Chiesa and Microsoft Corporation.
5// All rights reserved.
6//
7// This code module is part of DotNetZip, a zipfile class library.
8//
9// ------------------------------------------------------------------
10//
11// This code is licensed under the Microsoft Public License.
12// See the file License.txt for the license details.
13// More info on: http://dotnetzip.codeplex.com
14//
15// ------------------------------------------------------------------
16//
17// last saved (in emacs):
18// Time-stamp: <2010-January-08 18:32:12>
19//
20// ------------------------------------------------------------------
21//
22// This module defines classes for decompression. This code is derived
23// from the jzlib implementation of zlib, but significantly modified.
24// The object model is not the same, and many of the behaviors are
25// different.  Nonetheless, in keeping with the license for jzlib, I am
26// reproducing the copyright to that code here.
27//
28// ------------------------------------------------------------------
29//
30// Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
31//
32// Redistribution and use in source and binary forms, with or without
33// modification, are permitted provided that the following conditions are met:
34//
35// 1. Redistributions of source code must retain the above copyright notice,
36// this list of conditions and the following disclaimer.
37//
38// 2. Redistributions in binary form must reproduce the above copyright
39// notice, this list of conditions and the following disclaimer in
40// the documentation and/or other materials provided with the distribution.
41//
42// 3. The names of the authors may not be used to endorse or promote products
43// derived from this software without specific prior written permission.
44//
45// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
46// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
47// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
48// INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
49// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
50// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
51// OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
52// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
53// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
54// EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55//
56// -----------------------------------------------------------------------
57//
58// This program is based on zlib-1.1.3; credit to authors
59// Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
60// and contributors of zlib.
61//
62// -----------------------------------------------------------------------
63
64
65using System;
66namespace OfficeOpenXml.Packaging.Ionic.Zlib
67{
68    sealed class InflateBlocks
69    {
70        private const int MANY = 1440;
71
72        // Table for deflate from PKZIP's appnote.txt.
73        internal static readonly int[] border = new int[]
74        { 16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15 };
75
76        private enum InflateBlockMode
77        {
78            TYPE   = 0,                     // get type bits (3, including end bit)
79            LENS   = 1,                     // get lengths for stored
80            STORED = 2,                     // processing stored block
81            TABLE  = 3,                     // get table lengths
82            BTREE  = 4,                     // get bit lengths tree for a dynamic block
83            DTREE  = 5,                     // get length, distance trees for a dynamic block
84            CODES  = 6,                     // processing fixed or dynamic block
85            DRY    = 7,                     // output remaining window bytes
86            DONE   = 8,                     // finished last block, done
87            BAD    = 9,                     // ot a data error--stuck here
88        }
89
90        private InflateBlockMode mode;                    // current inflate_block mode
91
92        internal int left;                                // if STORED, bytes left to copy
93
94        internal int table;                               // table lengths (14 bits)
95        internal int index;                               // index into blens (or border)
96        internal int[] blens;                             // bit lengths of codes
97        internal int[] bb = new int[1];                   // bit length tree depth
98        internal int[] tb = new int[1];                   // bit length decoding tree
99
100        internal InflateCodes codes = new InflateCodes(); // if CODES, current state
101
102        internal int last;                                // true if this block is the last block
103
104        internal ZlibCodec _codec;                        // pointer back to this zlib stream
105
106                                                          // mode independent information
107        internal int bitk;                                // bits in bit buffer
108        internal int bitb;                                // bit buffer
109        internal int[] hufts;                             // single malloc for tree space
110        internal byte[] window;                           // sliding window
111        internal int end;                                 // one byte after sliding window
112        internal int readAt;                              // window read pointer
113        internal int writeAt;                             // window write pointer
114        internal System.Object checkfn;                   // check function
115        internal uint check;                              // check on output
116
117        internal InfTree inftree = new InfTree();
118
119        internal InflateBlocks(ZlibCodec codec, System.Object checkfn, int w)
120        {
121            _codec = codec;
122            hufts = new int[MANY * 3];
123            window = new byte[w];
124            end = w;
125            this.checkfn = checkfn;
126            mode = InflateBlockMode.TYPE;
127            Reset();
128        }
129
130        internal uint Reset()
131        {
132            uint oldCheck = check;
133            mode = InflateBlockMode.TYPE;
134            bitk = 0;
135            bitb = 0;
136            readAt = writeAt = 0;
137
138            if (checkfn != null)
139                _codec._Adler32 = check = Adler.Adler32(0, null, 0, 0);
140            return oldCheck;
141        }
142
143
144        internal int Process(int r)
145        {
146            int t; // temporary storage
147            int b; // bit buffer
148            int k; // bits in bit buffer
149            int p; // input data pointer
150            int n; // bytes available there
151            int q; // output window write pointer
152            int m; // bytes to end of window or read pointer
153
154            // copy input/output information to locals (UPDATE macro restores)
155
156            p = _codec.NextIn;
157            n = _codec.AvailableBytesIn;
158            b = bitb;
159            k = bitk;
160
161            q = writeAt;
162            m = (int)(q < readAt ? readAt - q - 1 : end - q);
163
164
165            // process input based on current state
166            while (true)
167            {
168                switch (mode)
169                {
170                    case InflateBlockMode.TYPE:
171
172                        while (k < (3))
173                        {
174                            if (n != 0)
175                            {
176                                r = ZlibConstants.Z_OK;
177                            }
178                            else
179                            {
180                                bitb = b; bitk = k;
181                                _codec.AvailableBytesIn = n;
182                                _codec.TotalBytesIn += p - _codec.NextIn;
183                                _codec.NextIn = p;
184                                writeAt = q;
185                                return Flush(r);
186                            }
187
188                            n--;
189                            b |= (_codec.InputBuffer[p++] & 0xff) << k;
190                            k += 8;
191                        }
192                        t = (int)(b & 7);
193                        last = t & 1;
194
195                        switch ((uint)t >> 1)
196                        {
197                            case 0:  // stored
198                                b >>= 3; k -= (3);
199                                t = k & 7; // go to byte boundary
200                                b >>= t; k -= t;
201                                mode = InflateBlockMode.LENS; // get length of stored block
202                                break;
203
204                            case 1:  // fixed
205                                int[] bl = new int[1];
206                                int[] bd = new int[1];
207                                int[][] tl = new int[1][];
208                                int[][] td = new int[1][];
209                                InfTree.inflate_trees_fixed(bl, bd, tl, td, _codec);
210                                codes.Init(bl[0], bd[0], tl[0], 0, td[0], 0);
211                                b >>= 3; k -= 3;
212                                mode = InflateBlockMode.CODES;
213                                break;
214
215                            case 2:  // dynamic
216                                b >>= 3; k -= 3;
217                                mode = InflateBlockMode.TABLE;
218                                break;
219
220                            case 3:  // illegal
221                                b >>= 3; k -= 3;
222                                mode = InflateBlockMode.BAD;
223                                _codec.Message = "invalid block type";
224                                r = ZlibConstants.Z_DATA_ERROR;
225                                bitb = b; bitk = k;
226                                _codec.AvailableBytesIn = n;
227                                _codec.TotalBytesIn += p - _codec.NextIn;
228                                _codec.NextIn = p;
229                                writeAt = q;
230                                return Flush(r);
231                        }
232                        break;
233
234                    case InflateBlockMode.LENS:
235
236                        while (k < (32))
237                        {
238                            if (n != 0)
239                            {
240                                r = ZlibConstants.Z_OK;
241                            }
242                            else
243                            {
244                                bitb = b; bitk = k;
245                                _codec.AvailableBytesIn = n;
246                                _codec.TotalBytesIn += p - _codec.NextIn;
247                                _codec.NextIn = p;
248                                writeAt = q;
249                                return Flush(r);
250                            }
251                            ;
252                            n--;
253                            b |= (_codec.InputBuffer[p++] & 0xff) << k;
254                            k += 8;
255                        }
256
257                        if ( ( ((~b)>>16) & 0xffff) != (b & 0xffff))
258                        {
259                            mode = InflateBlockMode.BAD;
260                            _codec.Message = "invalid stored block lengths";
261                            r = ZlibConstants.Z_DATA_ERROR;
262
263                            bitb = b; bitk = k;
264                            _codec.AvailableBytesIn = n;
265                            _codec.TotalBytesIn += p - _codec.NextIn;
266                            _codec.NextIn = p;
267                            writeAt = q;
268                            return Flush(r);
269                        }
270                        left = (b & 0xffff);
271                        b = k = 0; // dump bits
272                        mode = left != 0 ? InflateBlockMode.STORED : (last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE);
273                        break;
274
275                    case InflateBlockMode.STORED:
276                        if (n == 0)
277                        {
278                            bitb = b; bitk = k;
279                            _codec.AvailableBytesIn = n;
280                            _codec.TotalBytesIn += p - _codec.NextIn;
281                            _codec.NextIn = p;
282                            writeAt = q;
283                            return Flush(r);
284                        }
285
286                        if (m == 0)
287                        {
288                            if (q == end && readAt != 0)
289                            {
290                                q = 0; m = (int)(q < readAt ? readAt - q - 1 : end - q);
291                            }
292                            if (m == 0)
293                            {
294                                writeAt = q;
295                                r = Flush(r);
296                                q = writeAt; m = (int)(q < readAt ? readAt - q - 1 : end - q);
297                                if (q == end && readAt != 0)
298                                {
299                                    q = 0; m = (int)(q < readAt ? readAt - q - 1 : end - q);
300                                }
301                                if (m == 0)
302                                {
303                                    bitb = b; bitk = k;
304                                    _codec.AvailableBytesIn = n;
305                                    _codec.TotalBytesIn += p - _codec.NextIn;
306                                    _codec.NextIn = p;
307                                    writeAt = q;
308                                    return Flush(r);
309                                }
310                            }
311                        }
312                        r = ZlibConstants.Z_OK;
313
314                        t = left;
315                        if (t > n)
316                            t = n;
317                        if (t > m)
318                            t = m;
319                        Array.Copy(_codec.InputBuffer, p, window, q, t);
320                        p += t; n -= t;
321                        q += t; m -= t;
322                        if ((left -= t) != 0)
323                            break;
324                        mode = last != 0 ? InflateBlockMode.DRY : InflateBlockMode.TYPE;
325                        break;
326
327                    case InflateBlockMode.TABLE:
328
329                        while (k < (14))
330                        {
331                            if (n != 0)
332                            {
333                                r = ZlibConstants.Z_OK;
334                            }
335                            else
336                            {
337                                bitb = b; bitk = k;
338                                _codec.AvailableBytesIn = n;
339                                _codec.TotalBytesIn += p - _codec.NextIn;
340                                _codec.NextIn = p;
341                                writeAt = q;
342                                return Flush(r);
343                            }
344
345                            n--;
346                            b |= (_codec.InputBuffer[p++] & 0xff) << k;
347                            k += 8;
348                        }
349
350                        table = t = (b & 0x3fff);
351                        if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
352                        {
353                            mode = InflateBlockMode.BAD;
354                            _codec.Message = "too many length or distance symbols";
355                            r = ZlibConstants.Z_DATA_ERROR;
356
357                            bitb = b; bitk = k;
358                            _codec.AvailableBytesIn = n;
359                            _codec.TotalBytesIn += p - _codec.NextIn;
360                            _codec.NextIn = p;
361                            writeAt = q;
362                            return Flush(r);
363                        }
364                        t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
365                        if (blens == null || blens.Length < t)
366                        {
367                            blens = new int[t];
368                        }
369                        else
370                        {
371                            Array.Clear(blens, 0, t);
372                            // for (int i = 0; i < t; i++)
373                            // {
374                            //     blens[i] = 0;
375                            // }
376                        }
377
378                        b >>= 14;
379                        k -= 14;
380
381
382                        index = 0;
383                        mode = InflateBlockMode.BTREE;
384                        goto case InflateBlockMode.BTREE;
385
386                    case InflateBlockMode.BTREE:
387                        while (index < 4 + (table >> 10))
388                        {
389                            while (k < (3))
390                            {
391                                if (n != 0)
392                                {
393                                    r = ZlibConstants.Z_OK;
394                                }
395                                else
396                                {
397                                    bitb = b; bitk = k;
398                                    _codec.AvailableBytesIn = n;
399                                    _codec.TotalBytesIn += p - _codec.NextIn;
400                                    _codec.NextIn = p;
401                                    writeAt = q;
402                                    return Flush(r);
403                                }
404
405                                n--;
406                                b |= (_codec.InputBuffer[p++] & 0xff) << k;
407                                k += 8;
408                            }
409
410                            blens[border[index++]] = b & 7;
411
412                            b >>= 3; k -= 3;
413                        }
414
415                        while (index < 19)
416                        {
417                            blens[border[index++]] = 0;
418                        }
419
420                        bb[0] = 7;
421                        t = inftree.inflate_trees_bits(blens, bb, tb, hufts, _codec);
422                        if (t != ZlibConstants.Z_OK)
423                        {
424                            r = t;
425                            if (r == ZlibConstants.Z_DATA_ERROR)
426                            {
427                                blens = null;
428                                mode = InflateBlockMode.BAD;
429                            }
430
431                            bitb = b; bitk = k;
432                            _codec.AvailableBytesIn = n;
433                            _codec.TotalBytesIn += p - _codec.NextIn;
434                            _codec.NextIn = p;
435                            writeAt = q;
436                            return Flush(r);
437                        }
438
439                        index = 0;
440                        mode = InflateBlockMode.DTREE;
441                        goto case InflateBlockMode.DTREE;
442
443                    case InflateBlockMode.DTREE:
444                        while (true)
445                        {
446                            t = table;
447                            if (!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f)))
448                            {
449                                break;
450                            }
451
452                            int i, j, c;
453
454                            t = bb[0];
455
456                            while (k < t)
457                            {
458                                if (n != 0)
459                                {
460                                    r = ZlibConstants.Z_OK;
461                                }
462                                else
463                                {
464                                    bitb = b; bitk = k;
465                                    _codec.AvailableBytesIn = n;
466                                    _codec.TotalBytesIn += p - _codec.NextIn;
467                                    _codec.NextIn = p;
468                                    writeAt = q;
469                                    return Flush(r);
470                                }
471
472                                n--;
473                                b |= (_codec.InputBuffer[p++] & 0xff) << k;
474                                k += 8;
475                            }
476
477                            t = hufts[(tb[0] + (b & InternalInflateConstants.InflateMask[t])) * 3 + 1];
478                            c = hufts[(tb[0] + (b & InternalInflateConstants.InflateMask[t])) * 3 + 2];
479
480                            if (c < 16)
481                            {
482                                b >>= t; k -= t;
483                                blens[index++] = c;
484                            }
485                            else
486                            {
487                                // c == 16..18
488                                i = c == 18 ? 7 : c - 14;
489                                j = c == 18 ? 11 : 3;
490
491                                while (k < (t + i))
492                                {
493                                    if (n != 0)
494                                    {
495                                        r = ZlibConstants.Z_OK;
496                                    }
497                                    else
498                                    {
499                                        bitb = b; bitk = k;
500                                        _codec.AvailableBytesIn = n;
501                                        _codec.TotalBytesIn += p - _codec.NextIn;
502                                        _codec.NextIn = p;
503                                        writeAt = q;
504                                        return Flush(r);
505                                    }
506
507                                    n--;
508                                    b |= (_codec.InputBuffer[p++] & 0xff) << k;
509                                    k += 8;
510                                }
511
512                                b >>= t; k -= t;
513
514                                j += (b & InternalInflateConstants.InflateMask[i]);
515
516                                b >>= i; k -= i;
517
518                                i = index;
519                                t = table;
520                                if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || (c == 16 && i < 1))
521                                {
522                                    blens = null;
523                                    mode = InflateBlockMode.BAD;
524                                    _codec.Message = "invalid bit length repeat";
525                                    r = ZlibConstants.Z_DATA_ERROR;
526
527                                    bitb = b; bitk = k;
528                                    _codec.AvailableBytesIn = n;
529                                    _codec.TotalBytesIn += p - _codec.NextIn;
530                                    _codec.NextIn = p;
531                                    writeAt = q;
532                                    return Flush(r);
533                                }
534
535                                c = (c == 16) ? blens[i-1] : 0;
536                                do
537                                {
538                                    blens[i++] = c;
539                                }
540                                while (--j != 0);
541                                index = i;
542                            }
543                        }
544
545                        tb[0] = -1;
546                        {
547                            int[] bl = new int[] { 9 };  // must be <= 9 for lookahead assumptions
548                            int[] bd = new int[] { 6 }; // must be <= 9 for lookahead assumptions
549                            int[] tl = new int[1];
550                            int[] td = new int[1];
551
552                            t = table;
553                            t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), blens, bl, bd, tl, td, hufts, _codec);
554
555                            if (t != ZlibConstants.Z_OK)
556                            {
557                                if (t == ZlibConstants.Z_DATA_ERROR)
558                                {
559                                    blens = null;
560                                    mode = InflateBlockMode.BAD;
561                                }
562                                r = t;
563
564                                bitb = b; bitk = k;
565                                _codec.AvailableBytesIn = n;
566                                _codec.TotalBytesIn += p - _codec.NextIn;
567                                _codec.NextIn = p;
568                                writeAt = q;
569                                return Flush(r);
570                            }
571                            codes.Init(bl[0], bd[0], hufts, tl[0], hufts, td[0]);
572                        }
573                        mode = InflateBlockMode.CODES;
574                        goto case InflateBlockMode.CODES;
575
576                    case InflateBlockMode.CODES:
577                        bitb = b; bitk = k;
578                        _codec.AvailableBytesIn = n;
579                        _codec.TotalBytesIn += p - _codec.NextIn;
580                        _codec.NextIn = p;
581                        writeAt = q;
582
583                        r = codes.Process(this, r);
584                        if (r != ZlibConstants.Z_STREAM_END)
585                        {
586                            return Flush(r);
587                        }
588
589                        r = ZlibConstants.Z_OK;
590                        p = _codec.NextIn;
591                        n = _codec.AvailableBytesIn;
592                        b = bitb;
593                        k = bitk;
594                        q = writeAt;
595                        m = (int)(q < readAt ? readAt - q - 1 : end - q);
596
597                        if (last == 0)
598                        {
599                            mode = InflateBlockMode.TYPE;
600                            break;
601                        }
602                        mode = InflateBlockMode.DRY;
603                        goto case InflateBlockMode.DRY;
604
605                    case InflateBlockMode.DRY:
606                        writeAt = q;
607                        r = Flush(r);
608                        q = writeAt; m = (int)(q < readAt ? readAt - q - 1 : end - q);
609                        if (readAt != writeAt)
610                        {
611                            bitb = b; bitk = k;
612                            _codec.AvailableBytesIn = n;
613                            _codec.TotalBytesIn += p - _codec.NextIn;
614                            _codec.NextIn = p;
615                            writeAt = q;
616                            return Flush(r);
617                        }
618                        mode = InflateBlockMode.DONE;
619                        goto case InflateBlockMode.DONE;
620
621                    case InflateBlockMode.DONE:
622                        r = ZlibConstants.Z_STREAM_END;
623                        bitb = b;
624                        bitk = k;
625                        _codec.AvailableBytesIn = n;
626                        _codec.TotalBytesIn += p - _codec.NextIn;
627                        _codec.NextIn = p;
628                        writeAt = q;
629                        return Flush(r);
630
631                    case InflateBlockMode.BAD:
632                        r = ZlibConstants.Z_DATA_ERROR;
633
634                        bitb = b; bitk = k;
635                        _codec.AvailableBytesIn = n;
636                        _codec.TotalBytesIn += p - _codec.NextIn;
637                        _codec.NextIn = p;
638                        writeAt = q;
639                        return Flush(r);
640
641
642                    default:
643                        r = ZlibConstants.Z_STREAM_ERROR;
644
645                        bitb = b; bitk = k;
646                        _codec.AvailableBytesIn = n;
647                        _codec.TotalBytesIn += p - _codec.NextIn;
648                        _codec.NextIn = p;
649                        writeAt = q;
650                        return Flush(r);
651                }
652            }
653        }
654
655
656        internal void Free()
657        {
658            Reset();
659            window = null;
660            hufts = null;
661        }
662
663        internal void SetDictionary(byte[] d, int start, int n)
664        {
665            Array.Copy(d, start, window, 0, n);
666            readAt = writeAt = n;
667        }
668
669        // Returns true if inflate is currently at the end of a block generated
670        // by Z_SYNC_FLUSH or Z_FULL_FLUSH.
671        internal int SyncPoint()
672        {
673            return mode == InflateBlockMode.LENS ? 1 : 0;
674        }
675
676        // copy as much as possible from the sliding window to the output area
677        internal int Flush(int r)
678        {
679            int nBytes;
680
681            for (int pass=0; pass < 2; pass++)
682            {
683                if (pass==0)
684                {
685                    // compute number of bytes to copy as far as end of window
686                    nBytes = (int)((readAt <= writeAt ? writeAt : end) - readAt);
687                }
688                else
689                {
690                    // compute bytes to copy
691                    nBytes = writeAt - readAt;
692                }
693
694                // workitem 8870
695                if (nBytes == 0)
696                {
697                    if (r == ZlibConstants.Z_BUF_ERROR)
698                        r = ZlibConstants.Z_OK;
699                    return r;
700                }
701
702                if (nBytes > _codec.AvailableBytesOut)
703                    nBytes = _codec.AvailableBytesOut;
704
705                if (nBytes != 0 && r == ZlibConstants.Z_BUF_ERROR)
706                    r = ZlibConstants.Z_OK;
707
708                // update counters
709                _codec.AvailableBytesOut -= nBytes;
710                _codec.TotalBytesOut += nBytes;
711
712                // update check information
713                if (checkfn != null)
714                    _codec._Adler32 = check = Adler.Adler32(check, window, readAt, nBytes);
715
716                // copy as far as end of window
717                Array.Copy(window, readAt, _codec.OutputBuffer, _codec.NextOut, nBytes);
718                _codec.NextOut += nBytes;
719                readAt += nBytes;
720
721                // see if more to copy at beginning of window
722                if (readAt == end && pass == 0)
723                {
724                    // wrap pointers
725                    readAt = 0;
726                    if (writeAt == end)
727                        writeAt = 0;
728                }
729                else pass++;
730            }
731
732            // done
733            return r;
734        }
735    }
736
737
738    internal static class InternalInflateConstants
739    {
740        // And'ing with mask[n] masks the lower n bits
741        internal static readonly int[] InflateMask = new int[] {
742            0x00000000, 0x00000001, 0x00000003, 0x00000007,
743            0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
744            0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
745            0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff };
746    }
747
748
749    sealed class InflateCodes
750    {
751        // waiting for "i:"=input,
752        //             "o:"=output,
753        //             "x:"=nothing
754        private const int START   = 0; // x: set up for LEN
755        private const int LEN     = 1; // i: get length/literal/eob next
756        private const int LENEXT  = 2; // i: getting length extra (have base)
757        private const int DIST    = 3; // i: get distance next
758        private const int DISTEXT = 4; // i: getting distance extra
759        private const int COPY    = 5; // o: copying bytes in window, waiting for space
760        private const int LIT     = 6; // o: got literal, waiting for output space
761        private const int WASH    = 7; // o: got eob, possibly still output waiting
762        private const int END     = 8; // x: got eob and all data flushed
763        private const int BADCODE = 9; // x: got error
764
765        internal int mode;        // current inflate_codes mode
766
767        // mode dependent information
768        internal int len;
769
770        internal int[] tree;      // pointer into tree
771        internal int tree_index = 0;
772        internal int need;        // bits needed
773
774        internal int lit;
775
776        // if EXT or COPY, where and how much
777        internal int bitsToGet;   // bits to get for extra
778        internal int dist;        // distance back to copy from
779
780        internal byte lbits;      // ltree bits decoded per branch
781        internal byte dbits;      // dtree bits decoder per branch
782        internal int[] ltree;     // literal/length/eob tree
783        internal int ltree_index; // literal/length/eob tree
784        internal int[] dtree;     // distance tree
785        internal int dtree_index; // distance tree
786
787        internal InflateCodes()
788        {
789        }
790
791        internal void Init(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index)
792        {
793            mode = START;
794            lbits = (byte)bl;
795            dbits = (byte)bd;
796            ltree = tl;
797            ltree_index = tl_index;
798            dtree = td;
799            dtree_index = td_index;
800            tree = null;
801        }
802
803        internal int Process(InflateBlocks blocks, int r)
804        {
805            int j;      // temporary storage
806            int tindex; // temporary pointer
807            int e;      // extra bits or operation
808            int b = 0;  // bit buffer
809            int k = 0;  // bits in bit buffer
810            int p = 0;  // input data pointer
811            int n;      // bytes available there
812            int q;      // output window write pointer
813            int m;      // bytes to end of window or read pointer
814            int f;      // pointer to copy strings from
815
816            ZlibCodec z = blocks._codec;
817
818            // copy input/output information to locals (UPDATE macro restores)
819            p = z.NextIn;
820            n = z.AvailableBytesIn;
821            b = blocks.bitb;
822            k = blocks.bitk;
823            q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q;
824
825            // process input and output based on current state
826            while (true)
827            {
828                switch (mode)
829                {
830                    // waiting for "i:"=input, "o:"=output, "x:"=nothing
831                    case START:  // x: set up for LEN
832                        if (m >= 258 && n >= 10)
833                        {
834                            blocks.bitb = b; blocks.bitk = k;
835                            z.AvailableBytesIn = n;
836                            z.TotalBytesIn += p - z.NextIn;
837                            z.NextIn = p;
838                            blocks.writeAt = q;
839                            r = InflateFast(lbits, dbits, ltree, ltree_index, dtree, dtree_index, blocks, z);
840
841                            p = z.NextIn;
842                            n = z.AvailableBytesIn;
843                            b = blocks.bitb;
844                            k = blocks.bitk;
845                            q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q;
846
847                            if (r != ZlibConstants.Z_OK)
848                            {
849                                mode = (r == ZlibConstants.Z_STREAM_END) ? WASH : BADCODE;
850                                break;
851                            }
852                        }
853                        need = lbits;
854                        tree = ltree;
855                        tree_index = ltree_index;
856
857                        mode = LEN;
858                        goto case LEN;
859
860                    case LEN:  // i: get length/literal/eob next
861                        j = need;
862
863                        while (k < j)
864                        {
865                            if (n != 0)
866                                r = ZlibConstants.Z_OK;
867                            else
868                            {
869                                blocks.bitb = b; blocks.bitk = k;
870                                z.AvailableBytesIn = n;
871                                z.TotalBytesIn += p - z.NextIn;
872                                z.NextIn = p;
873                                blocks.writeAt = q;
874                                return blocks.Flush(r);
875                            }
876                            n--;
877                            b |= (z.InputBuffer[p++] & 0xff) << k;
878                            k += 8;
879                        }
880
881                        tindex = (tree_index + (b & InternalInflateConstants.InflateMask[j])) * 3;
882
883                        b >>= (tree[tindex + 1]);
884                        k -= (tree[tindex + 1]);
885
886                        e = tree[tindex];
887
888                        if (e == 0)
889                        {
890                            // literal
891                            lit = tree[tindex + 2];
892                            mode = LIT;
893                            break;
894                        }
895                        if ((e & 16) != 0)
896                        {
897                            // length
898                            bitsToGet = e & 15;
899                            len = tree[tindex + 2];
900                            mode = LENEXT;
901                            break;
902                        }
903                        if ((e & 64) == 0)
904                        {
905                            // next table
906                            need = e;
907                            tree_index = tindex / 3 + tree[tindex + 2];
908                            break;
909                        }
910                        if ((e & 32) != 0)
911                        {
912                            // end of block
913                            mode = WASH;
914                            break;
915                        }
916                        mode = BADCODE; // invalid code
917                        z.Message = "invalid literal/length code";
918                        r = ZlibConstants.Z_DATA_ERROR;
919
920                        blocks.bitb = b; blocks.bitk = k;
921                        z.AvailableBytesIn = n;
922                        z.TotalBytesIn += p - z.NextIn;
923                        z.NextIn = p;
924                        blocks.writeAt = q;
925                        return blocks.Flush(r);
926
927
928                    case LENEXT:  // i: getting length extra (have base)
929                        j = bitsToGet;
930
931                        while (k < j)
932                        {
933                            if (n != 0)
934                                r = ZlibConstants.Z_OK;
935                            else
936                            {
937                                blocks.bitb = b; blocks.bitk = k;
938                                z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p;
939                                blocks.writeAt = q;
940                                return blocks.Flush(r);
941                            }
942                            n--; b |= (z.InputBuffer[p++] & 0xff) << k;
943                            k += 8;
944                        }
945
946                        len += (b & InternalInflateConstants.InflateMask[j]);
947
948                        b >>= j;
949                        k -= j;
950
951                        need = dbits;
952                        tree = dtree;
953                        tree_index = dtree_index;
954                        mode = DIST;
955                        goto case DIST;
956
957                    case DIST:  // i: get distance next
958                        j = need;
959
960                        while (k < j)
961                        {
962                            if (n != 0)
963                                r = ZlibConstants.Z_OK;
964                            else
965                            {
966                                blocks.bitb = b; blocks.bitk = k;
967                                z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p;
968                                blocks.writeAt = q;
969                                return blocks.Flush(r);
970                            }
971                            n--; b |= (z.InputBuffer[p++] & 0xff) << k;
972                            k += 8;
973                        }
974
975                        tindex = (tree_index + (b & InternalInflateConstants.InflateMask[j])) * 3;
976
977                        b >>= tree[tindex + 1];
978                        k -= tree[tindex + 1];
979
980                        e = (tree[tindex]);
981                        if ((e & 0x10) != 0)
982                        {
983                            // distance
984                            bitsToGet = e & 15;
985                            dist = tree[tindex + 2];
986                            mode = DISTEXT;
987                            break;
988                        }
989                        if ((e & 64) == 0)
990                        {
991                            // next table
992                            need = e;
993                            tree_index = tindex / 3 + tree[tindex + 2];
994                            break;
995                        }
996                        mode = BADCODE; // invalid code
997                        z.Message = "invalid distance code";
998                        r = ZlibConstants.Z_DATA_ERROR;
999
1000                        blocks.bitb = b; blocks.bitk = k;
1001                        z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p;
1002                        blocks.writeAt = q;
1003                        return blocks.Flush(r);
1004
1005
1006                    case DISTEXT:  // i: getting distance extra
1007                        j = bitsToGet;
1008
1009                        while (k < j)
1010                        {
1011                            if (n != 0)
1012                                r = ZlibConstants.Z_OK;
1013                            else
1014                            {
1015                                blocks.bitb = b; blocks.bitk = k;
1016                                z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p;
1017                                blocks.writeAt = q;
1018                                return blocks.Flush(r);
1019                            }
1020                            n--; b |= (z.InputBuffer[p++] & 0xff) << k;
1021                            k += 8;
1022                        }
1023
1024                        dist += (b & InternalInflateConstants.InflateMask[j]);
1025
1026                        b >>= j;
1027                        k -= j;
1028
1029                        mode = COPY;
1030                        goto case COPY;
1031
1032                    case COPY:  // o: copying bytes in window, waiting for space
1033                        f = q - dist;
1034                        while (f < 0)
1035                        {
1036                            // modulo window size-"while" instead
1037                            f += blocks.end; // of "if" handles invalid distances
1038                        }
1039                        while (len != 0)
1040                        {
1041                            if (m == 0)
1042                            {
1043                                if (q == blocks.end && blocks.readAt != 0)
1044                                {
1045                                    q = 0; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q;
1046                                }
1047                                if (m == 0)
1048                                {
1049                                    blocks.writeAt = q; r = blocks.Flush(r);
1050                                    q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q;
1051
1052                                    if (q == blocks.end && blocks.readAt != 0)
1053                                    {
1054                                        q = 0; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q;
1055                                    }
1056
1057                                    if (m == 0)
1058                                    {
1059                                        blocks.bitb = b; blocks.bitk = k;
1060                                        z.AvailableBytesIn = n;
1061                                        z.TotalBytesIn += p - z.NextIn;
1062                                        z.NextIn = p;
1063                                        blocks.writeAt = q;
1064                                        return blocks.Flush(r);
1065                                    }
1066                                }
1067                            }
1068
1069                            blocks.window[q++] = blocks.window[f++]; m--;
1070
1071                            if (f == blocks.end)
1072                                f = 0;
1073                            len--;
1074                        }
1075                        mode = START;
1076                        break;
1077
1078                    case LIT:  // o: got literal, waiting for output space
1079                        if (m == 0)
1080                        {
1081                            if (q == blocks.end && blocks.readAt != 0)
1082                            {
1083                                q = 0; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q;
1084                            }
1085                            if (m == 0)
1086                            {
1087                                blocks.writeAt = q; r = blocks.Flush(r);
1088                                q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q;
1089
1090                                if (q == blocks.end && blocks.readAt != 0)
1091                                {
1092                                    q = 0; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q;
1093                                }
1094                                if (m == 0)
1095                                {
1096                                    blocks.bitb = b; blocks.bitk = k;
1097                                    z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p;
1098                                    blocks.writeAt = q;
1099                                    return blocks.Flush(r);
1100                                }
1101                            }
1102                        }
1103                        r = ZlibConstants.Z_OK;
1104
1105                        blocks.window[q++] = (byte)lit; m--;
1106
1107                        mode = START;
1108                        break;
1109
1110                    case WASH:  // o: got eob, possibly more output
1111                        if (k > 7)
1112                        {
1113                            // return unused byte, if any
1114                            k -= 8;
1115                            n++;
1116                            p--; // can always return one
1117                        }
1118
1119                        blocks.writeAt = q; r = blocks.Flush(r);
1120                        q = blocks.writeAt; m = q < blocks.readAt ? blocks.readAt - q - 1 : blocks.end - q;
1121
1122                        if (blocks.readAt != blocks.writeAt)
1123                        {
1124                            blocks.bitb = b; blocks.bitk = k;
1125                            z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p;
1126                            blocks.writeAt = q;
1127                            return blocks.Flush(r);
1128                        }
1129                        mode = END;
1130                        goto case END;
1131
1132                    case END:
1133                        r = ZlibConstants.Z_STREAM_END;
1134                        blocks.bitb = b; blocks.bitk = k;
1135                        z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p;
1136                        blocks.writeAt = q;
1137                        return blocks.Flush(r);
1138
1139                    case BADCODE:  // x: got error
1140
1141                        r = ZlibConstants.Z_DATA_ERROR;
1142
1143                        blocks.bitb = b; blocks.bitk = k;
1144                        z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p;
1145                        blocks.writeAt = q;
1146                        return blocks.Flush(r);
1147
1148                    default:
1149                        r = ZlibConstants.Z_STREAM_ERROR;
1150
1151                        blocks.bitb = b; blocks.bitk = k;
1152                        z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p;
1153                        blocks.writeAt = q;
1154                        return blocks.Flush(r);
1155                }
1156            }
1157        }
1158
1159
1160        // Called with number of bytes left to write in window at least 258
1161        // (the maximum string length) and number of input bytes available
1162        // at least ten.  The ten bytes are six bytes for the longest length/
1163        // distance pair plus four bytes for overloading the bit buffer.
1164
1165        internal int InflateFast(int bl, int bd, int[] tl, int tl_index, int[] td, int td_index, InflateBlocks s, ZlibCodec z)
1166        {
1167            int t;        // temporary pointer
1168            int[] tp;     // temporary pointer
1169            int tp_index; // temporary pointer
1170            int e;        // extra bits or operation
1171            int b;        // bit buffer
1172            int k;        // bits in bit buffer
1173            int p;        // input data pointer
1174            int n;        // bytes available there
1175            int q;        // output window write pointer
1176            int m;        // bytes to end of window or read pointer
1177            int ml;       // mask for literal/length tree
1178            int md;       // mask for distance tree
1179            int c;        // bytes to copy
1180            int d;        // distance back to copy from
1181            int r;        // copy source pointer
1182
1183            int tp_index_t_3; // (tp_index+t)*3
1184
1185            // load input, output, bit values
1186            p = z.NextIn; n = z.AvailableBytesIn; b = s.bitb; k = s.bitk;
1187            q = s.writeAt; m = q < s.readAt ? s.readAt - q - 1 : s.end - q;
1188
1189            // initialize masks
1190            ml = InternalInflateConstants.InflateMask[bl];
1191            md = InternalInflateConstants.InflateMask[bd];
1192
1193            // do until not enough input or output space for fast loop
1194            do
1195            {
1196                // assume called with m >= 258 && n >= 10
1197                // get literal/length code
1198                while (k < (20))
1199                {
1200                    // max bits for literal/length code
1201                    n--;
1202                    b |= (z.InputBuffer[p++] & 0xff) << k; k += 8;
1203                }
1204
1205                t = b & ml;
1206                tp = tl;
1207                tp_index = tl_index;
1208                tp_index_t_3 = (tp_index + t) * 3;
1209                if ((e = tp[tp_index_t_3]) == 0)
1210                {
1211                    b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
1212
1213                    s.window[q++] = (byte)tp[tp_index_t_3 + 2];
1214                    m--;
1215                    continue;
1216                }
1217                do
1218                {
1219
1220                    b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
1221
1222                    if ((e & 16) != 0)
1223                    {
1224                        e &= 15;
1225                        c = tp[tp_index_t_3 + 2] + ((int)b & InternalInflateConstants.InflateMask[e]);
1226
1227                        b >>= e; k -= e;
1228
1229                        // decode distance base of block to copy
1230                        while (k < 15)
1231                        {
1232                            // max bits for distance code
1233                            n--;
1234                            b |= (z.InputBuffer[p++] & 0xff) << k; k += 8;
1235                        }
1236
1237                        t = b & md;
1238                        tp = td;
1239                        tp_index = td_index;
1240                        tp_index_t_3 = (tp_index + t) * 3;
1241                        e = tp[tp_index_t_3];
1242
1243                        do
1244                        {
1245
1246                            b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
1247
1248                            if ((e & 16) != 0)
1249                            {
1250                                // get extra bits to add to distance base
1251                                e &= 15;
1252                                while (k < e)
1253                                {
1254                                    // get extra bits (up to 13)
1255                                    n--;
1256                                    b |= (z.InputBuffer[p++] & 0xff) << k; k += 8;
1257                                }
1258
1259                                d = tp[tp_index_t_3 + 2] + (b & InternalInflateConstants.InflateMask[e]);
1260
1261                                b >>= e; k -= e;
1262
1263                                // do the copy
1264                                m -= c;
1265                                if (q >= d)
1266                                {
1267                                    // offset before dest
1268                                    //  just copy
1269                                    r = q - d;
1270                                    if (q - r > 0 && 2 > (q - r))
1271                                    {
1272                                        s.window[q++] = s.window[r++]; // minimum count is three,
1273                                        s.window[q++] = s.window[r++]; // so unroll loop a little
1274                                        c -= 2;
1275                                    }
1276                                    else
1277                                    {
1278                                        Array.Copy(s.window, r, s.window, q, 2);
1279                                        q += 2; r += 2; c -= 2;
1280                                    }
1281                                }
1282                                else
1283                                {
1284                                    // else offset after destination
1285                                    r = q - d;
1286                                    do
1287                                    {
1288                                        r += s.end; // force pointer in window
1289                                    }
1290                                    while (r < 0); // covers invalid distances
1291                                    e = s.end - r;
1292                                    if (c > e)
1293                                    {
1294                                        // if source crosses,
1295                                        c -= e; // wrapped copy
1296                                        if (q - r > 0 && e > (q - r))
1297                                        {
1298                                            do
1299                                            {
1300                                                s.window[q++] = s.window[r++];
1301                                            }
1302                                            while (--e != 0);
1303                                        }
1304                                        else
1305                                        {
1306                                            Array.Copy(s.window, r, s.window, q, e);
1307                                            q += e; r += e; e = 0;
1308                                        }
1309                                        r = 0; // copy rest from start of window
1310                                    }
1311                                }
1312
1313                                // copy all or what's left
1314                                if (q - r > 0 && c > (q - r))
1315                                {
1316                                    do
1317                                    {
1318                                        s.window[q++] = s.window[r++];
1319                                    }
1320                                    while (--c != 0);
1321                                }
1322                                else
1323                                {
1324                                    Array.Copy(s.window, r, s.window, q, c);
1325                                    q += c; r += c; c = 0;
1326                                }
1327                                break;
1328                            }
1329                            else if ((e & 64) == 0)
1330                            {
1331                                t += tp[tp_index_t_3 + 2];
1332                                t += (b & InternalInflateConstants.InflateMask[e]);
1333                                tp_index_t_3 = (tp_index + t) * 3;
1334                                e = tp[tp_index_t_3];
1335                            }
1336                            else
1337                            {
1338                                z.Message = "invalid distance code";
1339
1340                                c = z.AvailableBytesIn - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= (c << 3);
1341
1342                                s.bitb = b; s.bitk = k;
1343                                z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p;
1344                                s.writeAt = q;
1345
1346                                return ZlibConstants.Z_DATA_ERROR;
1347                            }
1348                        }
1349                        while (true);
1350                        break;
1351                    }
1352
1353                    if ((e & 64) == 0)
1354                    {
1355                        t += tp[tp_index_t_3 + 2];
1356                        t += (b & InternalInflateConstants.InflateMask[e]);
1357                        tp_index_t_3 = (tp_index + t) * 3;
1358                        if ((e = tp[tp_index_t_3]) == 0)
1359                        {
1360                            b >>= (tp[tp_index_t_3 + 1]); k -= (tp[tp_index_t_3 + 1]);
1361                            s.window[q++] = (byte)tp[tp_index_t_3 + 2];
1362                            m--;
1363                            break;
1364                        }
1365                    }
1366                    else if ((e & 32) != 0)
1367                    {
1368                        c = z.AvailableBytesIn - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= (c << 3);
1369
1370                        s.bitb = b; s.bitk = k;
1371                        z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p;
1372                        s.writeAt = q;
1373
1374                        return ZlibConstants.Z_STREAM_END;
1375                    }
1376                    else
1377                    {
1378                        z.Message = "invalid literal/length code";
1379
1380                        c = z.AvailableBytesIn - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= (c << 3);
1381
1382                        s.bitb = b; s.bitk = k;
1383                        z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p;
1384                        s.writeAt = q;
1385
1386                        return ZlibConstants.Z_DATA_ERROR;
1387                    }
1388                }
1389                while (true);
1390            }
1391            while (m >= 258 && n >= 10);
1392
1393            // not enough input or output--restore pointers and return
1394            c = z.AvailableBytesIn - n; c = (k >> 3) < c ? k >> 3 : c; n += c; p -= c; k -= (c << 3);
1395
1396            s.bitb = b; s.bitk = k;
1397            z.AvailableBytesIn = n; z.TotalBytesIn += p - z.NextIn; z.NextIn = p;
1398            s.writeAt = q;
1399
1400            return ZlibConstants.Z_OK;
1401        }
1402    }
1403
1404
1405    internal sealed class InflateManager
1406    {
1407        // preset dictionary flag in zlib header
1408        private const int PRESET_DICT = 0x20;
1409
1410        private const int Z_DEFLATED = 8;
1411
1412        private enum InflateManagerMode
1413        {
1414            METHOD = 0,  // waiting for method byte
1415            FLAG   = 1,  // waiting for flag byte
1416            DICT4  = 2,  // four dictionary check bytes to go
1417            DICT3  = 3,  // three dictionary check bytes to go
1418            DICT2  = 4,  // two dictionary check bytes to go
1419            DICT1  = 5,  // one dictionary check byte to go
1420            DICT0  = 6,  // waiting for inflateSetDictionary
1421            BLOCKS = 7,  // decompressing blocks
1422            CHECK4 = 8,  // four check bytes to go
1423            CHECK3 = 9,  // three check bytes to go
1424            CHECK2 = 10, // two check bytes to go
1425            CHECK1 = 11, // one check byte to go
1426            DONE   = 12, // finished check, done
1427            BAD    = 13, // got an error--stay here
1428        }
1429
1430        private InflateManagerMode mode; // current inflate mode
1431        internal ZlibCodec _codec; // pointer back to this zlib stream
1432
1433        // mode dependent information
1434        internal int method; // if FLAGS, method byte
1435
1436        // if CHECK, check values to compare
1437        internal uint computedCheck; // computed check value
1438        internal uint expectedCheck; // stream check value
1439
1440        // if BAD, inflateSync's marker bytes count
1441        internal int marker;
1442
1443        // mode independent information
1444        //internal int nowrap; // flag for no wrapper
1445        private bool _handleRfc1950HeaderBytes = true;
1446        internal bool HandleRfc1950HeaderBytes
1447        {
1448            get { return _handleRfc1950HeaderBytes; }
1449            set { _handleRfc1950HeaderBytes = value; }
1450        }
1451        internal int wbits; // log2(window size)  (8..15, defaults to 15)
1452
1453        internal InflateBlocks blocks; // current inflate_blocks state
1454
1455        public InflateManager() { }
1456
1457        public InflateManager(bool expectRfc1950HeaderBytes)
1458        {
1459            _handleRfc1950HeaderBytes = expectRfc1950HeaderBytes;
1460        }
1461
1462        internal int Reset()
1463        {
1464            _codec.TotalBytesIn = _codec.TotalBytesOut = 0;
1465            _codec.Message = null;
1466            mode = HandleRfc1950HeaderBytes ? InflateManagerMode.METHOD : InflateManagerMode.BLOCKS;
1467            blocks.Reset();
1468            return ZlibConstants.Z_OK;
1469        }
1470
1471        internal int End()
1472        {
1473            if (blocks != null)
1474                blocks.Free();
1475            blocks = null;
1476            return ZlibConstants.Z_OK;
1477        }
1478
1479        internal int Initialize(ZlibCodec codec, int w)
1480        {
1481            _codec = codec;
1482            _codec.Message = null;
1483            blocks = null;
1484
1485            // handle undocumented nowrap option (no zlib header or check)
1486            //nowrap = 0;
1487            //if (w < 0)
1488            //{
1489            //    w = - w;
1490            //    nowrap = 1;
1491            //}
1492
1493            // set window size
1494            if (w < 8 || w > 15)
1495            {
1496                End();
1497                throw new ZlibException("Bad window size.");
1498
1499                //return ZlibConstants.Z_STREAM_ERROR;
1500            }
1501            wbits = w;
1502
1503            blocks = new InflateBlocks(codec,
1504                HandleRfc1950HeaderBytes ? this : null,
1505                1 << w);
1506
1507            // reset state
1508            Reset();
1509            return ZlibConstants.Z_OK;
1510        }
1511
1512
1513        internal int Inflate(FlushType flush)
1514        {
1515            int b;
1516
1517            if (_codec.InputBuffer == null)
1518                throw new ZlibException("InputBuffer is null. ");
1519
1520//             int f = (flush == FlushType.Finish)
1521//                 ? ZlibConstants.Z_BUF_ERROR
1522//                 : ZlibConstants.Z_OK;
1523
1524            // workitem 8870
1525            int f = ZlibConstants.Z_OK;
1526            int r = ZlibConstants.Z_BUF_ERROR;
1527
1528            while (true)
1529            {
1530                switch (mode)
1531                {
1532                    case InflateManagerMode.METHOD:
1533                        if (_codec.AvailableBytesIn == 0) return r;
1534                        r = f;
1535                        _codec.AvailableBytesIn--;
1536                        _codec.TotalBytesIn++;
1537                        if (((method = _codec.InputBuffer[_codec.NextIn++]) & 0xf) != Z_DEFLATED)
1538                        {
1539                            mode = InflateManagerMode.BAD;
1540                            _codec.Message = String.Format("unknown compression method (0x{0:X2})", method);
1541                            marker = 5; // can't try inflateSync
1542                            break;
1543                        }
1544                        if ((method >> 4) + 8 > wbits)
1545                        {
1546                            mode = InflateManagerMode.BAD;
1547                            _codec.Message = String.Format("invalid window size ({0})", (method >> 4) + 8);
1548                            marker = 5; // can't try inflateSync
1549                            break;
1550                        }
1551                        mode = InflateManagerMode.FLAG;
1552                        break;
1553
1554
1555                    case InflateManagerMode.FLAG:
1556                        if (_codec.AvailableBytesIn == 0) return r;
1557                        r = f;
1558                        _codec.AvailableBytesIn--;
1559                        _codec.TotalBytesIn++;
1560                        b = (_codec.InputBuffer[_codec.NextIn++]) & 0xff;
1561
1562                        if ((((method << 8) + b) % 31) != 0)
1563                        {
1564                            mode = InflateManagerMode.BAD;
1565                            _codec.Message = "incorrect header check";
1566                            marker = 5; // can't try inflateSync
1567                            break;
1568                        }
1569
1570                        mode = ((b & PRESET_DICT) == 0)
1571                            ? InflateManagerMode.BLOCKS
1572                            : InflateManagerMode.DICT4;
1573                        break;
1574
1575                    case InflateManagerMode.DICT4:
1576                        if (_codec.AvailableBytesIn == 0) return r;
1577                        r = f;
1578                        _codec.AvailableBytesIn--;
1579                        _codec.TotalBytesIn++;
1580                        expectedCheck = (uint)((_codec.InputBuffer[_codec.NextIn++] << 24) & 0xff000000);
1581                        mode = InflateManagerMode.DICT3;
1582                        break;
1583
1584                    case InflateManagerMode.DICT3:
1585                        if (_codec.AvailableBytesIn == 0) return r;
1586                        r = f;
1587                        _codec.AvailableBytesIn--;
1588                        _codec.TotalBytesIn++;
1589                        expectedCheck += (uint)((_codec.InputBuffer[_codec.NextIn++] << 16) & 0x00ff0000);
1590                        mode = InflateManagerMode.DICT2;
1591                        break;
1592
1593                    case InflateManagerMode.DICT2:
1594
1595                        if (_codec.AvailableBytesIn == 0) return r;
1596                        r = f;
1597                        _codec.AvailableBytesIn--;
1598                        _codec.TotalBytesIn++;
1599                        expectedCheck += (uint)((_codec.InputBuffer[_codec.NextIn++] << 8) & 0x0000ff00);
1600                        mode = InflateManagerMode.DICT1;
1601                        break;
1602
1603
1604                    case InflateManagerMode.DICT1:
1605                        if (_codec.AvailableBytesIn == 0) return r;
1606                        r = f;
1607                        _codec.AvailableBytesIn--; _codec.TotalBytesIn++;
1608                        expectedCheck += (uint)(_codec.InputBuffer[_codec.NextIn++] & 0x000000ff);
1609                        _codec._Adler32 = expectedCheck;
1610                        mode = InflateManagerMode.DICT0;
1611                        return ZlibConstants.Z_NEED_DICT;
1612
1613
1614                    case InflateManagerMode.DICT0:
1615                        mode = InflateManagerMode.BAD;
1616                        _codec.Message = "need dictionary";
1617                        marker = 0; // can try inflateSync
1618                        return ZlibConstants.Z_STREAM_ERROR;
1619
1620
1621                    case InflateManagerMode.BLOCKS:
1622                        r = blocks.Process(r);
1623                        if (r == ZlibConstants.Z_DATA_ERROR)
1624                        {
1625                            mode = InflateManagerMode.BAD;
1626                            marker = 0; // can try inflateSync
1627                            break;
1628                        }
1629
1630                        if (r == ZlibConstants.Z_OK) r = f;
1631
1632                        if (r != ZlibConstants.Z_STREAM_END)
1633                            return r;
1634
1635                        r = f;
1636                        computedCheck = blocks.Reset();
1637                        if (!HandleRfc1950HeaderBytes)
1638                        {
1639                            mode = InflateManagerMode.DONE;
1640                            return ZlibConstants.Z_STREAM_END;
1641                        }
1642                        mode = InflateManagerMode.CHECK4;
1643                        break;
1644
1645                    case InflateManagerMode.CHECK4:
1646                        if (_codec.AvailableBytesIn == 0) return r;
1647                        r = f;
1648                        _codec.AvailableBytesIn--;
1649                        _codec.TotalBytesIn++;
1650                        expectedCheck = (uint)((_codec.InputBuffer[_codec.NextIn++] << 24) & 0xff000000);
1651                        mode = InflateManagerMode.CHECK3;
1652                        break;
1653
1654                    case InflateManagerMode.CHECK3:
1655                        if (_codec.AvailableBytesIn == 0) return r;
1656                        r = f;
1657                        _codec.AvailableBytesIn--; _codec.TotalBytesIn++;
1658                        expectedCheck += (uint)((_codec.InputBuffer[_codec.NextIn++] << 16) & 0x00ff0000);
1659                        mode = InflateManagerMode.CHECK2;
1660                        break;
1661
1662                    case InflateManagerMode.CHECK2:
1663                        if (_codec.AvailableBytesIn == 0) return r;
1664                        r = f;
1665                        _codec.AvailableBytesIn--;
1666                        _codec.TotalBytesIn++;
1667                        expectedCheck += (uint)((_codec.InputBuffer[_codec.NextIn++] << 8) & 0x0000ff00);
1668                        mode = InflateManagerMode.CHECK1;
1669                        break;
1670
1671                    case InflateManagerMode.CHECK1:
1672                        if (_codec.AvailableBytesIn == 0) return r;
1673                        r = f;
1674                        _codec.AvailableBytesIn--; _codec.TotalBytesIn++;
1675                        expectedCheck += (uint)(_codec.InputBuffer[_codec.NextIn++] & 0x000000ff);
1676                        if (computedCheck != expectedCheck)
1677                        {
1678                            mode = InflateManagerMode.BAD;
1679                            _codec.Message = "incorrect data check";
1680                            marker = 5; // can't try inflateSync
1681                            break;
1682                        }
1683                        mode = InflateManagerMode.DONE;
1684                        return ZlibConstants.Z_STREAM_END;
1685
1686                    case InflateManagerMode.DONE:
1687                        return ZlibConstants.Z_STREAM_END;
1688
1689                    case InflateManagerMode.BAD:
1690                        throw new ZlibException(String.Format("Bad state ({0})", _codec.Message));
1691
1692                    default:
1693                        throw new ZlibException("Stream error.");
1694
1695                }
1696            }
1697        }
1698
1699
1700
1701        internal int SetDictionary(byte[] dictionary)
1702        {
1703            int index = 0;
1704            int length = dictionary.Length;
1705            if (mode != InflateManagerMode.DICT0)
1706                throw new ZlibException("Stream error.");
1707
1708            if (Adler.Adler32(1, dictionary, 0, dictionary.Length) != _codec._Adler32)
1709            {
1710                return ZlibConstants.Z_DATA_ERROR;
1711            }
1712
1713            _codec._Adler32 = Adler.Adler32(0, null, 0, 0);
1714
1715            if (length >= (1 << wbits))
1716            {
1717                length = (1 << wbits) - 1;
1718                index = dictionary.Length - length;
1719            }
1720            blocks.SetDictionary(dictionary, index, length);
1721            mode = InflateManagerMode.BLOCKS;
1722            return ZlibConstants.Z_OK;
1723        }
1724
1725
1726        private static readonly byte[] mark = new byte[] { 0, 0, 0xff, 0xff };
1727
1728        internal int Sync()
1729        {
1730            int n; // number of bytes to look at
1731            int p; // pointer to bytes
1732            int m; // number of marker bytes found in a row
1733            long r, w; // temporaries to save total_in and total_out
1734
1735            // set up
1736            if (mode != InflateManagerMode.BAD)
1737            {
1738                mode = InflateManagerMode.BAD;
1739                marker = 0;
1740            }
1741            if ((n = _codec.AvailableBytesIn) == 0)
1742                return ZlibConstants.Z_BUF_ERROR;
1743            p = _codec.NextIn;
1744            m = marker;
1745
1746            // search
1747            while (n != 0 && m < 4)
1748            {
1749                if (_codec.InputBuffer[p] == mark[m])
1750                {
1751                    m++;
1752                }
1753                else if (_codec.InputBuffer[p] != 0)
1754                {
1755                    m = 0;
1756                }
1757                else
1758                {
1759                    m = 4 - m;
1760                }
1761                p++; n--;
1762            }
1763
1764            // restore
1765            _codec.TotalBytesIn += p - _codec.NextIn;
1766            _codec.NextIn = p;
1767            _codec.AvailableBytesIn = n;
1768            marker = m;
1769
1770            // return no joy or set up to restart on a new block
1771            if (m != 4)
1772            {
1773                return ZlibConstants.Z_DATA_ERROR;
1774            }
1775            r = _codec.TotalBytesIn;
1776            w = _codec.TotalBytesOut;
1777            Reset();
1778            _codec.TotalBytesIn = r;
1779            _codec.TotalBytesOut = w;
1780            mode = InflateManagerMode.BLOCKS;
1781            return ZlibConstants.Z_OK;
1782        }
1783
1784
1785        // Returns true if inflate is currently at the end of a block generated
1786        // by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
1787        // implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
1788        // but removes the length bytes of the resulting empty stored block. When
1789        // decompressing, PPP checks that at the end of input packet, inflate is
1790        // waiting for these length bytes.
1791        internal int SyncPoint(ZlibCodec z)
1792        {
1793            return blocks.SyncPoint();
1794        }
1795    }
1796}
Note: See TracBrowser for help on using the repository browser.