INFCODES.C
上传用户:wep9318
上传日期:2007-01-07
资源大小:893k
文件大小:8k
源码类别:

图片显示

开发平台:

Visual C++

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