Path: blob/main/src/lwjgl/java/com/jcraft/jzlib/InfCodes.java
8650 views
/* -*-mode:java; c-basic-offset:2; -*- */1/*2Copyright (c) 2000,2001,2002,2003 ymnk, JCraft,Inc. All rights reserved.34Redistribution and use in source and binary forms, with or without5modification, are permitted provided that the following conditions are met:671. Redistributions of source code must retain the above copyright notice,8this list of conditions and the following disclaimer.9102. Redistributions in binary form must reproduce the above copyright11notice, this list of conditions and the following disclaimer in12the documentation and/or other materials provided with the distribution.13143. The names of the authors may not be used to endorse or promote products15derived from this software without specific prior written permission.1617THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,18INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND19FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL JCRAFT,20INC. OR ANY CONTRIBUTORS TO THIS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT,21INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT22LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,23OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF24LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING25NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,26EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.27*/28/*29* This program is based on zlib-1.1.3, so all credit should go authors30* Jean-loup Gailly([email protected]) and Mark Adler([email protected])31* and contributors of zlib.32*/3334package com.jcraft.jzlib;3536final class InfCodes{3738static final private int[] inflate_mask = {390x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000f,400x0000001f, 0x0000003f, 0x0000007f, 0x000000ff, 0x000001ff,410x000003ff, 0x000007ff, 0x00000fff, 0x00001fff, 0x00003fff,420x00007fff, 0x0000ffff43};4445static final private int Z_OK=0;46static final private int Z_STREAM_END=1;47static final private int Z_NEED_DICT=2;48static final private int Z_ERRNO=-1;49static final private int Z_STREAM_ERROR=-2;50static final private int Z_DATA_ERROR=-3;51static final private int Z_MEM_ERROR=-4;52static final private int Z_BUF_ERROR=-5;53static final private int Z_VERSION_ERROR=-6;5455// waiting for "i:"=input,56// "o:"=output,57// "x:"=nothing58static final private int START=0; // x: set up for LEN59static final private int LEN=1; // i: get length/literal/eob next60static final private int LENEXT=2; // i: getting length extra (have base)61static final private int DIST=3; // i: get distance next62static final private int DISTEXT=4;// i: getting distance extra63static final private int COPY=5; // o: copying bytes in window, waiting for space64static final private int LIT=6; // o: got literal, waiting for output space65static final private int WASH=7; // o: got eob, possibly still output waiting66static final private int END=8; // x: got eob and all data flushed67static final private int BADCODE=9;// x: got error6869int mode; // current inflate_codes mode7071// mode dependent information72int len;7374int[] tree; // pointer into tree75int tree_index=0;76int need; // bits needed7778int lit;7980// if EXT or COPY, where and how much81int get; // bits to get for extra82int dist; // distance back to copy from8384byte lbits; // ltree bits decoded per branch85byte dbits; // dtree bits decoder per branch86int[] ltree; // literal/length/eob tree87int ltree_index; // literal/length/eob tree88int[] dtree; // distance tree89int dtree_index; // distance tree9091private final ZStream z;92private final InfBlocks s;93InfCodes(ZStream z, InfBlocks s){94this.z=z;95this.s=s;96}9798void init(int bl, int bd,99int[] tl, int tl_index,100int[] td, int td_index){101mode=START;102lbits=(byte)bl;103dbits=(byte)bd;104ltree=tl;105ltree_index=tl_index;106dtree = td;107dtree_index=td_index;108tree=null;109}110111int proc(int r){112int j; // temporary storage113int[] t; // temporary pointer114int tindex; // temporary pointer115int e; // extra bits or operation116int b=0; // bit buffer117int k=0; // bits in bit buffer118int p=0; // input data pointer119int n; // bytes available there120int q; // output window write pointer121int m; // bytes to end of window or read pointer122int f; // pointer to copy strings from123124// copy input/output information to locals (UPDATE macro restores)125p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;126q=s.write;m=q<s.read?s.read-q-1:s.end-q;127128// process input and output based on current state129while (true){130switch (mode){131// waiting for "i:"=input, "o:"=output, "x:"=nothing132case START: // x: set up for LEN133if (m >= 258 && n >= 10){134135s.bitb=b;s.bitk=k;136z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;137s.write=q;138r = inflate_fast(lbits, dbits,139ltree, ltree_index,140dtree, dtree_index,141s, z);142143p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;144q=s.write;m=q<s.read?s.read-q-1:s.end-q;145146if (r != Z_OK){147mode = r == Z_STREAM_END ? WASH : BADCODE;148break;149}150}151need = lbits;152tree = ltree;153tree_index=ltree_index;154155mode = LEN;156case LEN: // i: get length/literal/eob next157j = need;158159while(k<(j)){160if(n!=0)r=Z_OK;161else{162163s.bitb=b;s.bitk=k;164z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;165s.write=q;166return s.inflate_flush(r);167}168n--;169b|=(z.next_in[p++]&0xff)<<k;170k+=8;171}172173tindex=(tree_index+(b&inflate_mask[j]))*3;174175b>>>=(tree[tindex+1]);176k-=(tree[tindex+1]);177178e=tree[tindex];179180if(e == 0){ // literal181lit = tree[tindex+2];182mode = LIT;183break;184}185if((e & 16)!=0 ){ // length186get = e & 15;187len = tree[tindex+2];188mode = LENEXT;189break;190}191if ((e & 64) == 0){ // next table192need = e;193tree_index = tindex/3+tree[tindex+2];194break;195}196if ((e & 32)!=0){ // end of block197mode = WASH;198break;199}200mode = BADCODE; // invalid code201z.msg = "invalid literal/length code";202r = Z_DATA_ERROR;203204s.bitb=b;s.bitk=k;205z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;206s.write=q;207return s.inflate_flush(r);208209case LENEXT: // i: getting length extra (have base)210j = get;211212while(k<(j)){213if(n!=0)r=Z_OK;214else{215216s.bitb=b;s.bitk=k;217z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;218s.write=q;219return s.inflate_flush(r);220}221n--; b|=(z.next_in[p++]&0xff)<<k;222k+=8;223}224225len += (b & inflate_mask[j]);226227b>>=j;228k-=j;229230need = dbits;231tree = dtree;232tree_index=dtree_index;233mode = DIST;234case DIST: // i: get distance next235j = need;236237while(k<(j)){238if(n!=0)r=Z_OK;239else{240241s.bitb=b;s.bitk=k;242z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;243s.write=q;244return s.inflate_flush(r);245}246n--; b|=(z.next_in[p++]&0xff)<<k;247k+=8;248}249250tindex=(tree_index+(b & inflate_mask[j]))*3;251252b>>=tree[tindex+1];253k-=tree[tindex+1];254255e = (tree[tindex]);256if((e & 16)!=0){ // distance257get = e & 15;258dist = tree[tindex+2];259mode = DISTEXT;260break;261}262if ((e & 64) == 0){ // next table263need = e;264tree_index = tindex/3 + tree[tindex+2];265break;266}267mode = BADCODE; // invalid code268z.msg = "invalid distance code";269r = Z_DATA_ERROR;270271s.bitb=b;s.bitk=k;272z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;273s.write=q;274return s.inflate_flush(r);275276case DISTEXT: // i: getting distance extra277j = get;278279while(k<(j)){280if(n!=0)r=Z_OK;281else{282283s.bitb=b;s.bitk=k;284z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;285s.write=q;286return s.inflate_flush(r);287}288n--; b|=(z.next_in[p++]&0xff)<<k;289k+=8;290}291292dist += (b & inflate_mask[j]);293294b>>=j;295k-=j;296297mode = COPY;298case COPY: // o: copying bytes in window, waiting for space299f = q - dist;300while(f < 0){ // modulo window size-"while" instead301f += s.end; // of "if" handles invalid distances302}303while (len!=0){304305if(m==0){306if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}307if(m==0){308s.write=q; r=s.inflate_flush(r);309q=s.write;m=q<s.read?s.read-q-1:s.end-q;310311if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}312313if(m==0){314s.bitb=b;s.bitk=k;315z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;316s.write=q;317return s.inflate_flush(r);318}319}320}321322s.window[q++]=s.window[f++]; m--;323324if (f == s.end)325f = 0;326len--;327}328mode = START;329break;330case LIT: // o: got literal, waiting for output space331if(m==0){332if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}333if(m==0){334s.write=q; r=s.inflate_flush(r);335q=s.write;m=q<s.read?s.read-q-1:s.end-q;336337if(q==s.end&&s.read!=0){q=0;m=q<s.read?s.read-q-1:s.end-q;}338if(m==0){339s.bitb=b;s.bitk=k;340z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;341s.write=q;342return s.inflate_flush(r);343}344}345}346r=Z_OK;347348s.window[q++]=(byte)lit; m--;349350mode = START;351break;352case WASH: // o: got eob, possibly more output353if (k > 7){ // return unused byte, if any354k -= 8;355n++;356p--; // can always return one357}358359s.write=q; r=s.inflate_flush(r);360q=s.write;m=q<s.read?s.read-q-1:s.end-q;361362if (s.read != s.write){363s.bitb=b;s.bitk=k;364z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;365s.write=q;366return s.inflate_flush(r);367}368mode = END;369case END:370r = Z_STREAM_END;371s.bitb=b;s.bitk=k;372z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;373s.write=q;374return s.inflate_flush(r);375376case BADCODE: // x: got error377378r = Z_DATA_ERROR;379380s.bitb=b;s.bitk=k;381z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;382s.write=q;383return s.inflate_flush(r);384385default:386r = Z_STREAM_ERROR;387388s.bitb=b;s.bitk=k;389z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;390s.write=q;391return s.inflate_flush(r);392}393}394}395396void free(ZStream z){397// ZFREE(z, c);398}399400// Called with number of bytes left to write in window at least 258401// (the maximum string length) and number of input bytes available402// at least ten. The ten bytes are six bytes for the longest length/403// distance pair plus four bytes for overloading the bit buffer.404405int inflate_fast(int bl, int bd,406int[] tl, int tl_index,407int[] td, int td_index,408InfBlocks s, ZStream z){409int t; // temporary pointer410int[] tp; // temporary pointer411int tp_index; // temporary pointer412int e; // extra bits or operation413int b; // bit buffer414int k; // bits in bit buffer415int p; // input data pointer416int n; // bytes available there417int q; // output window write pointer418int m; // bytes to end of window or read pointer419int ml; // mask for literal/length tree420int md; // mask for distance tree421int c; // bytes to copy422int d; // distance back to copy from423int r; // copy source pointer424425int tp_index_t_3; // (tp_index+t)*3426427// load input, output, bit values428p=z.next_in_index;n=z.avail_in;b=s.bitb;k=s.bitk;429q=s.write;m=q<s.read?s.read-q-1:s.end-q;430431// initialize masks432ml = inflate_mask[bl];433md = inflate_mask[bd];434435// do until not enough input or output space for fast loop436do { // assume called with m >= 258 && n >= 10437// get literal/length code438while(k<(20)){ // max bits for literal/length code439n--;440b|=(z.next_in[p++]&0xff)<<k;k+=8;441}442443t= b&ml;444tp=tl;445tp_index=tl_index;446tp_index_t_3=(tp_index+t)*3;447if ((e = tp[tp_index_t_3]) == 0){448b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);449450s.window[q++] = (byte)tp[tp_index_t_3+2];451m--;452continue;453}454do {455456b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);457458if((e&16)!=0){459e &= 15;460c = tp[tp_index_t_3+2] + ((int)b & inflate_mask[e]);461462b>>=e; k-=e;463464// decode distance base of block to copy465while(k<(15)){ // max bits for distance code466n--;467b|=(z.next_in[p++]&0xff)<<k;k+=8;468}469470t= b&md;471tp=td;472tp_index=td_index;473tp_index_t_3=(tp_index+t)*3;474e = tp[tp_index_t_3];475476do {477478b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);479480if((e&16)!=0){481// get extra bits to add to distance base482e &= 15;483while(k<(e)){ // get extra bits (up to 13)484n--;485b|=(z.next_in[p++]&0xff)<<k;k+=8;486}487488d = tp[tp_index_t_3+2] + (b&inflate_mask[e]);489490b>>=(e); k-=(e);491492// do the copy493m -= c;494if (q >= d){ // offset before dest495// just copy496r=q-d;497if(q-r>0 && 2>(q-r)){498s.window[q++]=s.window[r++]; // minimum count is three,499s.window[q++]=s.window[r++]; // so unroll loop a little500c-=2;501}502else{503System.arraycopy(s.window, r, s.window, q, 2);504q+=2; r+=2; c-=2;505}506}507else{ // else offset after destination508r=q-d;509do{510r+=s.end; // force pointer in window511}while(r<0); // covers invalid distances512e=s.end-r;513if(c>e){ // if source crosses,514c-=e; // wrapped copy515if(q-r>0 && e>(q-r)){516do{s.window[q++] = s.window[r++];}517while(--e!=0);518}519else{520System.arraycopy(s.window, r, s.window, q, e);521q+=e; r+=e; e=0;522}523r = 0; // copy rest from start of window524}525526}527528// copy all or what's left529if(q-r>0 && c>(q-r)){530do{s.window[q++] = s.window[r++];}531while(--c!=0);532}533else{534System.arraycopy(s.window, r, s.window, q, c);535q+=c; r+=c; c=0;536}537break;538}539else if((e&64)==0){540t+=tp[tp_index_t_3+2];541t+=(b&inflate_mask[e]);542tp_index_t_3=(tp_index+t)*3;543e=tp[tp_index_t_3];544}545else{546z.msg = "invalid distance code";547548c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;549550s.bitb=b;s.bitk=k;551z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;552s.write=q;553554return Z_DATA_ERROR;555}556}557while(true);558break;559}560561if((e&64)==0){562t+=tp[tp_index_t_3+2];563t+=(b&inflate_mask[e]);564tp_index_t_3=(tp_index+t)*3;565if((e=tp[tp_index_t_3])==0){566567b>>=(tp[tp_index_t_3+1]); k-=(tp[tp_index_t_3+1]);568569s.window[q++]=(byte)tp[tp_index_t_3+2];570m--;571break;572}573}574else if((e&32)!=0){575576c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;577578s.bitb=b;s.bitk=k;579z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;580s.write=q;581582return Z_STREAM_END;583}584else{585z.msg="invalid literal/length code";586587c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;588589s.bitb=b;s.bitk=k;590z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;591s.write=q;592593return Z_DATA_ERROR;594}595}596while(true);597}598while(m>=258 && n>= 10);599600// not enough input or output--restore pointers and return601c=z.avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;602603s.bitb=b;s.bitk=k;604z.avail_in=n;z.total_in+=p-z.next_in_index;z.next_in_index=p;605s.write=q;606607return Z_OK;608}609}610611612