internal void free(ZStream z){ // ZFREE(z, c); }
internal int inflateInit(ZStream z, int w){ z.msg = null; blocks = null; // handle undocumented nowrap option (no zlib header or check) nowrap = 0; if(w < 0){ w = - w; nowrap = 1; } // set window size if(w<8 ||w>15){ inflateEnd(z); return Z_STREAM_ERROR; } wbits=w; z.istate.blocks=new InfBlocks(z, z.istate.nowrap!=0 ? null : this, 1<<w); // reset state inflateReset(z); return Z_OK; }
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 reset(ZStream z, long[] c){ if(c!=null) c[0]=check; if(mode==BTREE || mode==DTREE){ } if(mode==CODES){ codes.free(z); } mode=TYPE; bitk=0; bitb=0; read=write=0; if(checkfn != null) z.adler=check=z._adler.adler32(0L, null, 0, 0); }
internal void free(ZStream z){ reset(z, null); window=null; hufts=null; //ZFREE(z, s); }
internal int inflate_trees_bits(int[] c, // 19 code lengths int[] bb, // bits tree desired/actual depth int[] tb, // bits tree result int[] hp, // space for trees ZStream z // for messages ){ int result; initWorkArea(19); hn[0]=0; result = huft_build(c, 0, 19, 19, null, null, tb, bb, hp, hn, v); if(result == Z_DATA_ERROR){ z.msg = "oversubscribed dynamic bit lengths tree"; } else if(result == Z_BUF_ERROR || bb[0] == 0){ z.msg = "incomplete dynamic bit lengths tree"; result = Z_DATA_ERROR; } return result; }
internal static int inflate_trees_fixed(int[] bl, //literal desired/actual bit depth int[] bd, //distance desired/actual bit depth int[][] tl,//literal/length tree result int[][] td,//distance tree result ZStream z //for memory allocation ){ bl[0]=fixed_bl; bd[0]=fixed_bd; tl[0]=fixed_tl; td[0]=fixed_td; return Z_OK; }
internal int deflateInit(ZStream strm, int level, int bits){ return deflateInit2(strm, level, Z_DEFLATED, bits, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY); }
internal int deflateInit(ZStream strm, int level){ return deflateInit(strm, level, MAX_WBITS); }
// Returns true if inflate is currently at the end of a block generated // by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP // implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH // but removes the length bytes of the resulting empty stored block. When // decompressing, PPP checks that at the end of input packet, inflate is // waiting for these length bytes. internal int inflateSyncPoint(ZStream z){ if(z == null || z.istate == null || z.istate.blocks == null) return Z_STREAM_ERROR; return z.istate.blocks.sync_point(); }
internal InfBlocks blocks; // current inflate_blocks state internal int inflateReset(ZStream z){ if(z == null || z.istate == null) return Z_STREAM_ERROR; z.total_in = z.total_out = 0; z.msg = null; z.istate.mode = z.istate.nowrap!=0 ? BLOCKS : METHOD; z.istate.blocks.reset(z, null); return Z_OK; }
internal int inflateSync(ZStream z){ int n; // number of bytes to look at int p; // pointer to bytes int m; // number of marker bytes found in a row long r, w; // temporaries to save total_in and total_out // set up if(z == null || z.istate == null) return Z_STREAM_ERROR; if(z.istate.mode != BAD){ z.istate.mode = BAD; z.istate.marker = 0; } if((n=z.avail_in)==0) return Z_BUF_ERROR; p=z.next_in_index; m=z.istate.marker; // search while (n!=0 && m < 4){ if(z.next_in[p] == mark[m]){ m++; } else if(z.next_in[p]!=0){ m = 0; } else{ m = 4 - m; } p++; n--; } // restore z.total_in += p-z.next_in_index; z.next_in_index = p; z.avail_in = n; z.istate.marker = m; // return no joy or set up to restart on a new block if(m != 4){ return Z_DATA_ERROR; } r=z.total_in; w=z.total_out; inflateReset(z); z.total_in=r; z.total_out = w; z.istate.mode = BLOCKS; return Z_OK; }
internal int inflateSetDictionary(ZStream z, byte[] dictionary, int dictLength){ int index=0; int length = dictLength; if(z==null || z.istate == null|| z.istate.mode != DICT0) return Z_STREAM_ERROR; if(z._adler.adler32(1L, dictionary, 0, dictLength)!=z.adler){ return Z_DATA_ERROR; } z.adler = z._adler.adler32(0, null, 0, 0); if(length >= (1<<z.istate.wbits)){ length = (1<<z.istate.wbits)-1; index=dictLength - length; } z.istate.blocks.set_dictionary(dictionary, index, length); z.istate.mode = BLOCKS; return Z_OK; }
internal int inflate(ZStream z, int f){ int r; int b; if(z == null || z.istate == null || z.next_in == null) return Z_STREAM_ERROR; f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK; r = Z_BUF_ERROR; while (true){ //System.out.println("mode: "+z.istate.mode); switch (z.istate.mode){ case METHOD: if(z.avail_in==0)return r;r=f; z.avail_in--; z.total_in++; if(((z.istate.method = z.next_in[z.next_in_index++])&0xf)!=Z_DEFLATED){ z.istate.mode = BAD; z.msg="unknown compression method"; z.istate.marker = 5; // can't try inflateSync break; } if((z.istate.method>>4)+8>z.istate.wbits){ z.istate.mode = BAD; z.msg="invalid window size"; z.istate.marker = 5; // can't try inflateSync break; } z.istate.mode=FLAG; goto case FLAG; case FLAG: if(z.avail_in==0)return r;r=f; z.avail_in--; z.total_in++; b = (z.next_in[z.next_in_index++])&0xff; if((((z.istate.method << 8)+b) % 31)!=0){ z.istate.mode = BAD; z.msg = "incorrect header check"; z.istate.marker = 5; // can't try inflateSync break; } if((b&PRESET_DICT)==0){ z.istate.mode = BLOCKS; break; } z.istate.mode = DICT4; goto case DICT4; case DICT4: if(z.avail_in==0)return r;r=f; z.avail_in--; z.total_in++; z.istate.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L; z.istate.mode=DICT3; goto case DICT3; case DICT3: if(z.avail_in==0)return r;r=f; z.avail_in--; z.total_in++; z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L; z.istate.mode=DICT2; goto case DICT2; case DICT2: if(z.avail_in==0)return r;r=f; z.avail_in--; z.total_in++; z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L; z.istate.mode=DICT1; goto case DICT1; case DICT1: if(z.avail_in==0)return r;r=f; z.avail_in--; z.total_in++; z.istate.need += (z.next_in[z.next_in_index++]&0xffL); z.adler = z.istate.need; z.istate.mode = DICT0; return Z_NEED_DICT; case DICT0: z.istate.mode = BAD; z.msg = "need dictionary"; z.istate.marker = 0; // can try inflateSync return Z_STREAM_ERROR; case BLOCKS: r = z.istate.blocks.proc(z, r); if(r == Z_DATA_ERROR){ z.istate.mode = BAD; z.istate.marker = 0; // can try inflateSync break; } if(r == Z_OK){ r = f; } if(r != Z_STREAM_END){ return r; } r = f; z.istate.blocks.reset(z, z.istate.was); if(z.istate.nowrap!=0){ z.istate.mode=DONE; break; } z.istate.mode=CHECK4; goto case CHECK4; case CHECK4: if(z.avail_in==0)return r;r=f; z.avail_in--; z.total_in++; z.istate.need=((z.next_in[z.next_in_index++]&0xff)<<24)&0xff000000L; z.istate.mode=CHECK3; goto case CHECK3; case CHECK3: if(z.avail_in==0)return r;r=f; z.avail_in--; z.total_in++; z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<16)&0xff0000L; z.istate.mode = CHECK2; goto case CHECK2; case CHECK2: if(z.avail_in==0)return r;r=f; z.avail_in--; z.total_in++; z.istate.need+=((z.next_in[z.next_in_index++]&0xff)<<8)&0xff00L; z.istate.mode = CHECK1; goto case CHECK1; case CHECK1: if(z.avail_in==0)return r;r=f; z.avail_in--; z.total_in++; z.istate.need+=(z.next_in[z.next_in_index++]&0xffL); if(((int)(z.istate.was[0])) != ((int)(z.istate.need))){ z.istate.mode = BAD; z.msg = "incorrect data check"; z.istate.marker = 5; // can't try inflateSync break; } z.istate.mode = DONE; goto case DONE; case DONE: return Z_STREAM_END; case BAD: return Z_DATA_ERROR; default: return Z_STREAM_ERROR; } } }
// 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; }
internal int deflateInit2(ZStream strm, int level, int method, int windowBits, int memLevel, int strategy){ int noheader = 0; // byte[] my_version=ZLIB_VERSION; // // if (version == null || version[0] != my_version[0] // || stream_size != sizeof(z_stream)) { // return Z_VERSION_ERROR; // } strm.msg = null; if (level == Z_DEFAULT_COMPRESSION) level = 6; if (windowBits < 0) { // undocumented feature: suppress zlib header noheader = 1; windowBits = -windowBits; } if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { return Z_STREAM_ERROR; } strm.dstate = (Deflate)this; this.noheader = noheader; w_bits = windowBits; w_size = 1 << w_bits; w_mask = w_size - 1; hash_bits = memLevel + 7; hash_size = 1 << hash_bits; hash_mask = hash_size - 1; hash_shift = ((hash_bits+MIN_MATCH-1)/MIN_MATCH); window = new byte[w_size*2]; prev = new short[w_size]; head = new short[hash_size]; lit_bufsize = 1 << (memLevel + 6); // 16K elements by default // We overlay pending_buf and d_buf+l_buf. This works since the average // output size for (length,distance) codes is <= 24 bits. pending_buf = new byte[lit_bufsize*4]; pending_buf_size = lit_bufsize*4; d_buf = lit_bufsize/2; l_buf = (1+2)*lit_bufsize; this.level = level; //System.out.println("level="+level); this.strategy = strategy; this.method = (byte)method; return deflateReset(strm); }
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 deflateReset(ZStream strm){ strm.total_in = strm.total_out = 0; strm.msg = null; // strm.data_type = Z_UNKNOWN; pending = 0; pending_out = 0; if(noheader < 0) { noheader = 0; // was set to -1 by deflate(..., Z_FINISH); } status = (noheader!=0) ? BUSY_STATE : INIT_STATE; strm.adler=strm._adler.adler32(0, null, 0, 0); last_flush = Z_NO_FLUSH; tr_init(); lm_init(); return Z_OK; }
internal int inflate_trees_dynamic(int nl, // number of literal/length codes int nd, // number of distance codes int[] c, // that many (total) code lengths int[] bl, // literal desired/actual bit depth int[] bd, // distance desired/actual bit depth int[] tl, // literal/length tree result int[] td, // distance tree result int[] hp, // space for trees ZStream z // for messages ){ int result; // build literal/length tree initWorkArea(288); hn[0]=0; result = huft_build(c, 0, nl, 257, cplens, cplext, tl, bl, hp, hn, v); if (result != Z_OK || bl[0] == 0){ if(result == Z_DATA_ERROR){ z.msg = "oversubscribed literal/length tree"; } else if (result != Z_MEM_ERROR){ z.msg = "incomplete literal/length tree"; result = Z_DATA_ERROR; } return result; } // build distance tree initWorkArea(288); result = huft_build(c, nl, nd, 0, cpdist, cpdext, td, bd, hp, hn, v); if (result != Z_OK || (bd[0] == 0 && nl > 257)){ if (result == Z_DATA_ERROR){ z.msg = "oversubscribed distance tree"; } else if (result == Z_BUF_ERROR) { z.msg = "incomplete distance tree"; result = Z_DATA_ERROR; } else if (result != Z_MEM_ERROR){ z.msg = "empty distance tree with lengths"; result = Z_DATA_ERROR; } return result; } return Z_OK; }
internal int deflateParams(ZStream strm, int _level, int _strategy){ int err=Z_OK; if(_level == Z_DEFAULT_COMPRESSION){ _level = 6; } if(_level < 0 || _level > 9 || _strategy < 0 || _strategy > Z_HUFFMAN_ONLY) { return Z_STREAM_ERROR; } if(config_table[level].func!=config_table[_level].func && strm.total_in != 0) { // Flush the last buffer: err = strm.deflate(Z_PARTIAL_FLUSH); } if(level != _level) { level = _level; max_lazy_match = config_table[level].max_lazy; good_match = config_table[level].good_length; nice_match = config_table[level].nice_length; max_chain_length = config_table[level].max_chain; } strategy = _strategy; return err; }
internal InfBlocks(ZStream z, Object checkfn, int w){ hufts=new int[MANY*3]; window=new byte[w]; end=w; this.checkfn = checkfn; mode = TYPE; reset(z, null); }
internal int deflateSetDictionary (ZStream strm, byte[] dictionary, int dictLength){ int length = dictLength; int index=0; if(dictionary == null || status != INIT_STATE) return Z_STREAM_ERROR; strm.adler=strm._adler.adler32(strm.adler, dictionary, 0, dictLength); if(length < MIN_MATCH) return Z_OK; if(length > w_size-MIN_LOOKAHEAD){ length = w_size-MIN_LOOKAHEAD; index=dictLength-length; // use the tail of the dictionary } System.Array.Copy(dictionary, index, window, 0, length); strstart = length; block_start = length; // Insert all strings in the hash table (except for the last two bytes). // s->lookahead stays null, so s->ins_h will be recomputed at the next // call of fill_window. ins_h = window[0]&0xff; ins_h=(((ins_h)<<hash_shift)^(window[1]&0xff))&hash_mask; for(int n=0; n<=length-MIN_MATCH; n++){ ins_h=(((ins_h)<<hash_shift)^(window[(n)+(MIN_MATCH-1)]&0xff))&hash_mask; prev[n&w_mask]=head[ins_h]; head[ins_h]=(short)n; } return Z_OK; }
internal int proc(ZStream z, int r){ int t; // temporary storage 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 // copy input/output information to locals (UPDATE macro restores) p=z.next_in_index;n=z.avail_in;b=bitb;k=bitk;} { q=write;m=(int)(q<read?read-q-1:end-q);} // process input based on current state while(true){ switch (mode){ case TYPE: while(k<(3)){ if(n!=0){ r=Z_OK; } else{ bitb=b; bitk=k; z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; return inflate_flush(z,r); }; n--; b|=(z.next_in[p++]&0xff)<<k; k+=8; } t = (int)(b & 7); last = t & 1; switch (t >> 1){ case 0: { // stored b>>=(3);k-=(3);} t = k & 7; { // go to byte boundary b>>=(t);k-=(t);} mode = LENS; // get length of stored block break; case 1: { // fixed int[] bl=new int[1]; int[] bd=new int[1]; int[][] tl=new int[1][]; int[][] td=new int[1][]; InfTree.inflate_trees_fixed(bl, bd, tl, td, z); codes.init(bl[0], bd[0], tl[0], 0, td[0], 0, z); } { b>>=(3);k-=(3);} mode = CODES; break; case 2: { // dynamic b>>=(3);k-=(3);} mode = TABLE; break; case 3: { // illegal b>>=(3);k-=(3);} mode = BAD; z.msg = "invalid block type"; r = Z_DATA_ERROR; bitb=b; bitk=k; z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; return inflate_flush(z,r); } break; case LENS: while(k<(32)){ if(n!=0){ r=Z_OK; } else{ bitb=b; bitk=k; z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; return inflate_flush(z,r); }; n--; b|=(z.next_in[p++]&0xff)<<k; k+=8; } if ((((~b) >> 16) & 0xffff) != (b & 0xffff)){ mode = BAD; z.msg = "invalid stored block lengths"; r = Z_DATA_ERROR; bitb=b; bitk=k; z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; return inflate_flush(z,r); } left = (b & 0xffff); b = k = 0; // dump bits mode = left!=0 ? STORED : (last!=0 ? DRY : TYPE); break; case STORED: if (n == 0){ bitb=b; bitk=k; z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; return inflate_flush(z,r); } if(m==0){ if(q==end&&read!=0){ q=0; m=(int)(q<read?read-q-1:end-q); } if(m==0){ write=q; r=inflate_flush(z,r); q=write;m=(int)(q<read?read-q-1:end-q); if(q==end&&read!=0){ q=0; m=(int)(q<read?read-q-1:end-q); } if(m==0){ bitb=b; bitk=k; z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; return inflate_flush(z,r); } } } r=Z_OK; t = left; if(t>n) t = n; if(t>m) t = m; System.Array.Copy(z.next_in, p, window, q, t); p += t; n -= t; q += t; m -= t; if ((left -= t) != 0) break; mode = last!=0 ? DRY : TYPE; break; case TABLE: while(k<(14)){ if(n!=0){ r=Z_OK; } else{ bitb=b; bitk=k; z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; return inflate_flush(z,r); }; n--; b|=(z.next_in[p++]&0xff)<<k; k+=8; } table = t = (b & 0x3fff); if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29) { mode = BAD; z.msg = "too many length or distance symbols"; r = Z_DATA_ERROR; bitb=b; bitk=k; z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; return inflate_flush(z,r); } t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f); if(blens==null || blens.Length<t){ blens=new int[t]; } else{ for(int i=0; i<t; i++){blens[i]=0;} } { b>>=(14);k-=(14);} index = 0; mode = BTREE; goto case BTREE; case BTREE: while (index < 4 + (table >> 10)){ while(k<(3)){ if(n!=0){ r=Z_OK; } else{ bitb=b; bitk=k; z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; return inflate_flush(z,r); }; n--; b|=(z.next_in[p++]&0xff)<<k; k+=8; } blens[border[index++]] = b&7; { b>>=(3);k-=(3);} } while(index < 19){ blens[border[index++]] = 0; } bb[0] = 7; t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z); if (t != Z_OK){ r = t; if (r == Z_DATA_ERROR){ blens=null; mode = BAD; } bitb=b; bitk=k; z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; return inflate_flush(z,r); } index = 0; mode = DTREE; goto case DTREE; case DTREE: while (true){ t = table; if(!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))){ break; } int i, j, c; t = bb[0]; while(k<(t)){ if(n!=0){ r=Z_OK; } else{ bitb=b; bitk=k; z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; return inflate_flush(z,r); }; n--; b|=(z.next_in[p++]&0xff)<<k; k+=8; } if(tb[0]==-1){ //System.err.println("null..."); } t=hufts[(tb[0]+(b&inflate_mask[t]))*3+1]; c=hufts[(tb[0]+(b&inflate_mask[t]))*3+2]; if (c < 16){ b>>=(t);k-=(t); blens[index++] = c; } else { // c == 16..18 i = c == 18 ? 7 : c - 14; j = c == 18 ? 11 : 3; while(k<(t+i)){ if(n!=0){ r=Z_OK; } else{ bitb=b; bitk=k; z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; return inflate_flush(z,r); }; n--; b|=(z.next_in[p++]&0xff)<<k; k+=8; } b>>=(t);k-=(t); j += (b & inflate_mask[i]); b>>=(i);k-=(i); i = index; t = table; if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) || (c == 16 && i < 1)){ blens=null; mode = BAD; z.msg = "invalid bit length repeat"; r = Z_DATA_ERROR; bitb=b; bitk=k; z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; return inflate_flush(z,r); } c = c == 16 ? blens[i-1] : 0; do{ blens[i++] = c; } while (--j!=0); index = i; } } tb[0]=-1; { int[] bl=new int[1]; int[] bd=new int[1]; int[] tl=new int[1]; int[] td=new int[1]; bl[0] = 9; // must be <= 9 for lookahead assumptions bd[0] = 6; // must be <= 9 for lookahead assumptions t = table; t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f), blens, bl, bd, tl, td, hufts, z); if (t != Z_OK){ if (t == Z_DATA_ERROR){ blens=null; mode = BAD; } r = t; bitb=b; bitk=k; z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; return inflate_flush(z,r); } codes.init(bl[0], bd[0], hufts, tl[0], hufts, td[0], z); } mode = CODES; goto case CODES; case CODES: bitb=b; bitk=k; z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; if ((r = codes.proc(this, z, r)) != Z_STREAM_END){ return inflate_flush(z, r); } r = Z_OK; codes.free(z); p=z.next_in_index; n=z.avail_in;b=bitb;k=bitk; q=write;m=(int)(q<read?read-q-1:end-q); if (last==0){ mode = TYPE; break; } mode = DRY; goto case DRY; case DRY: write=q; r=inflate_flush(z, r); q=write; m=(int)(q<read?read-q-1:end-q); if (read != write){ bitb=b; bitk=k; z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; return inflate_flush(z, r); } mode = DONE; goto case DONE; case DONE: r = Z_STREAM_END; bitb=b; bitk=k; z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; return inflate_flush(z, r); case BAD: r = Z_DATA_ERROR; bitb=b; bitk=k; z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; return inflate_flush(z, r); default: r = Z_STREAM_ERROR; bitb=b; bitk=k; z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p; write=q; return inflate_flush(z, r); } } }
internal int deflate(ZStream strm, int flush){ int old_flush; if(flush>Z_FINISH || flush<0){ return Z_STREAM_ERROR; } if(strm.next_out == null || (strm.next_in == null && strm.avail_in != 0) || (status == FINISH_STATE && flush != Z_FINISH)) { strm.msg=z_errmsg[Z_NEED_DICT-(Z_STREAM_ERROR)]; return Z_STREAM_ERROR; } if(strm.avail_out == 0){ strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; return Z_BUF_ERROR; } this.strm = strm; // just in case old_flush = last_flush; last_flush = flush; // Write the zlib header if(status == INIT_STATE) { int header = (Z_DEFLATED+((w_bits-8)<<4))<<8; int level_flags=((level-1)&0xff)>>1; if(level_flags>3) level_flags=3; header |= (level_flags<<6); if(strstart!=0) header |= PRESET_DICT; header+=31-(header % 31); status=BUSY_STATE; putShortMSB(header); // Save the adler32 of the preset dictionary: if(strstart!=0){ putShortMSB((int)(strm.adler>>16)); putShortMSB((int)(strm.adler&0xffff)); } strm.adler=strm._adler.adler32(0, null, 0, 0); } // Flush as much pending output as possible if(pending != 0) { strm.flush_pending(); if(strm.avail_out == 0) { //System.out.println(" avail_out==0"); // Since avail_out is 0, deflate will be called again with // more output space, but possibly with both pending and // avail_in equal to zero. There won't be anything to do, // but this is not an error situation so make sure we // return OK instead of BUF_ERROR at next call of deflate: last_flush = -1; return Z_OK; } // Make sure there is something to do and avoid duplicate consecutive // flushes. For repeated and useless calls with Z_FINISH, we keep // returning Z_STREAM_END instead of Z_BUFF_ERROR. } else if(strm.avail_in==0 && flush <= old_flush && flush != Z_FINISH) { strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; return Z_BUF_ERROR; } // User must not provide more input after the first FINISH: if(status == FINISH_STATE && strm.avail_in != 0) { strm.msg=z_errmsg[Z_NEED_DICT-(Z_BUF_ERROR)]; return Z_BUF_ERROR; } // Start a new block or continue the current one. if(strm.avail_in!=0 || lookahead!=0 || (flush != Z_NO_FLUSH && status != FINISH_STATE)) { int bstate=-1; switch(config_table[level].func){ case STORED: bstate = deflate_stored(flush); break; case FAST: bstate = deflate_fast(flush); break; case SLOW: bstate = deflate_slow(flush); break; default: break; } if (bstate==FinishStarted || bstate==FinishDone) { status = FINISH_STATE; } if (bstate==NeedMore || bstate==FinishStarted) { if(strm.avail_out == 0) { last_flush = -1; // avoid BUF_ERROR next call, see above } return Z_OK; // If flush != Z_NO_FLUSH && avail_out == 0, the next call // of deflate should use the same flush parameter to make sure // that the flush is complete. So we don't have to output an // empty block here, this will be done at next call. This also // ensures that for a very small output buffer, we emit at most // one empty block. } if (bstate==BlockDone) { if(flush == Z_PARTIAL_FLUSH) { _tr_align(); } else { // FULL_FLUSH or SYNC_FLUSH _tr_stored_block(0, 0, false); // For a full flush, this empty block will be recognized // as a special marker by inflate_sync(). if(flush == Z_FULL_FLUSH) { //state.head[s.hash_size-1]=0; for(int i=0; i<hash_size/*-1*/; i++) // forget history head[i]=0; } } strm.flush_pending(); if(strm.avail_out == 0) { last_flush = -1; // avoid BUF_ERROR at next call, see above return Z_OK; } } } if(flush!=Z_FINISH) return Z_OK; if(noheader!=0) return Z_STREAM_END; // Write the zlib trailer (adler32) putShortMSB((int)(strm.adler>>16)); putShortMSB((int)(strm.adler&0xffff)); strm.flush_pending(); // If avail_out is zero, the application will call deflate again // to flush the rest. noheader = -1; // write the trailer only once! return pending != 0 ? Z_OK : Z_STREAM_END; }
// copy as much as possible from the sliding window to the output area internal int inflate_flush(ZStream z, int r){ int n; int p; int q; // local copies of source and destination pointers p = z.next_out_index; q = read; // compute number of bytes to copy as far as end of window n = (int)((q <= write ? write : end) - q); if (n > z.avail_out) n = z.avail_out; if (n!=0 && r == Z_BUF_ERROR) r = Z_OK; // update counters z.avail_out -= n; z.total_out += n; // update check information if(checkfn != null) z.adler=check=z._adler.adler32(check, window, q, n); // copy as far as end of window System.Array.Copy(window, q, z.next_out, p, n); p += n; q += n; // see if more to copy at beginning of window if (q == end){ // wrap pointers q = 0; if (write == end) write = 0; // compute bytes to copy n = write - q; if (n > z.avail_out) n = z.avail_out; if (n!=0 && r == Z_BUF_ERROR) r = Z_OK; // update counters z.avail_out -= n; z.total_out += n; // update check information if(checkfn != null) z.adler=check=z._adler.adler32(check, window, q, n); // copy System.Array.Copy(window, q, z.next_out, p, n); p += n; q += n; } // update pointers z.next_out_index = p; read = q; // done return r; }
internal int inflateEnd(ZStream z){ if(blocks != null) blocks.free(z); blocks=null; // ZFREE(z, z->state); return Z_OK; }