203 lines
		
	
	
	
		
			5.3 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			203 lines
		
	
	
	
		
			5.3 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| 
								 | 
							
								/* infcodes.c -- process literals and length/distance pairs
							 | 
						||
| 
								 | 
							
								 * Copyright (C) 1995-1998 Mark Adler
							 | 
						||
| 
								 | 
							
								 * For conditions of distribution and use, see copyright notice in zlib.h 
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <linux/zutil.h>
							 | 
						||
| 
								 | 
							
								#include "inftrees.h"
							 | 
						||
| 
								 | 
							
								#include "infblock.h"
							 | 
						||
| 
								 | 
							
								#include "infcodes.h"
							 | 
						||
| 
								 | 
							
								#include "infutil.h"
							 | 
						||
| 
								 | 
							
								#include "inffast.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* simplify the use of the inflate_huft type with some defines */
							 | 
						||
| 
								 | 
							
								#define exop word.what.Exop
							 | 
						||
| 
								 | 
							
								#define bits word.what.Bits
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								inflate_codes_statef *zlib_inflate_codes_new(
							 | 
						||
| 
								 | 
							
									uInt bl,
							 | 
						||
| 
								 | 
							
									uInt bd,
							 | 
						||
| 
								 | 
							
									inflate_huft *tl,
							 | 
						||
| 
								 | 
							
									inflate_huft *td, /* need separate declaration for Borland C++ */
							 | 
						||
| 
								 | 
							
									z_streamp z
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  inflate_codes_statef *c;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  c = &WS(z)->working_state;
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    c->mode = START;
							 | 
						||
| 
								 | 
							
								    c->lbits = (Byte)bl;
							 | 
						||
| 
								 | 
							
								    c->dbits = (Byte)bd;
							 | 
						||
| 
								 | 
							
								    c->ltree = tl;
							 | 
						||
| 
								 | 
							
								    c->dtree = td;
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return c;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								int zlib_inflate_codes(
							 | 
						||
| 
								 | 
							
									inflate_blocks_statef *s,
							 | 
						||
| 
								 | 
							
									z_streamp z,
							 | 
						||
| 
								 | 
							
									int r
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  uInt j;               /* temporary storage */
							 | 
						||
| 
								 | 
							
								  inflate_huft *t;      /* temporary pointer */
							 | 
						||
| 
								 | 
							
								  uInt e;               /* extra bits or operation */
							 | 
						||
| 
								 | 
							
								  uLong b;              /* bit buffer */
							 | 
						||
| 
								 | 
							
								  uInt k;               /* bits in bit buffer */
							 | 
						||
| 
								 | 
							
								  Byte *p;              /* input data pointer */
							 | 
						||
| 
								 | 
							
								  uInt n;               /* bytes available there */
							 | 
						||
| 
								 | 
							
								  Byte *q;              /* output window write pointer */
							 | 
						||
| 
								 | 
							
								  uInt m;               /* bytes to end of window or read pointer */
							 | 
						||
| 
								 | 
							
								  Byte *f;              /* pointer to copy strings from */
							 | 
						||
| 
								 | 
							
								  inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* copy input/output information to locals (UPDATE macro restores) */
							 | 
						||
| 
								 | 
							
								  LOAD
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  /* process input and output based on current state */
							 | 
						||
| 
								 | 
							
								  while (1) switch (c->mode)
							 | 
						||
| 
								 | 
							
								  {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
							 | 
						||
| 
								 | 
							
								    case START:         /* x: set up for LEN */
							 | 
						||
| 
								 | 
							
								#ifndef SLOW
							 | 
						||
| 
								 | 
							
								      if (m >= 258 && n >= 10)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        UPDATE
							 | 
						||
| 
								 | 
							
								        r = zlib_inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
							 | 
						||
| 
								 | 
							
								        LOAD
							 | 
						||
| 
								 | 
							
								        if (r != Z_OK)
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          c->mode = r == Z_STREAM_END ? WASH : BADCODE;
							 | 
						||
| 
								 | 
							
								          break;
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								#endif /* !SLOW */
							 | 
						||
| 
								 | 
							
								      c->sub.code.need = c->lbits;
							 | 
						||
| 
								 | 
							
								      c->sub.code.tree = c->ltree;
							 | 
						||
| 
								 | 
							
								      c->mode = LEN;
							 | 
						||
| 
								 | 
							
								    case LEN:           /* i: get length/literal/eob next */
							 | 
						||
| 
								 | 
							
								      j = c->sub.code.need;
							 | 
						||
| 
								 | 
							
								      NEEDBITS(j)
							 | 
						||
| 
								 | 
							
								      t = c->sub.code.tree + ((uInt)b & zlib_inflate_mask[j]);
							 | 
						||
| 
								 | 
							
								      DUMPBITS(t->bits)
							 | 
						||
| 
								 | 
							
								      e = (uInt)(t->exop);
							 | 
						||
| 
								 | 
							
								      if (e == 0)               /* literal */
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        c->sub.lit = t->base;
							 | 
						||
| 
								 | 
							
								        c->mode = LIT;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      if (e & 16)               /* length */
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        c->sub.copy.get = e & 15;
							 | 
						||
| 
								 | 
							
								        c->len = t->base;
							 | 
						||
| 
								 | 
							
								        c->mode = LENEXT;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      if ((e & 64) == 0)        /* next table */
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        c->sub.code.need = e;
							 | 
						||
| 
								 | 
							
								        c->sub.code.tree = t + t->base;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      if (e & 32)               /* end of block */
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        c->mode = WASH;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      c->mode = BADCODE;        /* invalid code */
							 | 
						||
| 
								 | 
							
								      z->msg = (char*)"invalid literal/length code";
							 | 
						||
| 
								 | 
							
								      r = Z_DATA_ERROR;
							 | 
						||
| 
								 | 
							
								      LEAVE
							 | 
						||
| 
								 | 
							
								    case LENEXT:        /* i: getting length extra (have base) */
							 | 
						||
| 
								 | 
							
								      j = c->sub.copy.get;
							 | 
						||
| 
								 | 
							
								      NEEDBITS(j)
							 | 
						||
| 
								 | 
							
								      c->len += (uInt)b & zlib_inflate_mask[j];
							 | 
						||
| 
								 | 
							
								      DUMPBITS(j)
							 | 
						||
| 
								 | 
							
								      c->sub.code.need = c->dbits;
							 | 
						||
| 
								 | 
							
								      c->sub.code.tree = c->dtree;
							 | 
						||
| 
								 | 
							
								      c->mode = DIST;
							 | 
						||
| 
								 | 
							
								    case DIST:          /* i: get distance next */
							 | 
						||
| 
								 | 
							
								      j = c->sub.code.need;
							 | 
						||
| 
								 | 
							
								      NEEDBITS(j)
							 | 
						||
| 
								 | 
							
								      t = c->sub.code.tree + ((uInt)b & zlib_inflate_mask[j]);
							 | 
						||
| 
								 | 
							
								      DUMPBITS(t->bits)
							 | 
						||
| 
								 | 
							
								      e = (uInt)(t->exop);
							 | 
						||
| 
								 | 
							
								      if (e & 16)               /* distance */
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        c->sub.copy.get = e & 15;
							 | 
						||
| 
								 | 
							
								        c->sub.copy.dist = t->base;
							 | 
						||
| 
								 | 
							
								        c->mode = DISTEXT;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      if ((e & 64) == 0)        /* next table */
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        c->sub.code.need = e;
							 | 
						||
| 
								 | 
							
								        c->sub.code.tree = t + t->base;
							 | 
						||
| 
								 | 
							
								        break;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      c->mode = BADCODE;        /* invalid code */
							 | 
						||
| 
								 | 
							
								      z->msg = (char*)"invalid distance code";
							 | 
						||
| 
								 | 
							
								      r = Z_DATA_ERROR;
							 | 
						||
| 
								 | 
							
								      LEAVE
							 | 
						||
| 
								 | 
							
								    case DISTEXT:       /* i: getting distance extra */
							 | 
						||
| 
								 | 
							
								      j = c->sub.copy.get;
							 | 
						||
| 
								 | 
							
								      NEEDBITS(j)
							 | 
						||
| 
								 | 
							
								      c->sub.copy.dist += (uInt)b & zlib_inflate_mask[j];
							 | 
						||
| 
								 | 
							
								      DUMPBITS(j)
							 | 
						||
| 
								 | 
							
								      c->mode = COPY;
							 | 
						||
| 
								 | 
							
								    case COPY:          /* o: copying bytes in window, waiting for space */
							 | 
						||
| 
								 | 
							
								      f = q - c->sub.copy.dist;
							 | 
						||
| 
								 | 
							
								      while (f < s->window)             /* modulo window size-"while" instead */
							 | 
						||
| 
								 | 
							
								        f += s->end - s->window;        /* of "if" handles invalid distances */
							 | 
						||
| 
								 | 
							
								      while (c->len)
							 | 
						||
| 
								 | 
							
								      {
							 | 
						||
| 
								 | 
							
								        NEEDOUT
							 | 
						||
| 
								 | 
							
								        OUTBYTE(*f++)
							 | 
						||
| 
								 | 
							
								        if (f == s->end)
							 | 
						||
| 
								 | 
							
								          f = s->window;
							 | 
						||
| 
								 | 
							
								        c->len--;
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      c->mode = START;
							 | 
						||
| 
								 | 
							
								      break;
							 | 
						||
| 
								 | 
							
								    case LIT:           /* o: got literal, waiting for output space */
							 | 
						||
| 
								 | 
							
								      NEEDOUT
							 | 
						||
| 
								 | 
							
								      OUTBYTE(c->sub.lit)
							 | 
						||
| 
								 | 
							
								      c->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 */
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      FLUSH
							 | 
						||
| 
								 | 
							
								      if (s->read != s->write)
							 | 
						||
| 
								 | 
							
								        LEAVE
							 | 
						||
| 
								 | 
							
								      c->mode = END;
							 | 
						||
| 
								 | 
							
								    case END:
							 | 
						||
| 
								 | 
							
								      r = Z_STREAM_END;
							 | 
						||
| 
								 | 
							
								      LEAVE
							 | 
						||
| 
								 | 
							
								    case BADCODE:       /* x: got error */
							 | 
						||
| 
								 | 
							
								      r = Z_DATA_ERROR;
							 | 
						||
| 
								 | 
							
								      LEAVE
							 | 
						||
| 
								 | 
							
								    default:
							 | 
						||
| 
								 | 
							
								      r = Z_STREAM_ERROR;
							 | 
						||
| 
								 | 
							
								      LEAVE
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								#ifdef NEED_DUMMY_RETURN
							 | 
						||
| 
								 | 
							
								  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void zlib_inflate_codes_free(
							 | 
						||
| 
								 | 
							
									inflate_codes_statef *c,
							 | 
						||
| 
								 | 
							
									z_streamp z
							 | 
						||
| 
								 | 
							
								)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								}
							 |