⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inffast.c

📁 HEG是一个易用的强大的硬件加速2D游戏引擎 他完全具备了具有开发商业质量的2D游戏的中层引擎
💻 C
字号:
/* inffast.c -- fast decoding
 * Copyright (C) 1995-2003 Mark Adler
 * For conditions of distribution and use, see copyright notice in zlib.h
 */

#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"


#define PUP(a) *(a)++

/*
Decode literal, length, and distance codes and write out the resulting
literal and match bytes until either not enough input or output is
available, an end-of-block is encountered, or a data error is encountered.
When large enough input and output buffers are supplied to inflate(), for
example, a 16K input buffer and a 64K output buffer, more than 95% of the
inflate execution time is spent in this routine.

Entry assumptions:

state->mode == LEN
strm->avail_in >= 6
strm->avail_out >= 258
start >= strm->avail_out
state->bits < 8

On return, state->mode is one of:

LEN -- ran out of enough output space or enough available input
TYPE -- reached end of block code, inflate() to interpret next block
BAD -- error in block data

Notes:

- The maximum input bits used by a length/distance pair is 15 bits for the
length code, 5 bits for the length extra, 15 bits for the distance code,
and 13 bits for the distance extra.  This totals 48 bits, or six bytes.
Therefore if strm->avail_in >= 6, then there is enough input to avoid
checking for available input while decoding.

- The maximum bytes that a single length/distance pair can output is 258
bytes, which is the maximum length that can be coded.  inflate_fast()
requires strm->avail_out >= 258 for each loop to avoid checking for
output space.
 */

void inflate_fast(z_streamp strm, DWORD start)
{
  struct inflate_state *state = (struct inflate_state*)strm->state;

  BYTE *in = strm->next_in;
  BYTE *last = in + (strm->avail_in - 5);
  BYTE *dest = strm->next_out;
  BYTE *beg = dest - (start - strm->avail_out);
  BYTE *end = dest + (strm->avail_out - 257);
  BYTE *window = window = state->window;
  BYTE *from;

  DWORD wsize = state->wsize;
  DWORD whave = state->whave;
  DWORD write = state->write;
  DWORD hold = state->hold;
  DWORD bits = state->bits;
  DWORD lmask = (1U << state->lenbits) - 1;
  DWORD dmask = (1U << state->distbits) - 1;

  DWORD op;
  DWORD len;
  DWORD dist;

  code const *lcode = state->lencode;
  code const *dcode = state->distcode;
  code this;

  /* decode literals and length/distances until end-of-block or not enough
  input data or output space */

  do
  {
    if (bits < 15)
    {
      hold += (DWORD)(PUP(in)) << bits;
      bits += 8;
      hold += (DWORD)(PUP(in)) << bits;
      bits += 8;
    }

    this = lcode[hold & lmask];

 dolen:

    op = (DWORD)(this.bits);
    hold >>= op;
    bits -= op;
    op = (DWORD)(this.op);

    if (!op)
    {
      PUP(dest) = (BYTE)(this.val);
    }
    else if (op &16)
    {
      len = (DWORD)(this.val);
      op &= 15; /* number of extra bits */

      if (op)
      {
        if (bits < op)
        {
          hold += (DWORD)(PUP(in)) << bits;
          bits += 8;
        }

        len += (DWORD)hold &((1U << op) - 1);
        hold >>= op;
        bits -= op;
      }

      if (bits < 15)
      {
        hold += (DWORD)(PUP(in)) << bits;
        bits += 8;
        hold += (DWORD)(PUP(in)) << bits;
        bits += 8;
      }

      this = dcode[hold &dmask];
      dodist: op = (DWORD)(this.bits);
      hold >>= op;
      bits -= op;
      op = (DWORD)(this.op);

      if (op & 16)
      {
        /* distance base */
        dist = (DWORD)(this.val);
        op &= 15; /* number of extra bits */

        if (bits < op)
        {
          hold += (DWORD)(PUP(in)) << bits;
          bits += 8;

          if (bits < op)
          {
            hold += (DWORD)(PUP(in)) << bits;
            bits += 8;
          }
        }

        dist += (DWORD)hold &((1U << op) - 1);
        hold >>= op;
        bits -= op;
        op = (DWORD)(dest - beg);

        if (dist > op)
        {
          op = dist - op;

          if (op > whave)
          {
            state->mode = BAD;
            break;
          }

          from = window;

          if (!write) /* very common case */
          {
            from += wsize - op;

            if (op < len) /* some from window */
            {
              len -= op;
              do
              {
                PUP(dest) = PUP(from);
              }
              while (--op);
              from = dest - dist; /* rest from output */
            }
          }
          else if (write < op) /* wrap around window */
          {
            from += wsize + write - op;
            op -= write;
            
            if (op < len)   /* some from end of window */
            {
              len -= op;
              
              do
              {
                PUP(dest) = PUP(from);
              }
              while (--op);
              
              from = window;
              
              if (write < len)  /* some from start of window */
              {
                op = write;
                len -= op;
                
                do
                {
                  PUP(dest) = PUP(from);
                }
                while (--op);
                
                from = dest - dist; /* rest from output */
              }
            }
          }
          else
          {
            from += write - op;
            
            if (op < len)
            {
              len -= op;
              
              do
              {
                PUP(dest) = PUP(from);
              }
              while (--op);
              
              from = dest - dist; /* rest from output */
            }
          }
          
		  memcpy(dest, from, len);
		  dest += len;
		  from += len;
          len = 0;          
        }
        else
        {
          from = dest - dist; /* copy direct from output */
		  
#ifdef __GNUC__
//          asm("movl $dest, %edi");
//          asm("movl $from, %esi");
//          asm("movl $len, %ecx");
//          asm("movl %edi, %eax");
//          asm("addl %ecx, %eax");
//          asm("movl %eax, $dest");
//          asm("repne movsb");
          memcpy(dest, from, len);
          dest += len;
#else
          _asm mov edi, dword ptr dest
          _asm mov esi, dword ptr from
          _asm mov ecx, dword ptr len
          _asm mov eax, edi
          _asm add eax, ecx
          _asm mov dword ptr dest, eax
          _asm repne movsb     
#endif
        }
      }
      else if (!(op & 64))
      {
        this = dcode[this.val + (hold &((1 << op) - 1))];
        goto dodist;
      }
      else
      {
        state->mode = BAD;
        break;
      }
    }
    else if (!(op & 64))
    {
      this = lcode[this.val + (hold &((1 << op) - 1))];
      goto dolen;
    }
    else if (op & 32)
    {
      state->mode = TYPE;
      break;
    }
    else
    {
      state->mode = BAD;
      break;
    }
  }
  while (in < last && dest < end);

  /* return unused bytes (on entry, bits < 8, so in won't go too far back) */

  len = bits >> 3;
  in -= len;
  bits -= len << 3;
  hold &= (1U << bits) - 1;

  /* update state and return */
  strm->next_in = in;
  strm->next_out = dest;
  strm->avail_in = (DWORD)(in < last ? 5+(last - in): 5-(in - last));
  strm->avail_out = (DWORD)(dest < end ? 257+(end - dest): 257-(dest - end));
  state->hold = hold;
  state->bits = bits;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -