306 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			306 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
//
 | 
						|
// INFLATE.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
 | 
						|
 | 
						|
/* inflate.c -- zlib interface to inflate modules
 | 
						|
 * Copyright (C) 1995 Mark Adler
 | 
						|
 * For conditions of distribution and use, see copyright notice in zlib.h
 | 
						|
 */
 | 
						|
 | 
						|
#include "zutil.h"
 | 
						|
#include "infblock.h"
 | 
						|
 | 
						|
struct inflate_blocks_state {int dummy;}; /* for buggy compilers */
 | 
						|
 | 
						|
  /* mode */
 | 
						|
  enum internal_state_mode {
 | 
						|
      METHOD,   /* waiting for method byte */
 | 
						|
      FLAG,     /* waiting for flag byte */
 | 
						|
      BLOCKS,   /* decompressing blocks */
 | 
						|
      CHECK4,   /* four check bytes to go */
 | 
						|
      CHECK3,   /* three check bytes to go */
 | 
						|
      CHECK2,   /* two check bytes to go */
 | 
						|
      CHECK1,   /* one check byte to go */
 | 
						|
      DONE,     /* finished check, done */
 | 
						|
      BAD};
 | 
						|
           /* got an error--stay here */
 | 
						|
/* inflate private state */
 | 
						|
struct internal_state {
 | 
						|
 | 
						|
    internal_state_mode mode;               /* current inflate mode */
 | 
						|
 | 
						|
  /* mode dependent information */
 | 
						|
  union {
 | 
						|
    uInt method;        /* if FLAGS, method byte */
 | 
						|
    struct {
 | 
						|
      uLong was;                /* computed check value */
 | 
						|
      uLong need;               /* stream check value */
 | 
						|
    } check;            /* if CHECK, check values to compare */
 | 
						|
    uInt marker;        /* if BAD, inflateSync's marker bytes count */
 | 
						|
  } sub;        /* submode */
 | 
						|
 | 
						|
  /* mode independent information */
 | 
						|
  int  nowrap;          /* flag for no wrapper */
 | 
						|
  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
 | 
						|
  struct inflate_blocks_state
 | 
						|
    ZL_FAR *blocks;            /* current inflate_blocks state */
 | 
						|
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
int inflateReset(
 | 
						|
z_stream *z )
 | 
						|
{
 | 
						|
  uLong c;
 | 
						|
 | 
						|
  if (z == Z_NULL || z->state == Z_NULL)
 | 
						|
    return Z_STREAM_ERROR;
 | 
						|
  z->total_in = z->total_out = 0;
 | 
						|
  z->msg = Z_NULL;
 | 
						|
  z->state->mode = z->state->nowrap ? BLOCKS : METHOD;
 | 
						|
  inflate_blocks_reset(z->state->blocks, z, &c);
 | 
						|
  Trace((stderr, "inflate: reset\n"));
 | 
						|
  return Z_OK;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int inflateEnd(
 | 
						|
z_stream *z )
 | 
						|
{
 | 
						|
  uLong c;
 | 
						|
 | 
						|
  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
 | 
						|
    return Z_STREAM_ERROR;
 | 
						|
  if (z->state->blocks != Z_NULL)
 | 
						|
    inflate_blocks_free(z->state->blocks, z, &c);
 | 
						|
  ZFREE(z, z->state);
 | 
						|
  z->state = Z_NULL;
 | 
						|
  Trace((stderr, "inflate: end\n"));
 | 
						|
  return Z_OK;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int inflateInit2(
 | 
						|
z_stream *z,
 | 
						|
int w )
 | 
						|
{
 | 
						|
  /* initialize state */
 | 
						|
  if (z == Z_NULL)
 | 
						|
    return Z_STREAM_ERROR;
 | 
						|
  if (z->zalloc == Z_NULL) z->zalloc = zcalloc;
 | 
						|
  if (z->zfree == Z_NULL) z->zfree = zcfree;
 | 
						|
  if ((z->state = (struct internal_state ZL_FAR *)
 | 
						|
       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
 | 
						|
    return Z_MEM_ERROR;
 | 
						|
  z->state->blocks = Z_NULL;
 | 
						|
 | 
						|
  /* handle undocumented nowrap option (no zlib header or check) */
 | 
						|
  z->state->nowrap = 0;
 | 
						|
  if (w < 0)
 | 
						|
  {
 | 
						|
    w = - w;
 | 
						|
    z->state->nowrap = 1;
 | 
						|
  }
 | 
						|
 | 
						|
  /* set window size */
 | 
						|
  if (w < 8 || w > 15)
 | 
						|
  {
 | 
						|
    inflateEnd(z);
 | 
						|
    return Z_STREAM_ERROR;
 | 
						|
  }
 | 
						|
  z->state->wbits = (uInt)w;
 | 
						|
 | 
						|
  /* create inflate_blocks state */
 | 
						|
  if ((z->state->blocks =
 | 
						|
       inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, 1 << w))
 | 
						|
      == Z_NULL)
 | 
						|
  {
 | 
						|
    inflateEnd(z);
 | 
						|
    return Z_MEM_ERROR;
 | 
						|
  }
 | 
						|
  Trace((stderr, "inflate: allocated\n"));
 | 
						|
 | 
						|
  /* reset state */
 | 
						|
  inflateReset(z);
 | 
						|
  return Z_OK;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int inflateInit(
 | 
						|
z_stream *z )
 | 
						|
{
 | 
						|
  return inflateInit2(z, DEF_WBITS);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
#define NEEDBYTE {if(z->avail_in==0)return r;r=Z_OK;}
 | 
						|
#define NEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
 | 
						|
 | 
						|
int inflate(
 | 
						|
z_stream *z,
 | 
						|
int f )
 | 
						|
{
 | 
						|
  int r = f;    /* to avoid warning about unused f */
 | 
						|
  uInt b;
 | 
						|
 | 
						|
  if (z == Z_NULL || z->next_in == Z_NULL)
 | 
						|
    return Z_STREAM_ERROR;
 | 
						|
  r = Z_BUF_ERROR;
 | 
						|
  for ( ; ; )  switch (z->state->mode)
 | 
						|
  {
 | 
						|
    case METHOD:
 | 
						|
      NEEDBYTE
 | 
						|
      if (((z->state->sub.method = NEXTBYTE) & 0xf) != DEFLATED)
 | 
						|
      {
 | 
						|
        z->state->mode = BAD;
 | 
						|
        z->msg = "unknown compression method";
 | 
						|
        z->state->sub.marker = 5;       /* can't try inflateSync */
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
 | 
						|
      {
 | 
						|
        z->state->mode = BAD;
 | 
						|
        z->msg = "invalid window size";
 | 
						|
        z->state->sub.marker = 5;       /* can't try inflateSync */
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      z->state->mode = FLAG;
 | 
						|
    case FLAG:
 | 
						|
      NEEDBYTE
 | 
						|
      if ((b = NEXTBYTE) & 0x20)
 | 
						|
      {
 | 
						|
        z->state->mode = BAD;
 | 
						|
        z->msg = "invalid reserved bit";
 | 
						|
        z->state->sub.marker = 5;       /* can't try inflateSync */
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      if (((z->state->sub.method << 8) + b) % 31)
 | 
						|
      {
 | 
						|
        z->state->mode = BAD;
 | 
						|
        z->msg = "incorrect header check";
 | 
						|
        z->state->sub.marker = 5;       /* can't try inflateSync */
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      Trace((stderr, "inflate: zlib header ok\n"));
 | 
						|
      z->state->mode = BLOCKS;
 | 
						|
    case BLOCKS:
 | 
						|
      r = inflate_blocks(z->state->blocks, z, r);
 | 
						|
      if (r == Z_DATA_ERROR)
 | 
						|
      {
 | 
						|
        z->state->mode = BAD;
 | 
						|
        z->state->sub.marker = 0;       /* can try inflateSync */
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      if (r != Z_STREAM_END)
 | 
						|
        return r;
 | 
						|
      r = Z_OK;
 | 
						|
      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
 | 
						|
      if (z->state->nowrap)
 | 
						|
      {
 | 
						|
        z->state->mode = DONE;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      z->state->mode = CHECK4;
 | 
						|
    case CHECK4:
 | 
						|
      NEEDBYTE
 | 
						|
      z->state->sub.check.need = (uLong)NEXTBYTE << 24;
 | 
						|
      z->state->mode = CHECK3;
 | 
						|
    case CHECK3:
 | 
						|
      NEEDBYTE
 | 
						|
      z->state->sub.check.need += (uLong)NEXTBYTE << 16;
 | 
						|
      z->state->mode = CHECK2;
 | 
						|
    case CHECK2:
 | 
						|
      NEEDBYTE
 | 
						|
      z->state->sub.check.need += (uLong)NEXTBYTE << 8;
 | 
						|
      z->state->mode = CHECK1;
 | 
						|
    case CHECK1:
 | 
						|
      NEEDBYTE
 | 
						|
      z->state->sub.check.need += (uLong)NEXTBYTE;
 | 
						|
 | 
						|
      if (z->state->sub.check.was != z->state->sub.check.need)
 | 
						|
      {
 | 
						|
        z->state->mode = BAD;
 | 
						|
        z->msg = "incorrect data check";
 | 
						|
        z->state->sub.marker = 5;       /* can't try inflateSync */
 | 
						|
        break;
 | 
						|
      }
 | 
						|
      Trace((stderr, "inflate: zlib check ok\n"));
 | 
						|
      z->state->mode = DONE;
 | 
						|
    case DONE:
 | 
						|
      return Z_STREAM_END;
 | 
						|
    case BAD:
 | 
						|
      return Z_DATA_ERROR;
 | 
						|
    default:
 | 
						|
      return Z_STREAM_ERROR;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int inflateSync(
 | 
						|
z_stream *z )
 | 
						|
{
 | 
						|
  uInt n;       /* number of bytes to look at */
 | 
						|
  Byte ZL_FAR *p;      /* pointer to bytes */
 | 
						|
  uInt m;       /* number of marker bytes found in a row */
 | 
						|
  uLong r, w;   /* temporaries to save total_in and total_out */
 | 
						|
 | 
						|
  /* set up */
 | 
						|
  if (z == Z_NULL || z->state == Z_NULL)
 | 
						|
    return Z_STREAM_ERROR;
 | 
						|
  if (z->state->mode != BAD)
 | 
						|
  {
 | 
						|
    z->state->mode = BAD;
 | 
						|
    z->state->sub.marker = 0;
 | 
						|
  }
 | 
						|
  if ((n = z->avail_in) == 0)
 | 
						|
    return Z_BUF_ERROR;
 | 
						|
  p = z->next_in;
 | 
						|
  m = z->state->sub.marker;
 | 
						|
 | 
						|
  /* search */
 | 
						|
  while (n && m < 4)
 | 
						|
  {
 | 
						|
    if (*p == (Byte)(m < 2 ? 0 : 0xff))
 | 
						|
      m++;
 | 
						|
    else if (*p)
 | 
						|
      m = 0;
 | 
						|
    else
 | 
						|
      m = 4 - m;
 | 
						|
    p++, n--;
 | 
						|
  }
 | 
						|
 | 
						|
  /* restore */
 | 
						|
  z->total_in += p - z->next_in;
 | 
						|
  z->next_in = p;
 | 
						|
  z->avail_in = n;
 | 
						|
  z->state->sub.marker = m;
 | 
						|
 | 
						|
  /* return no joy or set up to restart on a new block */
 | 
						|
  if (m != 4)
 | 
						|
    return Z_DATA_ERROR;
 | 
						|
  r = z->total_in;  w = z->total_out;
 | 
						|
  inflateReset(z);
 | 
						|
  z->total_in = r;  z->total_out = w;
 | 
						|
  z->state->mode = BLOCKS;
 | 
						|
  return Z_OK;
 | 
						|
}
 |