home *** CD-ROM | disk | FTP | other *** search
/ PC World 2002 February / PCWorld_2002-02_cd.bin / Software / Vyzkuste / pdflib / pdflib-4.0.1.sit / pdflib-4.0.1 / flate / infcodes.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-07-04  |  7.7 KB  |  259 lines  |  [TEXT/CWIE]

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