emul/mini/src/main/java/org/apidesign/bck2brwsr/emul/zip/InfCodes.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.
     1 /* -*-mode:java; c-basic-offset:2; -*- */
     2 /*
     3 Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.
     4 
     5 Redistribution and use in source and binary forms, with or without
     6 modification, are permitted provided that the following conditions are met:
     7 
     8   1. Redistributions of source code must retain the above copyright notice,
     9      this list of conditions and the following disclaimer.
    10 
    11   2. Redistributions in binary form must reproduce the above copyright 
    12      notice, this list of conditions and the following disclaimer in 
    13      the documentation and/or other materials provided with the distribution.
    14 
    15   3. The names of the authors may not be used to endorse or promote products
    16      derived from this software without specific prior written permission.
    17 
    18 THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
    19 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
    20 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,
    21 INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,
    22 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    23 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
    24 OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
    25 LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
    26 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
    27 EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    28  */
    29 /*
    30  * This program is based on zlib-1.1.3, so all credit should go authors
    31  * Jean-loup Gailly(jloup@gzip.org) and Mark Adler(madler@alumni.caltech.edu)
    32  * and contributors of zlib.
    33  */
    34 
    35 package org.apidesign.bck2brwsr.emul.zip;
    36 
    37 import org.apidesign.bck2brwsr.emul.lang.System;
    38 
    39 final class InfCodes{
    40 
    41   static final private int[] inflate_mask = {
    42     0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
    43     0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,
    44     0x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,
    45     0x00007fff, 0x0000ffff
    46   };
    47 
    48   static final private int Z_OK=0;
    49   static final private int Z_STREAM_END=1;
    50   static final private int Z_NEED_DICT=2;
    51   static final private int Z_ERRNO=-1;
    52   static final private int Z_STREAM_ERROR=-2;
    53   static final private int Z_DATA_ERROR=-3;
    54   static final private int Z_MEM_ERROR=-4;
    55   static final private int Z_BUF_ERROR=-5;
    56   static final private int Z_VERSION_ERROR=-6;
    57 
    58   // waiting for "i:"=input,
    59   //             "o:"=output,
    60   //             "x:"=nothing
    61   static final private int START=0;  // x: set up for LEN
    62   static final private int LEN=1;    // i: get length/literal/eob next
    63   static final private int LENEXT=2; // i: getting length extra (have base)
    64   static final private int DIST=3;   // i: get distance next
    65   static final private int DISTEXT=4;// i: getting distance extra
    66   static final private int COPY=5;   // o: copying bytes in window, waiting for space
    67   static final private int LIT=6;    // o: got literal, waiting for output space
    68   static final private int WASH=7;   // o: got eob, possibly still output waiting
    69   static final private int END=8;    // x: got eob and all data flushed
    70   static final private int BADCODE=9;// x: got error
    71 
    72   int mode;      // current inflate_codes mode
    73 
    74   // mode dependent information
    75   int len;
    76 
    77   int[] tree; // pointer into tree
    78   int tree_index=0;
    79   int need;   // bits needed
    80 
    81   int lit;
    82 
    83   // if EXT or COPY, where and how much
    84   int get;              // bits to get for extra
    85   int dist;             // distance back to copy from
    86 
    87   byte lbits;           // ltree bits decoded per branch
    88   byte dbits;           // dtree bits decoder per branch
    89   int[] ltree;          // literal/length/eob tree
    90   int ltree_index;      // literal/length/eob tree
    91   int[] dtree;          // distance tree
    92   int dtree_index;      // distance tree
    93 
    94   private final ZStream z;
    95   private final InfBlocks s;
    96   InfCodes(ZStream z, InfBlocks s){
    97     this.z=z; 
    98     this.s=s; 
    99   }
   100 
   101   void init(int bl, int bd,
   102 	   int[] tl, int tl_index,
   103 	   int[] td, int td_index){
   104     mode=START;
   105     lbits=(byte)bl;
   106     dbits=(byte)bd;
   107     ltree=tl;
   108     ltree_index=tl_index;
   109     dtree = td;
   110     dtree_index=td_index;
   111     tree=null;
   112   }
   113 
   114   int proc(int r){ 
   115     int j;              // temporary storage
   116     int[] t;            // temporary pointer
   117     int tindex;         // temporary pointer
   118     int e;              // extra bits or operation
   119     int b=0;            // bit buffer
   120     int k=0;            // bits in bit buffer
   121     int p=0;            // input data pointer
   122     int n;              // bytes available there
   123     int q;              // output window write pointer
   124     int m;              // bytes to end of window or read pointer
   125     int f;              // pointer to copy strings from
   126 
   127     // copy input/output information to locals (UPDATE macro restores)
   128     p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
   129     q=s.write;m=q<s.read?s.read-q-1:s.end-q;
   130 
   131     // process input and output based on current state
   132     while (true){
   133       switch (mode){
   134 	// waiting for "i:"=input, "o:"=output, "x:"=nothing
   135       case START:         // x: set up for LEN
   136 	if (m >= 258 && n >= 10){
   137 
   138 	  s.bitb=b;s.bitk=k;
   139 	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
   140 	  s.write=q;
   141 	  r = inflate_fast(lbits, dbits, 
   142 			   ltree, ltree_index, 
   143 			   dtree, dtree_index,
   144 			   s, z);
   145 
   146 	  p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
   147 	  q=s.write;m=q<s.read?s.read-q-1:s.end-q;
   148 
   149 	  if (r != Z_OK){
   150 	    mode = r == Z_STREAM_END ? WASH : BADCODE;
   151 	    break;
   152 	  }
   153 	}
   154 	need = lbits;
   155 	tree = ltree;
   156 	tree_index=ltree_index;
   157 
   158 	mode = LEN;
   159       case LEN:           // i: get length/literal/eob next
   160 	j = need;
   161 
   162 	while(k<(j)){
   163 	  if(n!=0)r=Z_OK;
   164 	  else{
   165 
   166 	    s.bitb=b;s.bitk=k;
   167 	    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
   168 	    s.write=q;
   169 	    return s.inflate_flush(r);
   170 	  }
   171 	  n--;
   172 	  b|=(z.next_in[p++]&0xff)<<k;
   173 	  k+=8;
   174 	}
   175 
   176 	tindex=(tree_index+(b&inflate_mask[j]))*3;
   177 
   178 	b>>>=(tree[tindex+1]);
   179 	k-=(tree[tindex+1]);
   180 
   181 	e=tree[tindex];
   182 
   183 	if(e == 0){               // literal
   184 	  lit = tree[tindex+2];
   185 	  mode = LIT;
   186 	  break;
   187 	}
   188 	if((e & 16)!=0 ){          // length
   189 	  get = e & 15;
   190 	  len = tree[tindex+2];
   191 	  mode = LENEXT;
   192 	  break;
   193 	}
   194 	if ((e & 64) == 0){        // next table
   195 	  need = e;
   196 	  tree_index = tindex/3+tree[tindex+2];
   197 	  break;
   198 	}
   199 	if ((e & 32)!=0){               // end of block
   200 	  mode = WASH;
   201 	  break;
   202 	}
   203 	mode = BADCODE;        // invalid code
   204 	z.msg = "invalid literal/length code";
   205 	r = Z_DATA_ERROR;
   206 
   207 	s.bitb=b;s.bitk=k;
   208 	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
   209 	s.write=q;
   210 	return s.inflate_flush(r);
   211 
   212       case LENEXT:        // i: getting length extra (have base)
   213 	j = get;
   214 
   215 	while(k<(j)){
   216 	  if(n!=0)r=Z_OK;
   217 	  else{
   218 
   219 	    s.bitb=b;s.bitk=k;
   220 	    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
   221 	    s.write=q;
   222 	    return s.inflate_flush(r);
   223 	  }
   224 	  n--; b|=(z.next_in[p++]&0xff)<<k;
   225 	  k+=8;
   226 	}
   227 
   228 	len += (b & inflate_mask[j]);
   229 
   230 	b>>=j;
   231 	k-=j;
   232 
   233 	need = dbits;
   234 	tree = dtree;
   235 	tree_index=dtree_index;
   236 	mode = DIST;
   237       case DIST:          // i: get distance next
   238 	j = need;
   239 
   240 	while(k<(j)){
   241 	  if(n!=0)r=Z_OK;
   242 	  else{
   243 
   244 	    s.bitb=b;s.bitk=k;
   245 	    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
   246 	    s.write=q;
   247 	    return s.inflate_flush(r);
   248 	  }
   249 	  n--; b|=(z.next_in[p++]&0xff)<<k;
   250 	  k+=8;
   251 	}
   252 
   253 	tindex=(tree_index+(b & inflate_mask[j]))*3;
   254 
   255 	b>>=tree[tindex+1];
   256 	k-=tree[tindex+1];
   257 
   258 	e = (tree[tindex]);
   259 	if((e & 16)!=0){               // distance
   260 	  get = e & 15;
   261 	  dist = tree[tindex+2];
   262 	  mode = DISTEXT;
   263 	  break;
   264 	}
   265 	if ((e & 64) == 0){        // next table
   266 	  need = e;
   267 	  tree_index = tindex/3 + tree[tindex+2];
   268 	  break;
   269 	}
   270 	mode = BADCODE;        // invalid code
   271 	z.msg = "invalid distance code";
   272 	r = Z_DATA_ERROR;
   273 
   274 	s.bitb=b;s.bitk=k;
   275 	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
   276 	s.write=q;
   277 	return s.inflate_flush(r);
   278 
   279       case DISTEXT:       // i: getting distance extra
   280 	j = get;
   281 
   282 	while(k<(j)){
   283 	  if(n!=0)r=Z_OK;
   284 	  else{
   285 
   286 	    s.bitb=b;s.bitk=k;
   287 	    z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
   288 	    s.write=q;
   289 	    return s.inflate_flush(r);
   290 	  }
   291 	  n--; b|=(z.next_in[p++]&0xff)<<k;
   292 	  k+=8;
   293 	}
   294 
   295 	dist += (b & inflate_mask[j]);
   296 
   297 	b>>=j;
   298 	k-=j;
   299 
   300 	mode = COPY;
   301       case COPY:          // o: copying bytes in window, waiting for space
   302         f = q - dist;
   303         while(f < 0){     // modulo window size-"while" instead
   304           f += s.end;     // of "if" handles invalid distances
   305 	}
   306 	while (len!=0){
   307 
   308 	  if(m==0){
   309 	    if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
   310 	    if(m==0){
   311 	      s.write=q; r=s.inflate_flush(r);
   312 	      q=s.write;m=q<s.read?s.read-q-1:s.end-q;
   313 
   314 	      if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
   315 
   316 	      if(m==0){
   317 		s.bitb=b;s.bitk=k;
   318 		z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
   319 		s.write=q;
   320 		return s.inflate_flush(r);
   321 	      }  
   322 	    }
   323 	  }
   324 
   325 	  s.window[q++]=s.window[f++]; m--;
   326 
   327 	  if (f == s.end)
   328             f = 0;
   329 	  len--;
   330 	}
   331 	mode = START;
   332 	break;
   333       case LIT:           // o: got literal, waiting for output space
   334 	if(m==0){
   335 	  if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
   336 	  if(m==0){
   337 	    s.write=q; r=s.inflate_flush(r);
   338 	    q=s.write;m=q<s.read?s.read-q-1:s.end-q;
   339 
   340 	    if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}
   341 	    if(m==0){
   342 	      s.bitb=b;s.bitk=k;
   343 	      z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
   344 	      s.write=q;
   345 	      return s.inflate_flush(r);
   346 	    }
   347 	  }
   348 	}
   349 	r=Z_OK;
   350 
   351 	s.window[q++]=(byte)lit; m--;
   352 
   353 	mode = START;
   354 	break;
   355       case WASH:           // o: got eob, possibly more output
   356 	if (k > 7){        // return unused byte, if any
   357 	  k -= 8;
   358 	  n++;
   359 	  p--;             // can always return one
   360 	}
   361 
   362 	s.write=q; r=s.inflate_flush(r);
   363 	q=s.write;m=q<s.read?s.read-q-1:s.end-q;
   364 
   365 	if (s.read != s.write){
   366 	  s.bitb=b;s.bitk=k;
   367 	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
   368 	  s.write=q;
   369 	  return s.inflate_flush(r);
   370 	}
   371 	mode = END;
   372       case END:
   373 	r = Z_STREAM_END;
   374 	s.bitb=b;s.bitk=k;
   375 	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
   376 	s.write=q;
   377 	return s.inflate_flush(r);
   378 
   379       case BADCODE:       // x: got error
   380 
   381 	r = Z_DATA_ERROR;
   382 
   383 	s.bitb=b;s.bitk=k;
   384 	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
   385 	s.write=q;
   386 	return s.inflate_flush(r);
   387 
   388       default:
   389 	r = Z_STREAM_ERROR;
   390 
   391 	s.bitb=b;s.bitk=k;
   392 	z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
   393 	s.write=q;
   394 	return s.inflate_flush(r);
   395       }
   396     }
   397   }
   398 
   399   void free(ZStream z){
   400     //  ZFREE(z, c);
   401   }
   402 
   403   // Called with number of bytes left to write in window at least 258
   404   // (the maximum string length) and number of input bytes available
   405   // at least ten.  The ten bytes are six bytes for the longest length/
   406   // distance pair plus four bytes for overloading the bit buffer.
   407 
   408   int inflate_fast(int bl, int bd, 
   409 		   int[] tl, int tl_index,
   410 		   int[] td, int td_index,
   411 		   InfBlocks s, ZStream z){
   412     int t;                // temporary pointer
   413     int[] tp;             // temporary pointer
   414     int tp_index;         // temporary pointer
   415     int e;                // extra bits or operation
   416     int b;                // bit buffer
   417     int k;                // bits in bit buffer
   418     int p;                // input data pointer
   419     int n;                // bytes available there
   420     int q;                // output window write pointer
   421     int m;                // bytes to end of window or read pointer
   422     int ml;               // mask for literal/length tree
   423     int md;               // mask for distance tree
   424     int c;                // bytes to copy
   425     int d;                // distance back to copy from
   426     int r;                // copy source pointer
   427 
   428     int tp_index_t_3;     // (tp_index+t)*3
   429 
   430     // load input, output, bit values
   431     p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;
   432     q=s.write;m=q<s.read?s.read-q-1:s.end-q;
   433 
   434     // initialize masks
   435     ml = inflate_mask[bl];
   436     md = inflate_mask[bd];
   437 
   438     // do until not enough input or output space for fast loop
   439     do {                          // assume called with m >= 258 && n >= 10
   440       // get literal/length code
   441       while(k<(20)){              // max bits for literal/length code
   442 	n--;
   443 	b|=(z.next_in[p++]&0xff)<<k;k+=8;
   444       }
   445 
   446       t= b&ml;
   447       tp=tl; 
   448       tp_index=tl_index;
   449       tp_index_t_3=(tp_index+t)*3;
   450       if ((e = tp[tp_index_t_3]) == 0){
   451 	b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
   452 
   453 	s.window[q++] = (byte)tp[tp_index_t_3+2];
   454 	m--;
   455 	continue;
   456       }
   457       do {
   458 
   459 	b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
   460 
   461 	if((e&16)!=0){
   462 	  e &= 15;
   463 	  c = tp[tp_index_t_3+2] + ((int)b & inflate_mask[e]);
   464 
   465 	  b>>=e; k-=e;
   466 
   467 	  // decode distance base of block to copy
   468 	  while(k<(15)){           // max bits for distance code
   469 	    n--;
   470 	    b|=(z.next_in[p++]&0xff)<<k;k+=8;
   471 	  }
   472 
   473 	  t= b&md;
   474 	  tp=td;
   475 	  tp_index=td_index;
   476           tp_index_t_3=(tp_index+t)*3;
   477 	  e = tp[tp_index_t_3];
   478 
   479 	  do {
   480 
   481 	    b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
   482 
   483 	    if((e&16)!=0){
   484 	      // get extra bits to add to distance base
   485 	      e &= 15;
   486 	      while(k<(e)){         // get extra bits (up to 13)
   487 		n--;
   488 		b|=(z.next_in[p++]&0xff)<<k;k+=8;
   489 	      }
   490 
   491 	      d = tp[tp_index_t_3+2] + (b&inflate_mask[e]);
   492 
   493 	      b>>=(e); k-=(e);
   494 
   495 	      // do the copy
   496 	      m -= c;
   497 	      if (q >= d){                // offset before dest
   498 		//  just copy
   499 		r=q-d;
   500 		if(q-r>0 && 2>(q-r)){           
   501 		  s.window[q++]=s.window[r++]; // minimum count is three,
   502 		  s.window[q++]=s.window[r++]; // so unroll loop a little
   503 		  c-=2;
   504 		}
   505 		else{
   506 		  System.arraycopy(s.window, r, s.window, q, 2);
   507 		  q+=2; r+=2; c-=2;
   508 		}
   509 	      }
   510 	      else{                  // else offset after destination
   511                 r=q-d;
   512                 do{
   513                   r+=s.end;          // force pointer in window
   514                 }while(r<0);         // covers invalid distances
   515 		e=s.end-r;
   516 		if(c>e){             // if source crosses,
   517 		  c-=e;              // wrapped copy
   518 		  if(q-r>0 && e>(q-r)){           
   519 		    do{s.window[q++] = s.window[r++];}
   520 		    while(--e!=0);
   521 		  }
   522 		  else{
   523 		    System.arraycopy(s.window, r, s.window, q, e);
   524 		    q+=e; r+=e; e=0;
   525 		  }
   526 		  r = 0;                  // copy rest from start of window
   527 		}
   528 
   529 	      }
   530 
   531 	      // copy all or what's left
   532 	      if(q-r>0 && c>(q-r)){           
   533 		do{s.window[q++] = s.window[r++];}
   534 		while(--c!=0);
   535 	      }
   536 	      else{
   537 		System.arraycopy(s.window, r, s.window, q, c);
   538 		q+=c; r+=c; c=0;
   539 	      }
   540 	      break;
   541 	    }
   542 	    else if((e&64)==0){
   543 	      t+=tp[tp_index_t_3+2];
   544 	      t+=(b&inflate_mask[e]);
   545 	      tp_index_t_3=(tp_index+t)*3;
   546 	      e=tp[tp_index_t_3];
   547 	    }
   548 	    else{
   549 	      z.msg = "invalid distance code";
   550 
   551 	      c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
   552 
   553 	      s.bitb=b;s.bitk=k;
   554 	      z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
   555 	      s.write=q;
   556 
   557 	      return Z_DATA_ERROR;
   558 	    }
   559 	  }
   560 	  while(true);
   561 	  break;
   562 	}
   563 
   564 	if((e&64)==0){
   565 	  t+=tp[tp_index_t_3+2];
   566 	  t+=(b&inflate_mask[e]);
   567 	  tp_index_t_3=(tp_index+t)*3;
   568 	  if((e=tp[tp_index_t_3])==0){
   569 
   570 	    b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);
   571 
   572 	    s.window[q++]=(byte)tp[tp_index_t_3+2];
   573 	    m--;
   574 	    break;
   575 	  }
   576 	}
   577 	else if((e&32)!=0){
   578 
   579 	  c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
   580  
   581 	  s.bitb=b;s.bitk=k;
   582 	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
   583 	  s.write=q;
   584 
   585 	  return Z_STREAM_END;
   586 	}
   587 	else{
   588 	  z.msg="invalid literal/length code";
   589 
   590 	  c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
   591 
   592 	  s.bitb=b;s.bitk=k;
   593 	  z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
   594 	  s.write=q;
   595 
   596 	  return Z_DATA_ERROR;
   597 	}
   598       } 
   599       while(true);
   600     } 
   601     while(m>=258 && n>= 10);
   602 
   603     // not enough input or output--restore pointers and return
   604     c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;
   605 
   606     s.bitb=b;s.bitk=k;
   607     z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;
   608     s.write=q;
   609 
   610     return Z_OK;
   611   }
   612 }