The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/lib/libz/infcodes.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 526379ac6cb0a2615300b84293f4d3a4


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.