emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/InfBlocks.java
author Jaroslav Tulach <jaroslav.tulach@apidesign.org>
Thu, 07 Feb 2013 12:58:12 +0100
branchemul
changeset 694 0d277415ed02
permissions -rw-r--r--
Rebasing the Inflater support on jzlib which, unlike GNU ClassPath, has correct implementation of Huffman code. Making the implementation more easily testable by turning Inflater and ZipInputStream into pure delegates. Current implementation is going to need proper long support.
jaroslav@694
     1
/* -*-mode:java; c-basic-offset:2; -*- */
jaroslav@694
     2
/*
jaroslav@694
     3
Copyright (c) 2011 ymnk, JCraft,Inc. All rights reserved.
jaroslav@694
     4
jaroslav@694
     5
Redistribution and use in source and binary forms, with or without
jaroslav@694
     6
modification, are permitted provided that the following conditions are met:
jaroslav@694
     7
jaroslav@694
     8
  1. Redistributions of source code must retain the above copyright notice,
jaroslav@694
     9
     this list of conditions and the following disclaimer.
jaroslav@694
    10
jaroslav@694
    11
  2. Redistributions in binary form must reproduce the above copyright 
jaroslav@694
    12
     notice, this list of conditions and the following disclaimer in 
jaroslav@694
    13
     the documentation and/or other materials provided with the distribution.
jaroslav@694
    14
jaroslav@694
    15
  3. The names of the authors may not be used to endorse or promote products
jaroslav@694
    16
     derived from this software without specific prior written permission.
jaroslav@694
    17
jaroslav@694
    18
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
jaroslav@694
    19
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
jaroslav@694
    20
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
jaroslav@694
    21
INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
jaroslav@694
    22
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
jaroslav@694
    23
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
jaroslav@694
    24
OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
jaroslav@694
    25
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
jaroslav@694
    26
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
jaroslav@694
    27
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
jaroslav@694
    28
 */
jaroslav@694
    29
/*
jaroslav@694
    30
 * This program is based on zlib-1.1.3, so all credit should go authors
jaroslav@694
    31
 * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
jaroslav@694
    32
 * and contributors of zlib.
jaroslav@694
    33
 */
jaroslav@694
    34
jaroslav@694
    35
package org.apidesign.bck2brwsr.emul.zip;
jaroslav@694
    36
jaroslav@694
    37
import org.apidesign.bck2brwsr.emul.lang.System;
jaroslav@694
    38
jaroslav@694
    39
final class InfBlocks{
jaroslav@694
    40
  static final private int MANY=1440;
jaroslav@694
    41
jaroslav@694
    42
  // And'ing with mask[n] masks the lower n bits
jaroslav@694
    43
  static final private int[] inflate_mask = {
jaroslav@694
    44
    0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
jaroslav@694
    45
    0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
jaroslav@694
    46
    0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
jaroslav@694
    47
    0x00007fff, 0x0000ffff
jaroslav@694
    48
  };
jaroslav@694
    49
jaroslav@694
    50
  // Table for deflate from PKZIP's appnote.txt.
jaroslav@694
    51
  static final int[] border = { // Order of the bit length code lengths
jaroslav@694
    52
    16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15
jaroslav@694
    53
  };
jaroslav@694
    54
jaroslav@694
    55
  static final private int Z_OK=0;
jaroslav@694
    56
  static final private int Z_STREAM_END=1;
jaroslav@694
    57
  static final private int Z_NEED_DICT=2;
jaroslav@694
    58
  static final private int Z_ERRNO=-1;
jaroslav@694
    59
  static final private int Z_STREAM_ERROR=-2;
jaroslav@694
    60
  static final private int Z_DATA_ERROR=-3;
jaroslav@694
    61
  static final private int Z_MEM_ERROR=-4;
jaroslav@694
    62
  static final private int Z_BUF_ERROR=-5;
jaroslav@694
    63
  static final private int Z_VERSION_ERROR=-6;
jaroslav@694
    64
jaroslav@694
    65
  static final private int TYPE=0;  // get type bits (3, including end bit)
jaroslav@694
    66
  static final private int LENS=1;  // get lengths for stored
jaroslav@694
    67
  static final private int STORED=2;// processing stored block
jaroslav@694
    68
  static final private int TABLE=3; // get table lengths
jaroslav@694
    69
  static final private int BTREE=4; // get bit lengths tree for a dynamic block
jaroslav@694
    70
  static final private int DTREE=5; // get length, distance trees for a dynamic block
jaroslav@694
    71
  static final private int CODES=6; // processing fixed or dynamic block
jaroslav@694
    72
  static final private int DRY=7;   // output remaining window bytes
jaroslav@694
    73
  static final private int DONE=8;  // finished last block, done
jaroslav@694
    74
  static final private int BAD=9;   // ot a data error--stuck here
jaroslav@694
    75
jaroslav@694
    76
  int mode;            // current inflate_block mode 
jaroslav@694
    77
jaroslav@694
    78
  int left;            // if STORED, bytes left to copy 
jaroslav@694
    79
jaroslav@694
    80
  int table;           // table lengths (14 bits) 
jaroslav@694
    81
  int index;           // index into blens (or border) 
jaroslav@694
    82
  int[] blens;         // bit lengths of codes 
jaroslav@694
    83
  int[] bb=new int[1]; // bit length tree depth 
jaroslav@694
    84
  int[] tb=new int[1]; // bit length decoding tree 
jaroslav@694
    85
jaroslav@694
    86
  int[] bl=new int[1];
jaroslav@694
    87
  int[] bd=new int[1];
jaroslav@694
    88
jaroslav@694
    89
  int[][] tl=new int[1][];
jaroslav@694
    90
  int[][] td=new int[1][];
jaroslav@694
    91
  int[] tli=new int[1]; // tl_index
jaroslav@694
    92
  int[] tdi=new int[1]; // td_index
jaroslav@694
    93
jaroslav@694
    94
  private final InfCodes codes;      // if CODES, current state 
jaroslav@694
    95
jaroslav@694
    96
  int last;            // true if this block is the last block 
jaroslav@694
    97
jaroslav@694
    98
  // mode independent information 
jaroslav@694
    99
  int bitk;            // bits in bit buffer 
jaroslav@694
   100
  int bitb;            // bit buffer 
jaroslav@694
   101
  int[] hufts;         // single malloc for tree space 
jaroslav@694
   102
  byte[] window;       // sliding window 
jaroslav@694
   103
  int end;             // one byte after sliding window 
jaroslav@694
   104
  int read;            // window read pointer 
jaroslav@694
   105
  int write;           // window write pointer 
jaroslav@694
   106
  private boolean check;
jaroslav@694
   107
jaroslav@694
   108
  private final InfTree inftree=new InfTree();
jaroslav@694
   109
jaroslav@694
   110
  private final ZStream z; 
jaroslav@694
   111
jaroslav@694
   112
  InfBlocks(ZStream z, int w){
jaroslav@694
   113
    this.z=z;
jaroslav@694
   114
    this.codes=new InfCodes(this.z, this);
jaroslav@694
   115
    hufts=new int[MANY*3];
jaroslav@694
   116
    window=new byte[w];
jaroslav@694
   117
    end=w;
jaroslav@694
   118
    this.check = (z.istate.wrap==0) ? false : true;
jaroslav@694
   119
    mode = TYPE;
jaroslav@694
   120
    reset();
jaroslav@694
   121
  }
jaroslav@694
   122
jaroslav@694
   123
  void reset(){
jaroslav@694
   124
    if(mode==BTREE || mode==DTREE){
jaroslav@694
   125
    }
jaroslav@694
   126
    if(mode==CODES){
jaroslav@694
   127
      codes.free(z);
jaroslav@694
   128
    }
jaroslav@694
   129
    mode=TYPE;
jaroslav@694
   130
    bitk=0;
jaroslav@694
   131
    bitb=0;
jaroslav@694
   132
    read=write=0;
jaroslav@694
   133
    if(check){
jaroslav@694
   134
      z.adler.reset();
jaroslav@694
   135
    }
jaroslav@694
   136
  }
jaroslav@694
   137
jaroslav@694
   138
  int proc(int r){
jaroslav@694
   139
    int t;              // temporary storage
jaroslav@694
   140
    int b;              // bit buffer
jaroslav@694
   141
    int k;              // bits in bit buffer
jaroslav@694
   142
    int p;              // input data pointer
jaroslav@694
   143
    int n;              // bytes available there
jaroslav@694
   144
    int q;              // output window write pointer
jaroslav@694
   145
    int m;              // bytes to end of window or read pointer
jaroslav@694
   146
jaroslav@694
   147
    // copy input/output information to locals (UPDATE macro restores)
jaroslav@694
   148
    {p=z.next_in_index;n=z.avail_in;b=bitb;k=bitk;}
jaroslav@694
   149
    {q=write;m=(int)(q<read?read-q-1:end-q);}
jaroslav@694
   150
jaroslav@694
   151
    // process input based on current state
jaroslav@694
   152
    while(true){
jaroslav@694
   153
      switch (mode){
jaroslav@694
   154
      case TYPE:
jaroslav@694
   155
jaroslav@694
   156
	while(k<(3)){
jaroslav@694
   157
	  if(n!=0){
jaroslav@694
   158
	    r=Z_OK;
jaroslav@694
   159
	  }
jaroslav@694
   160
	  else{
jaroslav@694
   161
	    bitb=b; bitk=k; 
jaroslav@694
   162
	    z.avail_in=n;
jaroslav@694
   163
	    z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   164
	    write=q;
jaroslav@694
   165
	    return inflate_flush(r);
jaroslav@694
   166
	  };
jaroslav@694
   167
	  n--;
jaroslav@694
   168
	  b|=(z.next_in[p++]&0xff)<<k;
jaroslav@694
   169
	  k+=8;
jaroslav@694
   170
	}
jaroslav@694
   171
	t = (int)(b & 7);
jaroslav@694
   172
	last = t & 1;
jaroslav@694
   173
jaroslav@694
   174
	switch (t >>> 1){
jaroslav@694
   175
        case 0:                         // stored 
jaroslav@694
   176
          {b>>>=(3);k-=(3);}
jaroslav@694
   177
          t = k & 7;                    // go to byte boundary
jaroslav@694
   178
jaroslav@694
   179
          {b>>>=(t);k-=(t);}
jaroslav@694
   180
          mode = LENS;                  // get length of stored block
jaroslav@694
   181
          break;
jaroslav@694
   182
        case 1:                         // fixed
jaroslav@694
   183
          InfTree.inflate_trees_fixed(bl, bd, tl, td, z);
jaroslav@694
   184
          codes.init(bl[0], bd[0], tl[0], 0, td[0], 0);
jaroslav@694
   185
jaroslav@694
   186
          {b>>>=(3);k-=(3);}
jaroslav@694
   187
jaroslav@694
   188
          mode = CODES;
jaroslav@694
   189
          break;
jaroslav@694
   190
        case 2:                         // dynamic
jaroslav@694
   191
jaroslav@694
   192
          {b>>>=(3);k-=(3);}
jaroslav@694
   193
jaroslav@694
   194
          mode = TABLE;
jaroslav@694
   195
          break;
jaroslav@694
   196
        case 3:                         // illegal
jaroslav@694
   197
jaroslav@694
   198
          {b>>>=(3);k-=(3);}
jaroslav@694
   199
          mode = BAD;
jaroslav@694
   200
          z.msg = "invalid block type";
jaroslav@694
   201
          r = Z_DATA_ERROR;
jaroslav@694
   202
jaroslav@694
   203
	  bitb=b; bitk=k; 
jaroslav@694
   204
	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   205
	  write=q;
jaroslav@694
   206
	  return inflate_flush(r);
jaroslav@694
   207
	}
jaroslav@694
   208
	break;
jaroslav@694
   209
      case LENS:
jaroslav@694
   210
jaroslav@694
   211
	while(k<(32)){
jaroslav@694
   212
	  if(n!=0){
jaroslav@694
   213
	    r=Z_OK;
jaroslav@694
   214
	  }
jaroslav@694
   215
	  else{
jaroslav@694
   216
	    bitb=b; bitk=k; 
jaroslav@694
   217
	    z.avail_in=n;
jaroslav@694
   218
	    z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   219
	    write=q;
jaroslav@694
   220
	    return inflate_flush(r);
jaroslav@694
   221
	  };
jaroslav@694
   222
	  n--;
jaroslav@694
   223
	  b|=(z.next_in[p++]&0xff)<<k;
jaroslav@694
   224
	  k+=8;
jaroslav@694
   225
	}
jaroslav@694
   226
jaroslav@694
   227
	if ((((~b) >>> 16) & 0xffff) != (b & 0xffff)){
jaroslav@694
   228
	  mode = BAD;
jaroslav@694
   229
	  z.msg = "invalid stored block lengths";
jaroslav@694
   230
	  r = Z_DATA_ERROR;
jaroslav@694
   231
jaroslav@694
   232
	  bitb=b; bitk=k; 
jaroslav@694
   233
	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   234
	  write=q;
jaroslav@694
   235
	  return inflate_flush(r);
jaroslav@694
   236
	}
jaroslav@694
   237
	left = (b & 0xffff);
jaroslav@694
   238
	b = k = 0;                       // dump bits
jaroslav@694
   239
	mode = left!=0 ? STORED : (last!=0 ? DRY : TYPE);
jaroslav@694
   240
	break;
jaroslav@694
   241
      case STORED:
jaroslav@694
   242
	if (n == 0){
jaroslav@694
   243
	  bitb=b; bitk=k; 
jaroslav@694
   244
	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   245
	  write=q;
jaroslav@694
   246
	  return inflate_flush(r);
jaroslav@694
   247
	}
jaroslav@694
   248
jaroslav@694
   249
	if(m==0){
jaroslav@694
   250
	  if(q==end&&read!=0){
jaroslav@694
   251
	    q=0; m=(int)(q<read?read-q-1:end-q);
jaroslav@694
   252
	  }
jaroslav@694
   253
	  if(m==0){
jaroslav@694
   254
	    write=q; 
jaroslav@694
   255
	    r=inflate_flush(r);
jaroslav@694
   256
	    q=write;m=(int)(q<read?read-q-1:end-q);
jaroslav@694
   257
	    if(q==end&&read!=0){
jaroslav@694
   258
	      q=0; m=(int)(q<read?read-q-1:end-q);
jaroslav@694
   259
	    }
jaroslav@694
   260
	    if(m==0){
jaroslav@694
   261
	      bitb=b; bitk=k; 
jaroslav@694
   262
	      z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   263
	      write=q;
jaroslav@694
   264
	      return inflate_flush(r);
jaroslav@694
   265
	    }
jaroslav@694
   266
	  }
jaroslav@694
   267
	}
jaroslav@694
   268
	r=Z_OK;
jaroslav@694
   269
jaroslav@694
   270
	t = left;
jaroslav@694
   271
	if(t>n) t = n;
jaroslav@694
   272
	if(t>m) t = m;
jaroslav@694
   273
	System.arraycopy(z.next_in, p, window, q, t);
jaroslav@694
   274
	p += t;  n -= t;
jaroslav@694
   275
	q += t;  m -= t;
jaroslav@694
   276
	if ((left -= t) != 0)
jaroslav@694
   277
	  break;
jaroslav@694
   278
	mode = last!=0 ? DRY : TYPE;
jaroslav@694
   279
	break;
jaroslav@694
   280
      case TABLE:
jaroslav@694
   281
jaroslav@694
   282
	while(k<(14)){
jaroslav@694
   283
	  if(n!=0){
jaroslav@694
   284
	    r=Z_OK;
jaroslav@694
   285
	  }
jaroslav@694
   286
	  else{
jaroslav@694
   287
	    bitb=b; bitk=k; 
jaroslav@694
   288
	    z.avail_in=n;
jaroslav@694
   289
	    z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   290
	    write=q;
jaroslav@694
   291
	    return inflate_flush(r);
jaroslav@694
   292
	  };
jaroslav@694
   293
	  n--;
jaroslav@694
   294
	  b|=(z.next_in[p++]&0xff)<<k;
jaroslav@694
   295
	  k+=8;
jaroslav@694
   296
	}
jaroslav@694
   297
jaroslav@694
   298
	table = t = (b & 0x3fff);
jaroslav@694
   299
	if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
jaroslav@694
   300
	  {
jaroslav@694
   301
	    mode = BAD;
jaroslav@694
   302
	    z.msg = "too many length or distance symbols";
jaroslav@694
   303
	    r = Z_DATA_ERROR;
jaroslav@694
   304
jaroslav@694
   305
	    bitb=b; bitk=k; 
jaroslav@694
   306
	    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   307
	    write=q;
jaroslav@694
   308
	    return inflate_flush(r);
jaroslav@694
   309
	  }
jaroslav@694
   310
	t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
jaroslav@694
   311
	if(blens==null || blens.length<t){
jaroslav@694
   312
	  blens=new int[t];
jaroslav@694
   313
	}
jaroslav@694
   314
	else{
jaroslav@694
   315
	  for(int i=0; i<t; i++){blens[i]=0;}
jaroslav@694
   316
	}
jaroslav@694
   317
jaroslav@694
   318
	{b>>>=(14);k-=(14);}
jaroslav@694
   319
jaroslav@694
   320
	index = 0;
jaroslav@694
   321
	mode = BTREE;
jaroslav@694
   322
      case BTREE:
jaroslav@694
   323
	while (index < 4 + (table >>> 10)){
jaroslav@694
   324
	  while(k<(3)){
jaroslav@694
   325
	    if(n!=0){
jaroslav@694
   326
	      r=Z_OK;
jaroslav@694
   327
	    }
jaroslav@694
   328
	    else{
jaroslav@694
   329
	      bitb=b; bitk=k; 
jaroslav@694
   330
	      z.avail_in=n;
jaroslav@694
   331
	      z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   332
	      write=q;
jaroslav@694
   333
	      return inflate_flush(r);
jaroslav@694
   334
	    };
jaroslav@694
   335
	    n--;
jaroslav@694
   336
	    b|=(z.next_in[p++]&0xff)<<k;
jaroslav@694
   337
	    k+=8;
jaroslav@694
   338
	  }
jaroslav@694
   339
jaroslav@694
   340
	  blens[border[index++]] = b&7;
jaroslav@694
   341
jaroslav@694
   342
	  {b>>>=(3);k-=(3);}
jaroslav@694
   343
	}
jaroslav@694
   344
jaroslav@694
   345
	while(index < 19){
jaroslav@694
   346
	  blens[border[index++]] = 0;
jaroslav@694
   347
	}
jaroslav@694
   348
jaroslav@694
   349
	bb[0] = 7;
jaroslav@694
   350
	t = inftree.inflate_trees_bits(blens, bb, tb, hufts, z);
jaroslav@694
   351
	if (t != Z_OK){
jaroslav@694
   352
	  r = t;
jaroslav@694
   353
	  if (r == Z_DATA_ERROR){
jaroslav@694
   354
	    blens=null;
jaroslav@694
   355
	    mode = BAD;
jaroslav@694
   356
	  }
jaroslav@694
   357
jaroslav@694
   358
	  bitb=b; bitk=k; 
jaroslav@694
   359
	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   360
	  write=q;
jaroslav@694
   361
	  return inflate_flush(r);
jaroslav@694
   362
	}
jaroslav@694
   363
jaroslav@694
   364
	index = 0;
jaroslav@694
   365
	mode = DTREE;
jaroslav@694
   366
      case DTREE:
jaroslav@694
   367
	while (true){
jaroslav@694
   368
	  t = table;
jaroslav@694
   369
	  if(!(index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))){
jaroslav@694
   370
	    break;
jaroslav@694
   371
	  }
jaroslav@694
   372
jaroslav@694
   373
	  int[] h;
jaroslav@694
   374
	  int i, j, c;
jaroslav@694
   375
jaroslav@694
   376
	  t = bb[0];
jaroslav@694
   377
jaroslav@694
   378
	  while(k<(t)){
jaroslav@694
   379
	    if(n!=0){
jaroslav@694
   380
	      r=Z_OK;
jaroslav@694
   381
	    }
jaroslav@694
   382
	    else{
jaroslav@694
   383
	      bitb=b; bitk=k; 
jaroslav@694
   384
	      z.avail_in=n;
jaroslav@694
   385
	      z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   386
	      write=q;
jaroslav@694
   387
	      return inflate_flush(r);
jaroslav@694
   388
	    };
jaroslav@694
   389
	    n--;
jaroslav@694
   390
	    b|=(z.next_in[p++]&0xff)<<k;
jaroslav@694
   391
	    k+=8;
jaroslav@694
   392
	  }
jaroslav@694
   393
jaroslav@694
   394
	  if(tb[0]==-1){
jaroslav@694
   395
            //System.err.println("null...");
jaroslav@694
   396
	  }
jaroslav@694
   397
jaroslav@694
   398
	  t=hufts[(tb[0]+(b&inflate_mask[t]))*3+1];
jaroslav@694
   399
	  c=hufts[(tb[0]+(b&inflate_mask[t]))*3+2];
jaroslav@694
   400
jaroslav@694
   401
	  if (c < 16){
jaroslav@694
   402
	    b>>>=(t);k-=(t);
jaroslav@694
   403
	    blens[index++] = c;
jaroslav@694
   404
	  }
jaroslav@694
   405
	  else { // c == 16..18
jaroslav@694
   406
	    i = c == 18 ? 7 : c - 14;
jaroslav@694
   407
	    j = c == 18 ? 11 : 3;
jaroslav@694
   408
jaroslav@694
   409
	    while(k<(t+i)){
jaroslav@694
   410
	      if(n!=0){
jaroslav@694
   411
		r=Z_OK;
jaroslav@694
   412
	      }
jaroslav@694
   413
	      else{
jaroslav@694
   414
		bitb=b; bitk=k; 
jaroslav@694
   415
		z.avail_in=n;
jaroslav@694
   416
		z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   417
		write=q;
jaroslav@694
   418
		return inflate_flush(r);
jaroslav@694
   419
	      };
jaroslav@694
   420
	      n--;
jaroslav@694
   421
	      b|=(z.next_in[p++]&0xff)<<k;
jaroslav@694
   422
	      k+=8;
jaroslav@694
   423
	    }
jaroslav@694
   424
jaroslav@694
   425
	    b>>>=(t);k-=(t);
jaroslav@694
   426
jaroslav@694
   427
	    j += (b & inflate_mask[i]);
jaroslav@694
   428
jaroslav@694
   429
	    b>>>=(i);k-=(i);
jaroslav@694
   430
jaroslav@694
   431
	    i = index;
jaroslav@694
   432
	    t = table;
jaroslav@694
   433
	    if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
jaroslav@694
   434
		(c == 16 && i < 1)){
jaroslav@694
   435
	      blens=null;
jaroslav@694
   436
	      mode = BAD;
jaroslav@694
   437
	      z.msg = "invalid bit length repeat";
jaroslav@694
   438
	      r = Z_DATA_ERROR;
jaroslav@694
   439
jaroslav@694
   440
	      bitb=b; bitk=k; 
jaroslav@694
   441
	      z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   442
	      write=q;
jaroslav@694
   443
	      return inflate_flush(r);
jaroslav@694
   444
	    }
jaroslav@694
   445
jaroslav@694
   446
	    c = c == 16 ? blens[i-1] : 0;
jaroslav@694
   447
	    do{
jaroslav@694
   448
	      blens[i++] = c;
jaroslav@694
   449
	    }
jaroslav@694
   450
	    while (--j!=0);
jaroslav@694
   451
	    index = i;
jaroslav@694
   452
	  }
jaroslav@694
   453
	}
jaroslav@694
   454
jaroslav@694
   455
	tb[0]=-1;
jaroslav@694
   456
	{
jaroslav@694
   457
	  bl[0] = 9;         // must be <= 9 for lookahead assumptions
jaroslav@694
   458
	  bd[0] = 6;         // must be <= 9 for lookahead assumptions
jaroslav@694
   459
	  t = table;
jaroslav@694
   460
	  t = inftree.inflate_trees_dynamic(257 + (t & 0x1f), 
jaroslav@694
   461
					    1 + ((t >> 5) & 0x1f),
jaroslav@694
   462
					    blens, bl, bd, tli, tdi, hufts, z);
jaroslav@694
   463
jaroslav@694
   464
	  if (t != Z_OK){
jaroslav@694
   465
	    if (t == Z_DATA_ERROR){
jaroslav@694
   466
	      blens=null;
jaroslav@694
   467
	      mode = BAD;
jaroslav@694
   468
	    }
jaroslav@694
   469
	    r = t;
jaroslav@694
   470
jaroslav@694
   471
	    bitb=b; bitk=k; 
jaroslav@694
   472
	    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   473
	    write=q;
jaroslav@694
   474
	    return inflate_flush(r);
jaroslav@694
   475
	  }
jaroslav@694
   476
	  codes.init(bl[0], bd[0], hufts, tli[0], hufts, tdi[0]);
jaroslav@694
   477
	}
jaroslav@694
   478
	mode = CODES;
jaroslav@694
   479
      case CODES:
jaroslav@694
   480
	bitb=b; bitk=k;
jaroslav@694
   481
	z.avail_in=n; z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   482
	write=q;
jaroslav@694
   483
jaroslav@694
   484
	if ((r = codes.proc(r)) != Z_STREAM_END){
jaroslav@694
   485
	  return inflate_flush(r);
jaroslav@694
   486
	}
jaroslav@694
   487
	r = Z_OK;
jaroslav@694
   488
	codes.free(z);
jaroslav@694
   489
jaroslav@694
   490
	p=z.next_in_index; n=z.avail_in;b=bitb;k=bitk;
jaroslav@694
   491
	q=write;m=(int)(q<read?read-q-1:end-q);
jaroslav@694
   492
jaroslav@694
   493
	if (last==0){
jaroslav@694
   494
	  mode = TYPE;
jaroslav@694
   495
	  break;
jaroslav@694
   496
	}
jaroslav@694
   497
	mode = DRY;
jaroslav@694
   498
      case DRY:
jaroslav@694
   499
	write=q; 
jaroslav@694
   500
	r=inflate_flush(r); 
jaroslav@694
   501
	q=write; m=(int)(q<read?read-q-1:end-q);
jaroslav@694
   502
	if (read != write){
jaroslav@694
   503
	  bitb=b; bitk=k; 
jaroslav@694
   504
	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   505
	  write=q;
jaroslav@694
   506
	  return inflate_flush(r);
jaroslav@694
   507
	}
jaroslav@694
   508
	mode = DONE;
jaroslav@694
   509
      case DONE:
jaroslav@694
   510
	r = Z_STREAM_END;
jaroslav@694
   511
jaroslav@694
   512
	bitb=b; bitk=k; 
jaroslav@694
   513
	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   514
	write=q;
jaroslav@694
   515
	return inflate_flush(r);
jaroslav@694
   516
      case BAD:
jaroslav@694
   517
	r = Z_DATA_ERROR;
jaroslav@694
   518
jaroslav@694
   519
	bitb=b; bitk=k; 
jaroslav@694
   520
	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   521
	write=q;
jaroslav@694
   522
	return inflate_flush(r);
jaroslav@694
   523
jaroslav@694
   524
      default:
jaroslav@694
   525
	r = Z_STREAM_ERROR;
jaroslav@694
   526
jaroslav@694
   527
	bitb=b; bitk=k; 
jaroslav@694
   528
	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
jaroslav@694
   529
	write=q;
jaroslav@694
   530
	return inflate_flush(r);
jaroslav@694
   531
      }
jaroslav@694
   532
    }
jaroslav@694
   533
  }
jaroslav@694
   534
jaroslav@694
   535
  void free(){
jaroslav@694
   536
    reset();
jaroslav@694
   537
    window=null;
jaroslav@694
   538
    hufts=null;
jaroslav@694
   539
    //ZFREE(z, s);
jaroslav@694
   540
  }
jaroslav@694
   541
jaroslav@694
   542
  void set_dictionary(byte[] d, int start, int n){
jaroslav@694
   543
    System.arraycopy(d, start, window, 0, n);
jaroslav@694
   544
    read = write = n;
jaroslav@694
   545
  }
jaroslav@694
   546
jaroslav@694
   547
  // Returns true if inflate is currently at the end of a block generated
jaroslav@694
   548
  // by Z_SYNC_FLUSH or Z_FULL_FLUSH. 
jaroslav@694
   549
  int sync_point(){
jaroslav@694
   550
    return mode == LENS ? 1 : 0;
jaroslav@694
   551
  }
jaroslav@694
   552
jaroslav@694
   553
  // copy as much as possible from the sliding window to the output area
jaroslav@694
   554
  int inflate_flush(int r){
jaroslav@694
   555
    int n;
jaroslav@694
   556
    int p;
jaroslav@694
   557
    int q;
jaroslav@694
   558
jaroslav@694
   559
    // local copies of source and destination pointers
jaroslav@694
   560
    p = z.next_out_index;
jaroslav@694
   561
    q = read;
jaroslav@694
   562
jaroslav@694
   563
    // compute number of bytes to copy as far as end of window
jaroslav@694
   564
    n = (int)((q <= write ? write : end) - q);
jaroslav@694
   565
    if(n > z.avail_out) n = z.avail_out;
jaroslav@694
   566
    if(n!=0 && r == Z_BUF_ERROR) r = Z_OK;
jaroslav@694
   567
jaroslav@694
   568
    // update counters
jaroslav@694
   569
    z.avail_out -= n;
jaroslav@694
   570
    z.total_out += n;
jaroslav@694
   571
jaroslav@694
   572
    // update check information
jaroslav@694
   573
    if(check && n>0){
jaroslav@694
   574
      z.adler.update(window, q, n);
jaroslav@694
   575
    }
jaroslav@694
   576
jaroslav@694
   577
    // copy as far as end of window
jaroslav@694
   578
    System.arraycopy(window, q, z.next_out, p, n);
jaroslav@694
   579
    p += n;
jaroslav@694
   580
    q += n;
jaroslav@694
   581
jaroslav@694
   582
    // see if more to copy at beginning of window
jaroslav@694
   583
    if (q == end){
jaroslav@694
   584
      // wrap pointers
jaroslav@694
   585
      q = 0;
jaroslav@694
   586
      if (write == end)
jaroslav@694
   587
        write = 0;
jaroslav@694
   588
jaroslav@694
   589
      // compute bytes to copy
jaroslav@694
   590
      n = write - q;
jaroslav@694
   591
      if (n > z.avail_out) n = z.avail_out;
jaroslav@694
   592
      if (n!=0 && r == Z_BUF_ERROR) r = Z_OK;
jaroslav@694
   593
jaroslav@694
   594
      // update counters
jaroslav@694
   595
      z.avail_out -= n;
jaroslav@694
   596
      z.total_out += n;
jaroslav@694
   597
jaroslav@694
   598
      // update check information
jaroslav@694
   599
      if(check && n>0){
jaroslav@694
   600
	z.adler.update(window, q, n);
jaroslav@694
   601
      }
jaroslav@694
   602
jaroslav@694
   603
      // copy
jaroslav@694
   604
      System.arraycopy(window, q, z.next_out, p, n);
jaroslav@694
   605
      p += n;
jaroslav@694
   606
      q += n;
jaroslav@694
   607
    }
jaroslav@694
   608
jaroslav@694
   609
    // update pointers
jaroslav@694
   610
    z.next_out_index = p;
jaroslav@694
   611
    read = q;
jaroslav@694
   612
jaroslav@694
   613
    // done
jaroslav@694
   614
    return r;
jaroslav@694
   615
  }
jaroslav@694
   616
}