Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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