198 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			198 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
//
 | 
						|
// INFFAST.CPP
 | 
						|
//
 | 
						|
//  Source file for ArchiveLib 2.0
 | 
						|
//
 | 
						|
//  No Copyright claimed by Greenleaf Software!
 | 
						|
//
 | 
						|
// DESCRIPTION
 | 
						|
//
 | 
						|
//  This is one of the ZLIB source files, with as few changes as possible.
 | 
						|
//
 | 
						|
// REVISION HISTORY
 | 
						|
//
 | 
						|
//   February 14, 1996  2.0A : New release
 | 
						|
 | 
						|
#include "arclib.h"
 | 
						|
#if !defined( AL_IBM )
 | 
						|
#pragma hdrstop
 | 
						|
#endif
 | 
						|
#if defined( AL_BORLAND )
 | 
						|
#pragma option -w-
 | 
						|
#endif
 | 
						|
 | 
						|
/* inffast.c -- process literals and length/distance pairs fast
 | 
						|
 * Copyright (C) 1995 Mark Adler
 | 
						|
 * For conditions of distribution and use, see copyright notice in zlib.h 
 | 
						|
 */
 | 
						|
 | 
						|
#include "zutil.h"
 | 
						|
#include "inftrees.h"
 | 
						|
#include "infutil.h"
 | 
						|
#include "inffast.h"
 | 
						|
 | 
						|
struct inflate_codes_state {int dummy;}; /* for buggy compilers */
 | 
						|
 | 
						|
/* simplify the use of the inflate_huft type with some defines */
 | 
						|
#define base more.Base
 | 
						|
#define next more.Next
 | 
						|
#define exop word.what.Exop
 | 
						|
#define bits word.what.Bits
 | 
						|
 | 
						|
/* macros for bit input with no checking and for returning unused bytes */
 | 
						|
#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
 | 
						|
#define UNGRAB {n+=(c=k>>3);p-=c;k&=7;}
 | 
						|
 | 
						|
/* 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. */
 | 
						|
 | 
						|
int inflate_fast(
 | 
						|
uInt bl,
 | 
						|
uInt bd,
 | 
						|
inflate_huft ZL_FAR *tl,
 | 
						|
inflate_huft ZL_FAR *td,
 | 
						|
struct inflate_blocks_state ZL_FAR *s,
 | 
						|
z_stream *z )
 | 
						|
{
 | 
						|
  inflate_huft ZL_FAR *t;      /* temporary pointer */
 | 
						|
  uInt e;               /* extra bits or operation */
 | 
						|
  uLong b;              /* bit buffer */
 | 
						|
  uInt k;               /* bits in bit buffer */
 | 
						|
  Byte ZL_FAR *p;              /* input data pointer */
 | 
						|
  uInt n;               /* bytes available there */
 | 
						|
  Byte ZL_FAR *q;              /* output window write pointer */
 | 
						|
  uInt m;               /* bytes to end of window or read pointer */
 | 
						|
  uInt ml;              /* mask for literal/length tree */
 | 
						|
  uInt md;              /* mask for distance tree */
 | 
						|
  uInt c;               /* bytes to copy */
 | 
						|
  uInt d;               /* distance back to copy from */
 | 
						|
  Byte ZL_FAR *r;              /* copy source pointer */
 | 
						|
 | 
						|
  /* load input, output, bit values */
 | 
						|
  LOAD
 | 
						|
 | 
						|
  /* 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 */
 | 
						|
    GRABBITS(20)                /* max bits for literal/length code */
 | 
						|
    if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
 | 
						|
    {
 | 
						|
      DUMPBITS(t->bits)
 | 
						|
      Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
 | 
						|
                "inflate:         * literal '%c'\n" :
 | 
						|
                "inflate:         * literal 0x%02x\n", t->base));
 | 
						|
      *q++ = (Byte)t->base;
 | 
						|
      m--;
 | 
						|
      continue;
 | 
						|
    }
 | 
						|
//
 | 
						|
// Microsoft complains about do{} while (1)
 | 
						|
//
 | 
						|
    for ( ; ; ) {
 | 
						|
      DUMPBITS(t->bits)
 | 
						|
      if (e & 16)
 | 
						|
      {
 | 
						|
        /* get extra bits for length */
 | 
						|
        e &= 15;
 | 
						|
        c = t->base + ((uInt)b & inflate_mask[e]);
 | 
						|
        DUMPBITS(e)
 | 
						|
        Tracevv((stderr, "inflate:         * length %u\n", c));
 | 
						|
 | 
						|
        /* decode distance base of block to copy */
 | 
						|
        GRABBITS(15);           /* max bits for distance code */
 | 
						|
        e = (t = td + ((uInt)b & md))->exop;
 | 
						|
//
 | 
						|
// VC 1.5 complains about do{} while (1), so I changed this to
 | 
						|
// for (; ; )
 | 
						|
//
 | 
						|
        for ( ; ; ) {
 | 
						|
          DUMPBITS(t->bits)
 | 
						|
          if (e & 16)
 | 
						|
          {
 | 
						|
            /* get extra bits to add to distance base */
 | 
						|
            e &= 15;
 | 
						|
            GRABBITS(e)         /* get extra bits (up to 13) */
 | 
						|
            d = t->base + ((uInt)b & inflate_mask[e]);
 | 
						|
            DUMPBITS(e)
 | 
						|
            Tracevv((stderr, "inflate:         * distance %u\n", d));
 | 
						|
 | 
						|
            /* do the copy */
 | 
						|
            m -= c;
 | 
						|
            if ((uInt)(q - s->window) >= d)     /* offset before dest */
 | 
						|
            {                                   /*  just copy */
 | 
						|
              r = q - d;
 | 
						|
              *q++ = *r++;  c--;        /* minimum count is three, */
 | 
						|
              *q++ = *r++;  c--;        /*  so unroll loop a little */
 | 
						|
            }
 | 
						|
            else                        /* else offset after destination */
 | 
						|
            {
 | 
						|
              e = d - (q - s->window);  /* bytes from offset to end */
 | 
						|
              r = s->end - e;           /* pointer to offset */
 | 
						|
              if (c > e)                /* if source crosses, */
 | 
						|
              {
 | 
						|
                c -= e;                 /* copy to end of window */
 | 
						|
                do {
 | 
						|
                  *q++ = *r++;
 | 
						|
                } while (--e);
 | 
						|
                r = s->window;          /* copy rest from start of window */
 | 
						|
              }
 | 
						|
            }
 | 
						|
            do {                        /* copy all or what's left */
 | 
						|
              *q++ = *r++;
 | 
						|
            } while (--c);
 | 
						|
            break;
 | 
						|
          }
 | 
						|
          else if ((e & 64) == 0)
 | 
						|
            e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop;
 | 
						|
          else
 | 
						|
          {
 | 
						|
            z->msg = "invalid distance code";
 | 
						|
            UNGRAB
 | 
						|
            UPDATE
 | 
						|
            return Z_DATA_ERROR;
 | 
						|
          }
 | 
						|
        }
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      if ((e & 64) == 0)
 | 
						|
      {
 | 
						|
        if ((e = (t = t->next + ((uInt)b & inflate_mask[e]))->exop) == 0)
 | 
						|
        {
 | 
						|
          DUMPBITS(t->bits)
 | 
						|
          Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
 | 
						|
                    "inflate:         * literal '%c'\n" :
 | 
						|
                    "inflate:         * literal 0x%02x\n", t->base));
 | 
						|
          *q++ = (Byte)t->base;
 | 
						|
          m--;
 | 
						|
          break;
 | 
						|
        }
 | 
						|
      }
 | 
						|
      else if (e & 32)
 | 
						|
      {
 | 
						|
        Tracevv((stderr, "inflate:         * end of block\n"));
 | 
						|
        UNGRAB
 | 
						|
        UPDATE
 | 
						|
        return Z_STREAM_END;
 | 
						|
      }
 | 
						|
      else
 | 
						|
      {
 | 
						|
        z->msg = "invalid literal/length code";
 | 
						|
        UNGRAB
 | 
						|
        UPDATE
 | 
						|
        return Z_DATA_ERROR;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } while (m >= 258 && n >= 10);
 | 
						|
 | 
						|
  /* not enough input or output--restore pointers and return */
 | 
						|
  UNGRAB
 | 
						|
  UPDATE
 | 
						|
  return Z_OK;
 | 
						|
}
 |