summary refs log tree commit diff
path: root/crypto/src/util/zlib/InfCodes.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/util/zlib/InfCodes.cs')
-rw-r--r--crypto/src/util/zlib/InfCodes.cs611
1 files changed, 611 insertions, 0 deletions
diff --git a/crypto/src/util/zlib/InfCodes.cs b/crypto/src/util/zlib/InfCodes.cs
new file mode 100644
index 000000000..6fcafe458
--- /dev/null
+++ b/crypto/src/util/zlib/InfCodes.cs
@@ -0,0 +1,611 @@
+using System;
+/*
+ * $Id: InfCodes.cs,v 1.2 2008-05-10 09:35:40 bouncy Exp $
+ *
+Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+  1. Redistributions of source code must retain the above copyright notice,
+     this list of conditions and the following disclaimer.
+
+  2. Redistributions in binary form must reproduce the above copyright 
+     notice, this list of conditions and the following disclaimer in 
+     the documentation and/or other materials provided with the distribution.
+
+  3. The names of the authors may not be used to endorse or promote products
+     derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
+INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
+INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
+OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * This program is based on zlib-1.1.3, so all credit should go authors
+ * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
+ * and contributors of zlib.
+ */
+
+namespace Org.BouncyCastle.Utilities.Zlib {
+
+    internal sealed class InfCodes{
+
+        private static readonly int[] inflate_mask = {
+                                                0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
+                                                0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
+                                                0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
+                                                0x00007fff, 0x0000ffff
+                                            };
+
+        private const int Z_OK=0;
+        private const int Z_STREAM_END=1;
+        private const int Z_NEED_DICT=2;
+        private const int Z_ERRNO=-1;
+        private const int Z_STREAM_ERROR=-2;
+        private const int Z_DATA_ERROR=-3;
+        private const int Z_MEM_ERROR=-4;
+        private const int Z_BUF_ERROR=-5;
+        private const int Z_VERSION_ERROR=-6;
+
+        // waiting for "i:"=input,
+        //             "o:"=output,
+        //             "x:"=nothing
+        private const int START=0;  // x: set up for LEN
+        private const int LEN=1;    // i: get length/literal/eob next
+        private const int LENEXT=2; // i: getting length extra (have base)
+        private const int DIST=3;   // i: get distance next
+        private const int DISTEXT=4;// i: getting distance extra
+        private const int COPY=5;   // o: copying bytes in window, waiting for space
+        private const int LIT=6;    // o: got literal, waiting for output space
+        private const int WASH=7;   // o: got eob, possibly still output waiting
+        private const int END=8;    // x: got eob and all data flushed
+        private const int BADCODE=9;// x: got error
+
+        int mode;      // current inflate_codes mode
+
+        // mode dependent information
+        int len;
+
+        int[] tree; // pointer into tree
+        int tree_index=0;
+        int need;   // bits needed
+
+        int lit;
+
+        // if EXT or COPY, where and how much
+        int get;              // bits to get for extra
+        int dist;             // distance back to copy from
+
+        byte lbits;           // ltree bits decoded per branch
+        byte dbits;           // dtree bits decoder per branch
+        int[] ltree;          // literal/length/eob tree
+        int ltree_index;      // literal/length/eob tree
+        int[] dtree;          // distance tree
+        int dtree_index;      // distance tree
+
+        internal InfCodes(){
+        }
+        internal void init(int bl, int bd,
+            int[] tl, int tl_index,
+            int[] td, int td_index, ZStream z){
+            mode=START;
+            lbits=(byte)bl;
+            dbits=(byte)bd;
+            ltree=tl;
+            ltree_index=tl_index;
+            dtree = td;
+            dtree_index=td_index;
+            tree=null;
+        }
+
+        internal int proc(InfBlocks s, ZStream z, int r){ 
+            int j;              // temporary storage
+            int tindex;         // temporary pointer
+            int e;              // extra bits or operation
+            int b=0;            // bit buffer
+            int k=0;            // bits in bit buffer
+            int p=0;            // input data pointer
+            int n;              // bytes available there
+            int q;              // output window write pointer
+            int m;              // bytes to end of window or read pointer
+            int f;              // pointer to copy strings from
+
+            // copy input/output information to locals (UPDATE macro restores)
+            p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
+            q=s.write;m=q<s.read?s.read-q-1:s.end-q;
+
+            // process input and output based on current state
+            while (true){
+                switch (mode){
+                        // waiting for "i:"=input, "o:"=output, "x:"=nothing
+                    case START:         // x: set up for LEN
+                        if (m >= 258 && n >= 10){
+
+                            s.bitb=b;s.bitk=k;
+                            z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                            s.write=q;
+                            r = inflate_fast(lbits, dbits, 
+                                ltree, ltree_index, 
+                                dtree, dtree_index,
+                                s, z);
+
+                            p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
+                            q=s.write;m=q<s.read?s.read-q-1:s.end-q;
+
+                            if (r != Z_OK){
+                                mode = r == Z_STREAM_END ? WASH : BADCODE;
+                                break;
+                            }
+                        }
+                        need = lbits;
+                        tree = ltree;
+                        tree_index=ltree_index;
+
+                        mode = LEN;
+                        goto case LEN;
+                    case LEN:           // i: get length/literal/eob next
+                        j = need;
+
+                        while(k<(j)){
+                            if(n!=0)r=Z_OK;
+                            else{
+
+                                s.bitb=b;s.bitk=k;
+                                z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                s.write=q;
+                                return s.inflate_flush(z,r);
+                            }
+                            n--;
+                            b|=(z.next_in[p++]&0xff)<<k;
+                            k+=8;
+                        }
+
+                        tindex=(tree_index+(b&inflate_mask[j]))*3;
+
+                        b>>=(tree[tindex+1]);
+                        k-=(tree[tindex+1]);
+
+                        e=tree[tindex];
+
+                        if(e == 0){               // literal
+                            lit = tree[tindex+2];
+                            mode = LIT;
+                            break;
+                        }
+                        if((e & 16)!=0 ){          // length
+                            get = e & 15;
+                            len = tree[tindex+2];
+                            mode = LENEXT;
+                            break;
+                        }
+                        if ((e & 64) == 0){        // next table
+                            need = e;
+                            tree_index = tindex/3+tree[tindex+2];
+                            break;
+                        }
+                        if ((e & 32)!=0){               // end of block
+                            mode = WASH;
+                            break;
+                        }
+                        mode = BADCODE;        // invalid code
+                        z.msg = "invalid literal/length code";
+                        r = Z_DATA_ERROR;
+
+                        s.bitb=b;s.bitk=k;
+                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                        s.write=q;
+                        return s.inflate_flush(z,r);
+
+                    case LENEXT:        // i: getting length extra (have base)
+                        j = get;
+
+                        while(k<(j)){
+                            if(n!=0)r=Z_OK;
+                            else{
+
+                                s.bitb=b;s.bitk=k;
+                                z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                s.write=q;
+                                return s.inflate_flush(z,r);
+                            }
+                            n--; b|=(z.next_in[p++]&0xff)<<k;
+                            k+=8;
+                        }
+
+                        len += (b & inflate_mask[j]);
+
+                        b>>=j;
+                        k-=j;
+
+                        need = dbits;
+                        tree = dtree;
+                        tree_index=dtree_index;
+                        mode = DIST;
+                        goto case DIST;
+                    case DIST:          // i: get distance next
+                        j = need;
+
+                        while(k<(j)){
+                            if(n!=0)r=Z_OK;
+                            else{
+
+                                s.bitb=b;s.bitk=k;
+                                z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                s.write=q;
+                                return s.inflate_flush(z,r);
+                            }
+                            n--; b|=(z.next_in[p++]&0xff)<<k;
+                            k+=8;
+                        }
+
+                        tindex=(tree_index+(b & inflate_mask[j]))*3;
+
+                        b>>=tree[tindex+1];
+                        k-=tree[tindex+1];
+
+                        e = (tree[tindex]);
+                        if((e & 16)!=0){               // distance
+                            get = e & 15;
+                            dist = tree[tindex+2];
+                            mode = DISTEXT;
+                            break;
+                        }
+                        if ((e & 64) == 0){        // next table
+                            need = e;
+                            tree_index = tindex/3 + tree[tindex+2];
+                            break;
+                        }
+                        mode = BADCODE;        // invalid code
+                        z.msg = "invalid distance code";
+                        r = Z_DATA_ERROR;
+
+                        s.bitb=b;s.bitk=k;
+                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                        s.write=q;
+                        return s.inflate_flush(z,r);
+
+                    case DISTEXT:       // i: getting distance extra
+                        j = get;
+
+                        while(k<(j)){
+                            if(n!=0)r=Z_OK;
+                            else{
+
+                                s.bitb=b;s.bitk=k;
+                                z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                s.write=q;
+                                return s.inflate_flush(z,r);
+                            }
+                            n--; b|=(z.next_in[p++]&0xff)<<k;
+                            k+=8;
+                        }
+
+                        dist += (b & inflate_mask[j]);
+
+                        b>>=j;
+                        k-=j;
+
+                        mode = COPY;
+                        goto case COPY;
+                    case COPY:          // o: copying bytes in window, waiting for space
+                        f = q - dist;
+                        while(f < 0){     // modulo window size-"while" instead
+                            f += s.end;     // of "if" handles invalid distances
+                        }
+                        while (len!=0){
+
+                            if(m==0){
+                                if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
+                                if(m==0){
+                                    s.write=q; r=s.inflate_flush(z,r);
+                                    q=s.write;m=q<s.read?s.read-q-1:s.end-q;
+
+                                    if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
+
+                                    if(m==0){
+                                        s.bitb=b;s.bitk=k;
+                                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                        s.write=q;
+                                        return s.inflate_flush(z,r);
+                                    }  
+                                }
+                            }
+
+                            s.window[q++]=s.window[f++]; m--;
+
+                            if (f == s.end)
+                                f = 0;
+                            len--;
+                        }
+                        mode = START;
+                        break;
+                    case LIT:           // o: got literal, waiting for output space
+                        if(m==0){
+                            if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
+                            if(m==0){
+                                s.write=q; r=s.inflate_flush(z,r);
+                                q=s.write;m=q<s.read?s.read-q-1:s.end-q;
+
+                                if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
+                                if(m==0){
+                                    s.bitb=b;s.bitk=k;
+                                    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                    s.write=q;
+                                    return s.inflate_flush(z,r);
+                                }
+                            }
+                        }
+                        r=Z_OK;
+
+                        s.window[q++]=(byte)lit; m--;
+
+                        mode = START;
+                        break;
+                    case WASH:           // o: got eob, possibly more output
+                        if (k > 7){        // return unused byte, if any
+                            k -= 8;
+                            n++;
+                            p--;             // can always return one
+                        }
+
+                        s.write=q; r=s.inflate_flush(z,r);
+                        q=s.write;m=q<s.read?s.read-q-1:s.end-q;
+
+                        if (s.read != s.write){
+                            s.bitb=b;s.bitk=k;
+                            z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                            s.write=q;
+                            return s.inflate_flush(z,r);
+                        }
+                        mode = END;
+                        goto case END;
+                    case END:
+                        r = Z_STREAM_END;
+                        s.bitb=b;s.bitk=k;
+                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                        s.write=q;
+                        return s.inflate_flush(z,r);
+
+                    case BADCODE:       // x: got error
+
+                        r = Z_DATA_ERROR;
+
+                        s.bitb=b;s.bitk=k;
+                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                        s.write=q;
+                        return s.inflate_flush(z,r);
+
+                    default:
+                        r = Z_STREAM_ERROR;
+
+                        s.bitb=b;s.bitk=k;
+                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                        s.write=q;
+                        return s.inflate_flush(z,r);
+                }
+            }
+        }
+
+        internal void free(ZStream z){
+            //  ZFREE(z, c);
+        }
+
+        // Called with number of bytes left to write in window at least 258
+        // (the maximum string length) and number of input bytes available
+        // at least ten.  The ten bytes are six bytes for the longest length/
+        // distance pair plus four bytes for overloading the bit buffer.
+
+        internal int inflate_fast(int bl, int bd, 
+            int[] tl, int tl_index,
+            int[] td, int td_index,
+            InfBlocks s, ZStream z){
+            int t;                // temporary pointer
+            int[] tp;             // temporary pointer
+            int tp_index;         // temporary pointer
+            int e;                // extra bits or operation
+            int b;                // bit buffer
+            int k;                // bits in bit buffer
+            int p;                // input data pointer
+            int n;                // bytes available there
+            int q;                // output window write pointer
+            int m;                // bytes to end of window or read pointer
+            int ml;               // mask for literal/length tree
+            int md;               // mask for distance tree
+            int c;                // bytes to copy
+            int d;                // distance back to copy from
+            int r;                // copy source pointer
+
+            int tp_index_t_3;     // (tp_index+t)*3
+
+            // load input, output, bit values
+            p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
+            q=s.write;m=q<s.read?s.read-q-1:s.end-q;
+
+            // initialize masks
+            ml = inflate_mask[bl];
+            md = inflate_mask[bd];
+
+            // do until not enough input or output space for fast loop
+            do {                          // assume called with m >= 258 && n >= 10
+                // get literal/length code
+            while(k<(20)){              // max bits for literal/length code
+                n--;
+                b|=(z.next_in[p++]&0xff)<<k;k+=8;
+            }
+
+                t= b&ml;
+                tp=tl; 
+                tp_index=tl_index;
+                tp_index_t_3=(tp_index+t)*3;
+                if ((e = tp[tp_index_t_3]) == 0){
+                    b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
+
+                    s.window[q++] = (byte)tp[tp_index_t_3+2];
+                    m--;
+                    continue;
+                }
+                do {
+
+                    b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
+
+                    if((e&16)!=0){
+                        e &= 15;
+                        c = tp[tp_index_t_3+2] + ((int)b & inflate_mask[e]);
+
+                        b>>=e; k-=e;
+
+                        // decode distance base of block to copy
+                        while(k<(15)){           // max bits for distance code
+                            n--;
+                            b|=(z.next_in[p++]&0xff)<<k;k+=8;
+                        }
+
+                        t= b&md;
+                        tp=td;
+                        tp_index=td_index;
+                        tp_index_t_3=(tp_index+t)*3;
+                        e = tp[tp_index_t_3];
+
+                        do {
+
+                            b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
+
+                            if((e&16)!=0){
+                                // get extra bits to add to distance base
+                                e &= 15;
+                                while(k<(e)){         // get extra bits (up to 13)
+                                    n--;
+                                    b|=(z.next_in[p++]&0xff)<<k;k+=8;
+                                }
+
+                                d = tp[tp_index_t_3+2] + (b&inflate_mask[e]);
+
+                                b>>=(e); k-=(e);
+
+                                // do the copy
+                                m -= c;
+                                if (q >= d){                // offset before dest
+                                    //  just copy
+                                    r=q-d;
+                                    if(q-r>0 && 2>(q-r)){           
+                                        s.window[q++]=s.window[r++]; // minimum count is three,
+                                        s.window[q++]=s.window[r++]; // so unroll loop a little
+                                        c-=2;
+                                    }
+                                    else{
+                                        System.Array.Copy(s.window, r, s.window, q, 2);
+                                        q+=2; r+=2; c-=2;
+                                    }
+                                }
+                                else{                  // else offset after destination
+                                    r=q-d;
+                                    do{
+                                        r+=s.end;          // force pointer in window
+                                    }while(r<0);         // covers invalid distances
+                                    e=s.end-r;
+                                    if(c>e){             // if source crosses,
+                                        c-=e;              // wrapped copy
+                                        if(q-r>0 && e>(q-r)){           
+                                            do{s.window[q++] = s.window[r++];}
+                                            while(--e!=0);
+                                        }
+                                        else{
+                                            System.Array.Copy(s.window, r, s.window, q, e);
+                                            q+=e; r+=e; e=0;
+                                        }
+                                        r = 0;                  // copy rest from start of window
+                                    }
+
+                                }
+
+                                // copy all or what's left
+                                if(q-r>0 && c>(q-r)){           
+                                    do{s.window[q++] = s.window[r++];}
+                                    while(--c!=0);
+                                }
+                                else{
+                                    System.Array.Copy(s.window, r, s.window, q, c);
+                                    q+=c; r+=c; c=0;
+                                }
+                                break;
+                            }
+                            else if((e&64)==0){
+                                t+=tp[tp_index_t_3+2];
+                                t+=(b&inflate_mask[e]);
+                                tp_index_t_3=(tp_index+t)*3;
+                                e=tp[tp_index_t_3];
+                            }
+                            else{
+                                z.msg = "invalid distance code";
+
+                                c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
+
+                                s.bitb=b;s.bitk=k;
+                                z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                                s.write=q;
+
+                                return Z_DATA_ERROR;
+                            }
+                        }
+                        while(true);
+                        break;
+                    }
+
+                    if((e&64)==0){
+                        t+=tp[tp_index_t_3+2];
+                        t+=(b&inflate_mask[e]);
+                        tp_index_t_3=(tp_index+t)*3;
+                        if((e=tp[tp_index_t_3])==0){
+
+                            b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
+
+                            s.window[q++]=(byte)tp[tp_index_t_3+2];
+                            m--;
+                            break;
+                        }
+                    }
+                    else if((e&32)!=0){
+
+                        c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
+ 
+                        s.bitb=b;s.bitk=k;
+                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                        s.write=q;
+
+                        return Z_STREAM_END;
+                    }
+                    else{
+                        z.msg="invalid literal/length code";
+
+                        c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
+
+                        s.bitb=b;s.bitk=k;
+                        z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+                        s.write=q;
+
+                        return Z_DATA_ERROR;
+                    }
+                } 
+                while(true);
+            } 
+            while(m>=258 && n>= 10);
+
+            // not enough input or output--restore pointers and return
+            c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
+
+            s.bitb=b;s.bitk=k;
+            z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
+            s.write=q;
+
+            return Z_OK;
+        }
+    }
+}
\ No newline at end of file