infcodes.c
上传用户:zlt_tm
上传日期:2007-01-06
资源大小:214k
文件大小:8k
源码类别:

压缩解压

开发平台:

WINDOWS

  1. /* infcodes.c -- process literals and length/distance pairs
  2.  * Copyright (C) 1995-1998 Mark Adler
  3.  * For conditions of distribution and use, see copyright notice in zlib.h 
  4.  */
  5. #include "zutil.h"
  6. #include "inftrees.h"
  7. #include "infblock.h"
  8. #include "infcodes.h"
  9. #include "infutil.h"
  10. #include "inffast.h"
  11. /* simplify the use of the inflate_huft type with some defines */
  12. #define exop word.what.Exop
  13. #define bits word.what.Bits
  14. typedef enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
  15.       START,    /* x: set up for LEN */
  16.       LEN,      /* i: get length/literal/eob next */
  17.       LENEXT,   /* i: getting length extra (have base) */
  18.       DIST,     /* i: get distance next */
  19.       DISTEXT,  /* i: getting distance extra */
  20.       COPY,     /* o: copying bytes in window, waiting for space */
  21.       LIT,      /* o: got literal, waiting for output space */
  22.       WASH,     /* o: got eob, possibly still output waiting */
  23.       END,      /* x: got eob and all data flushed */
  24.       BADCODE}  /* x: got error */
  25. inflate_codes_mode;
  26. /* inflate codes private state */
  27. struct inflate_codes_state {
  28.   /* mode */
  29.   inflate_codes_mode mode;      /* current inflate_codes mode */
  30.   /* mode dependent information */
  31.   uInt len;
  32.   union {
  33.     struct {
  34.       inflate_huft *tree;       /* pointer into tree */
  35.       uInt need;                /* bits needed */
  36.     } code;             /* if LEN or DIST, where in tree */
  37.     uInt lit;           /* if LIT, literal */
  38.     struct {
  39.       uInt get;                 /* bits to get for extra */
  40.       uInt dist;                /* distance back to copy from */
  41.     } copy;             /* if EXT or COPY, where and how much */
  42.   } sub;                /* submode */
  43.   /* mode independent information */
  44.   Byte lbits;           /* ltree bits decoded per branch */
  45.   Byte dbits;           /* dtree bits decoder per branch */
  46.   inflate_huft *ltree;          /* literal/length/eob tree */
  47.   inflate_huft *dtree;          /* distance tree */
  48. };
  49. inflate_codes_statef *inflate_codes_new(bl, bd, tl, td, z)
  50. uInt bl, bd;
  51. inflate_huft *tl;
  52. inflate_huft *td; /* need separate declaration for Borland C++ */
  53. z_streamp z;
  54. {
  55.   inflate_codes_statef *c;
  56.   if ((c = (inflate_codes_statef *)
  57.        ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
  58.   {
  59.     c->mode = START;
  60.     c->lbits = (Byte)bl;
  61.     c->dbits = (Byte)bd;
  62.     c->ltree = tl;
  63.     c->dtree = td;
  64.     Tracev((stderr, "inflate:       codes newn"));
  65.   }
  66.   return c;
  67. }
  68. int inflate_codes(s, z, r)
  69. inflate_blocks_statef *s;
  70. z_streamp z;
  71. int r;
  72. {
  73.   uInt j;               /* temporary storage */
  74.   inflate_huft *t;      /* temporary pointer */
  75.   uInt e;               /* extra bits or operation */
  76.   uLong b;              /* bit buffer */
  77.   uInt k;               /* bits in bit buffer */
  78.   Bytef *p;             /* input data pointer */
  79.   uInt n;               /* bytes available there */
  80.   Bytef *q;             /* output window write pointer */
  81.   uInt m;               /* bytes to end of window or read pointer */
  82.   Bytef *f;             /* pointer to copy strings from */
  83.   inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
  84.   /* copy input/output information to locals (UPDATE macro restores) */
  85.   LOAD
  86.   /* process input and output based on current state */
  87.   while (1) switch (c->mode)
  88.   {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
  89.     case START:         /* x: set up for LEN */
  90. #ifndef SLOW
  91.       if (m >= 258 && n >= 10)
  92.       {
  93.         UPDATE
  94.         r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
  95.         LOAD
  96.         if (r != Z_OK)
  97.         {
  98.           c->mode = r == Z_STREAM_END ? WASH : BADCODE;
  99.           break;
  100.         }
  101.       }
  102. #endif /* !SLOW */
  103.       c->sub.code.need = c->lbits;
  104.       c->sub.code.tree = c->ltree;
  105.       c->mode = LEN;
  106.     case LEN:           /* i: get length/literal/eob next */
  107.       j = c->sub.code.need;
  108.       NEEDBITS(j)
  109.       t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
  110.       DUMPBITS(t->bits)
  111.       e = (uInt)(t->exop);
  112.       if (e == 0)               /* literal */
  113.       {
  114.         c->sub.lit = t->base;
  115.         Tracevv((stderr, t->base >= 0x20 && t->base < 0x7f ?
  116.                  "inflate:         literal '%c'n" :
  117.                  "inflate:         literal 0x%02xn", t->base));
  118.         c->mode = LIT;
  119.         break;
  120.       }
  121.       if (e & 16)               /* length */
  122.       {
  123.         c->sub.copy.get = e & 15;
  124.         c->len = t->base;
  125.         c->mode = LENEXT;
  126.         break;
  127.       }
  128.       if ((e & 64) == 0)        /* next table */
  129.       {
  130.         c->sub.code.need = e;
  131.         c->sub.code.tree = t + t->base;
  132.         break;
  133.       }
  134.       if (e & 32)               /* end of block */
  135.       {
  136.         Tracevv((stderr, "inflate:         end of blockn"));
  137.         c->mode = WASH;
  138.         break;
  139.       }
  140.       c->mode = BADCODE;        /* invalid code */
  141.       z->msg = (char*)"invalid literal/length code";
  142.       r = Z_DATA_ERROR;
  143.       LEAVE
  144.     case LENEXT:        /* i: getting length extra (have base) */
  145.       j = c->sub.copy.get;
  146.       NEEDBITS(j)
  147.       c->len += (uInt)b & inflate_mask[j];
  148.       DUMPBITS(j)
  149.       c->sub.code.need = c->dbits;
  150.       c->sub.code.tree = c->dtree;
  151.       Tracevv((stderr, "inflate:         length %un", c->len));
  152.       c->mode = DIST;
  153.     case DIST:          /* i: get distance next */
  154.       j = c->sub.code.need;
  155.       NEEDBITS(j)
  156.       t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
  157.       DUMPBITS(t->bits)
  158.       e = (uInt)(t->exop);
  159.       if (e & 16)               /* distance */
  160.       {
  161.         c->sub.copy.get = e & 15;
  162.         c->sub.copy.dist = t->base;
  163.         c->mode = DISTEXT;
  164.         break;
  165.       }
  166.       if ((e & 64) == 0)        /* next table */
  167.       {
  168.         c->sub.code.need = e;
  169.         c->sub.code.tree = t + t->base;
  170.         break;
  171.       }
  172.       c->mode = BADCODE;        /* invalid code */
  173.       z->msg = (char*)"invalid distance code";
  174.       r = Z_DATA_ERROR;
  175.       LEAVE
  176.     case DISTEXT:       /* i: getting distance extra */
  177.       j = c->sub.copy.get;
  178.       NEEDBITS(j)
  179.       c->sub.copy.dist += (uInt)b & inflate_mask[j];
  180.       DUMPBITS(j)
  181.       Tracevv((stderr, "inflate:         distance %un", c->sub.copy.dist));
  182.       c->mode = COPY;
  183.     case COPY:          /* o: copying bytes in window, waiting for space */
  184. #ifndef __TURBOC__ /* Turbo C bug for following expression */
  185.       f = (uInt)(q - s->window) < c->sub.copy.dist ?
  186.           s->end - (c->sub.copy.dist - (q - s->window)) :
  187.           q - c->sub.copy.dist;
  188. #else
  189.       f = q - c->sub.copy.dist;
  190.       if ((uInt)(q - s->window) < c->sub.copy.dist)
  191.         f = s->end - (c->sub.copy.dist - (uInt)(q - s->window));
  192. #endif
  193.       while (c->len)
  194.       {
  195.         NEEDOUT
  196.         OUTBYTE(*f++)
  197.         if (f == s->end)
  198.           f = s->window;
  199.         c->len--;
  200.       }
  201.       c->mode = START;
  202.       break;
  203.     case LIT:           /* o: got literal, waiting for output space */
  204.       NEEDOUT
  205.       OUTBYTE(c->sub.lit)
  206.       c->mode = START;
  207.       break;
  208.     case WASH:          /* o: got eob, possibly more output */
  209.       if (k > 7)        /* return unused byte, if any */
  210.       {
  211.         Assert(k < 16, "inflate_codes grabbed too many bytes")
  212.         k -= 8;
  213.         n++;
  214.         p--;            /* can always return one */
  215.       }
  216.       FLUSH
  217.       if (s->read != s->write)
  218.         LEAVE
  219.       c->mode = END;
  220.     case END:
  221.       r = Z_STREAM_END;
  222.       LEAVE
  223.     case BADCODE:       /* x: got error */
  224.       r = Z_DATA_ERROR;
  225.       LEAVE
  226.     default:
  227.       r = Z_STREAM_ERROR;
  228.       LEAVE
  229.   }
  230. #ifdef NEED_DUMMY_RETURN
  231.   return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
  232. #endif
  233. }
  234. void inflate_codes_free(c, z)
  235. inflate_codes_statef *c;
  236. z_streamp z;
  237. {
  238.   ZFREE(z, c);
  239.   Tracev((stderr, "inflate:       codes freen"));
  240. }