infback9.c

Go to the documentation of this file.
00001 /* infback9.c -- inflate deflate64 data using a call-back interface
00002  * Copyright (C) 1995-2003 Mark Adler
00003  * For conditions of distribution and use, see copyright notice in zlib.h
00004  */
00005 
00006 #include "zutil.h"
00007 #include "infback9.h"
00008 #include "inftree9.h"
00009 #include "inflate9.h"
00010 
00011 #define WSIZE 65536UL
00012 
00013 /*
00014    strm provides memory allocation functions in zalloc and zfree, or
00015    Z_NULL to use the library memory allocation functions.
00016 
00017    window is a user-supplied window and output buffer that is 64K bytes.
00018  */
00019 int ZEXPORT inflateBack9Init_(strm, window, version, stream_size)
00020 z_stream FAR *strm;
00021 unsigned char FAR *window;
00022 const char *version;
00023 int stream_size;
00024 {
00025     struct inflate_state FAR *state;
00026 
00027     if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
00028         stream_size != (int)(sizeof(z_stream)))
00029         return Z_VERSION_ERROR;
00030     if (strm == Z_NULL || window == Z_NULL)
00031         return Z_STREAM_ERROR;
00032     strm->msg = Z_NULL;                 /* in case we return an error */
00033     if (strm->zalloc == (alloc_func)0) {
00034         strm->zalloc = zcalloc;
00035         strm->opaque = (voidpf)0;
00036     }
00037     if (strm->zfree == (free_func)0) strm->zfree = zcfree;
00038     state = (struct inflate_state FAR *)ZALLOC(strm, 1,
00039                                                sizeof(struct inflate_state));
00040     if (state == Z_NULL) return Z_MEM_ERROR;
00041     Tracev((stderr, "inflate: allocated\n"));
00042     strm->state = (voidpf)state;
00043     state->window = window;
00044     return Z_OK;
00045 }
00046 
00047 /*
00048    Build and output length and distance decoding tables for fixed code
00049    decoding.
00050  */
00051 #ifdef MAKEFIXED
00052 #include <stdio.h>
00053 
00054 void makefixed9(void)
00055 {
00056     unsigned sym, bits, low, size;
00057     code *next, *lenfix, *distfix;
00058     struct inflate_state state;
00059     code fixed[544];
00060 
00061     /* literal/length table */
00062     sym = 0;
00063     while (sym < 144) state.lens[sym++] = 8;
00064     while (sym < 256) state.lens[sym++] = 9;
00065     while (sym < 280) state.lens[sym++] = 7;
00066     while (sym < 288) state.lens[sym++] = 8;
00067     next = fixed;
00068     lenfix = next;
00069     bits = 9;
00070     inflate_table9(LENS, state.lens, 288, &(next), &(bits), state.work);
00071 
00072     /* distance table */
00073     sym = 0;
00074     while (sym < 32) state.lens[sym++] = 5;
00075     distfix = next;
00076     bits = 5;
00077     inflate_table9(DISTS, state.lens, 32, &(next), &(bits), state.work);
00078 
00079     /* write tables */
00080     puts("    /* inffix9.h -- table for decoding deflate64 fixed codes");
00081     puts("     * Generated automatically by makefixed9().");
00082     puts("     */");
00083     puts("");
00084     puts("    /* WARNING: this file should *not* be used by applications.");
00085     puts("       It is part of the implementation of this library and is");
00086     puts("       subject to change. Applications should only use zlib.h.");
00087     puts("     */");
00088     puts("");
00089     size = 1U << 9;
00090     printf("    static const code lenfix[%u] = {", size);
00091     low = 0;
00092     for (;;) {
00093         if ((low % 6) == 0) printf("\n        ");
00094         printf("{%u,%u,%d}", lenfix[low].op, lenfix[low].bits,
00095                lenfix[low].val);
00096         if (++low == size) break;
00097         putchar(',');
00098     }
00099     puts("\n    };");
00100     size = 1U << 5;
00101     printf("\n    static const code distfix[%u] = {", size);
00102     low = 0;
00103     for (;;) {
00104         if ((low % 5) == 0) printf("\n        ");
00105         printf("{%u,%u,%d}", distfix[low].op, distfix[low].bits,
00106                distfix[low].val);
00107         if (++low == size) break;
00108         putchar(',');
00109     }
00110     puts("\n    };");
00111 }
00112 #endif /* MAKEFIXED */
00113 
00114 /* Macros for inflateBack(): */
00115 
00116 /* Clear the input bit accumulator */
00117 #define INITBITS() \
00118     do { \
00119         hold = 0; \
00120         bits = 0; \
00121     } while (0)
00122 
00123 /* Assure that some input is available.  If input is requested, but denied,
00124    then return a Z_BUF_ERROR from inflateBack(). */
00125 #define PULL() \
00126     do { \
00127         if (have == 0) { \
00128             have = in(in_desc, &next); \
00129             if (have == 0) { \
00130                 next = Z_NULL; \
00131                 ret = Z_BUF_ERROR; \
00132                 goto inf_leave; \
00133             } \
00134         } \
00135     } while (0)
00136 
00137 /* Get a byte of input into the bit accumulator, or return from inflateBack()
00138    with an error if there is no input available. */
00139 #define PULLBYTE() \
00140     do { \
00141         PULL(); \
00142         have--; \
00143         hold += (unsigned long)(*next++) << bits; \
00144         bits += 8; \
00145     } while (0)
00146 
00147 /* Assure that there are at least n bits in the bit accumulator.  If there is
00148    not enough available input to do that, then return from inflateBack() with
00149    an error. */
00150 #define NEEDBITS(n) \
00151     do { \
00152         while (bits < (unsigned)(n)) \
00153             PULLBYTE(); \
00154     } while (0)
00155 
00156 /* Return the low n bits of the bit accumulator (n <= 16) */
00157 #define BITS(n) \
00158     ((unsigned)hold & ((1U << (n)) - 1))
00159 
00160 /* Remove n bits from the bit accumulator */
00161 #define DROPBITS(n) \
00162     do { \
00163         hold >>= (n); \
00164         bits -= (unsigned)(n); \
00165     } while (0)
00166 
00167 /* Remove zero to seven bits as needed to go to a byte boundary */
00168 #define BYTEBITS() \
00169     do { \
00170         hold >>= bits & 7; \
00171         bits -= bits & 7; \
00172     } while (0)
00173 
00174 /* Assure that some output space is available, by writing out the window
00175    if it's full.  If the write fails, return from inflateBack() with a
00176    Z_BUF_ERROR. */
00177 #define ROOM() \
00178     do { \
00179         if (left == 0) { \
00180             put = window; \
00181             left = WSIZE; \
00182             wrap = 1; \
00183             if (out(out_desc, put, (unsigned)left)) { \
00184                 ret = Z_BUF_ERROR; \
00185                 goto inf_leave; \
00186             } \
00187         } \
00188     } while (0)
00189 
00190 /*
00191    strm provides the memory allocation functions and window buffer on input,
00192    and provides information on the unused input on return.  For Z_DATA_ERROR
00193    returns, strm will also provide an error message.
00194 
00195    in() and out() are the call-back input and output functions.  When
00196    inflateBack() needs more input, it calls in().  When inflateBack() has
00197    filled the window with output, or when it completes with data in the
00198    window, it calls out() to write out the data.  The application must not
00199    change the provided input until in() is called again or inflateBack()
00200    returns.  The application must not change the window/output buffer until
00201    inflateBack() returns.
00202 
00203    in() and out() are called with a descriptor parameter provided in the
00204    inflateBack() call.  This parameter can be a structure that provides the
00205    information required to do the read or write, as well as accumulated
00206    information on the input and output such as totals and check values.
00207 
00208    in() should return zero on failure.  out() should return non-zero on
00209    failure.  If either in() or out() fails, than inflateBack() returns a
00210    Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
00211    was in() or out() that caused in the error.  Otherwise,  inflateBack()
00212    returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
00213    error, or Z_MEM_ERROR if it could not allocate memory for the state.
00214    inflateBack() can also return Z_STREAM_ERROR if the input parameters
00215    are not correct, i.e. strm is Z_NULL or the state was not initialized.
00216  */
00217 int ZEXPORT inflateBack9(strm, in, in_desc, out, out_desc)
00218 z_stream FAR *strm;
00219 in_func in;
00220 void FAR *in_desc;
00221 out_func out;
00222 void FAR *out_desc;
00223 {
00224     struct inflate_state FAR *state;
00225     unsigned char FAR *next;    /* next input */
00226     unsigned char FAR *put;     /* next output */
00227     unsigned have;              /* available input */
00228     unsigned long left;         /* available output */
00229     inflate_mode mode;          /* current inflate mode */
00230     int lastblock;              /* true if processing last block */
00231     int wrap;                   /* true if the window has wrapped */
00232     unsigned long write;        /* window write index */
00233     unsigned char FAR *window;  /* allocated sliding window, if needed */
00234     unsigned long hold;         /* bit buffer */
00235     unsigned bits;              /* bits in bit buffer */
00236     unsigned extra;             /* extra bits needed */
00237     unsigned long length;       /* literal or length of data to copy */
00238     unsigned long offset;       /* distance back to copy string from */
00239     unsigned long copy;         /* number of stored or match bytes to copy */
00240     unsigned char FAR *from;    /* where to copy match bytes from */
00241     code const FAR *lencode;    /* starting table for length/literal codes */
00242     code const FAR *distcode;   /* starting table for distance codes */
00243     unsigned lenbits;           /* index bits for lencode */
00244     unsigned distbits;          /* index bits for distcode */
00245     code this;                  /* current decoding table entry */
00246     code last;                  /* parent table entry */
00247     unsigned len;               /* length to copy for repeats, bits to drop */
00248     int ret;                    /* return code */
00249     static const unsigned short order[19] = /* permutation of code lengths */
00250         {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
00251 #include "inffix9.h"
00252 
00253     /* Check that the strm exists and that the state was initialized */
00254     if (strm == Z_NULL || strm->state == Z_NULL)
00255         return Z_STREAM_ERROR;
00256     state = (struct inflate_state FAR *)strm->state;
00257 
00258     /* Reset the state */
00259     strm->msg = Z_NULL;
00260     mode = TYPE;
00261     lastblock = 0;
00262     write = 0;
00263     wrap = 0;
00264     window = state->window;
00265     next = strm->next_in;
00266     have = next != Z_NULL ? strm->avail_in : 0;
00267     hold = 0;
00268     bits = 0;
00269     put = window;
00270     left = WSIZE;
00271     lencode = Z_NULL;
00272     distcode = Z_NULL;
00273 
00274     /* Inflate until end of block marked as last */
00275     for (;;)
00276         switch (mode) {
00277         case TYPE:
00278             /* determine and dispatch block type */
00279             if (lastblock) {
00280                 BYTEBITS();
00281                 mode = DONE;
00282                 break;
00283             }
00284             NEEDBITS(3);
00285             lastblock = BITS(1);
00286             DROPBITS(1);
00287             switch (BITS(2)) {
00288             case 0:                             /* stored block */
00289                 Tracev((stderr, "inflate:     stored block%s\n",
00290                         lastblock ? " (last)" : ""));
00291                 mode = STORED;
00292                 break;
00293             case 1:                             /* fixed block */
00294                 lencode = lenfix;
00295                 lenbits = 9;
00296                 distcode = distfix;
00297                 distbits = 5;
00298                 Tracev((stderr, "inflate:     fixed codes block%s\n",
00299                         lastblock ? " (last)" : ""));
00300                 mode = LEN;                     /* decode codes */
00301                 break;
00302             case 2:                             /* dynamic block */
00303                 Tracev((stderr, "inflate:     dynamic codes block%s\n",
00304                         lastblock ? " (last)" : ""));
00305                 mode = TABLE;
00306                 break;
00307             case 3:
00308                 strm->msg = (char *)"invalid block type";
00309                 mode = BAD;
00310             }
00311             DROPBITS(2);
00312             break;
00313 
00314         case STORED:
00315             /* get and verify stored block length */
00316             BYTEBITS();                         /* go to byte boundary */
00317             NEEDBITS(32);
00318             if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
00319                 strm->msg = (char *)"invalid stored block lengths";
00320                 mode = BAD;
00321                 break;
00322             }
00323             length = (unsigned)hold & 0xffff;
00324             Tracev((stderr, "inflate:       stored length %lu\n",
00325                     length));
00326             INITBITS();
00327 
00328             /* copy stored block from input to output */
00329             while (length != 0) {
00330                 copy = length;
00331                 PULL();
00332                 ROOM();
00333                 if (copy > have) copy = have;
00334                 if (copy > left) copy = left;
00335                 zmemcpy(put, next, copy);
00336                 have -= copy;
00337                 next += copy;
00338                 left -= copy;
00339                 put += copy;
00340                 length -= copy;
00341             }
00342             Tracev((stderr, "inflate:       stored end\n"));
00343             mode = TYPE;
00344             break;
00345 
00346         case TABLE:
00347             /* get dynamic table entries descriptor */
00348             NEEDBITS(14);
00349             state->nlen = BITS(5) + 257;
00350             DROPBITS(5);
00351             state->ndist = BITS(5) + 1;
00352             DROPBITS(5);
00353             state->ncode = BITS(4) + 4;
00354             DROPBITS(4);
00355             if (state->nlen > 286) {
00356                 strm->msg = (char *)"too many length symbols";
00357                 mode = BAD;
00358                 break;
00359             }
00360             Tracev((stderr, "inflate:       table sizes ok\n"));
00361 
00362             /* get code length code lengths (not a typo) */
00363             state->have = 0;
00364             while (state->have < state->ncode) {
00365                 NEEDBITS(3);
00366                 state->lens[order[state->have++]] = (unsigned short)BITS(3);
00367                 DROPBITS(3);
00368             }
00369             while (state->have < 19)
00370                 state->lens[order[state->have++]] = 0;
00371             state->next = state->codes;
00372             lencode = (code const FAR *)(state->next);
00373             lenbits = 7;
00374             ret = inflate_table9(CODES, state->lens, 19, &(state->next),
00375                                 &(lenbits), state->work);
00376             if (ret) {
00377                 strm->msg = (char *)"invalid code lengths set";
00378                 mode = BAD;
00379                 break;
00380             }
00381             Tracev((stderr, "inflate:       code lengths ok\n"));
00382 
00383             /* get length and distance code code lengths */
00384             state->have = 0;
00385             while (state->have < state->nlen + state->ndist) {
00386                 for (;;) {
00387                     this = lencode[BITS(lenbits)];
00388                     if ((unsigned)(this.bits) <= bits) break;
00389                     PULLBYTE();
00390                 }
00391                 if (this.val < 16) {
00392                     NEEDBITS(this.bits);
00393                     DROPBITS(this.bits);
00394                     state->lens[state->have++] = this.val;
00395                 }
00396                 else {
00397                     if (this.val == 16) {
00398                         NEEDBITS(this.bits + 2);
00399                         DROPBITS(this.bits);
00400                         if (state->have == 0) {
00401                             strm->msg = (char *)"invalid bit length repeat";
00402                             mode = BAD;
00403                             break;
00404                         }
00405                         len = (unsigned)(state->lens[state->have - 1]);
00406                         copy = 3 + BITS(2);
00407                         DROPBITS(2);
00408                     }
00409                     else if (this.val == 17) {
00410                         NEEDBITS(this.bits + 3);
00411                         DROPBITS(this.bits);
00412                         len = 0;
00413                         copy = 3 + BITS(3);
00414                         DROPBITS(3);
00415                     }
00416                     else {
00417                         NEEDBITS(this.bits + 7);
00418                         DROPBITS(this.bits);
00419                         len = 0;
00420                         copy = 11 + BITS(7);
00421                         DROPBITS(7);
00422                     }
00423                     if (state->have + copy > state->nlen + state->ndist) {
00424                         strm->msg = (char *)"invalid bit length repeat";
00425                         mode = BAD;
00426                         break;
00427                     }
00428                     while (copy--)
00429                         state->lens[state->have++] = (unsigned short)len;
00430                 }
00431             }
00432 
00433             /* handle error breaks in while */
00434             if (mode == BAD) break;
00435 
00436             /* build code tables */
00437             state->next = state->codes;
00438             lencode = (code const FAR *)(state->next);
00439             lenbits = 9;
00440             ret = inflate_table9(LENS, state->lens, state->nlen,
00441                             &(state->next), &(lenbits), state->work);
00442             if (ret) {
00443                 strm->msg = (char *)"invalid literal/lengths set";
00444                 mode = BAD;
00445                 break;
00446             }
00447             distcode = (code const FAR *)(state->next);
00448             distbits = 6;
00449             ret = inflate_table9(DISTS, state->lens + state->nlen,
00450                             state->ndist, &(state->next), &(distbits),
00451                             state->work);
00452             if (ret) {
00453                 strm->msg = (char *)"invalid distances set";
00454                 mode = BAD;
00455                 break;
00456             }
00457             Tracev((stderr, "inflate:       codes ok\n"));
00458             mode = LEN;
00459 
00460         case LEN:
00461             /* get a literal, length, or end-of-block code */
00462             for (;;) {
00463                 this = lencode[BITS(lenbits)];
00464                 if ((unsigned)(this.bits) <= bits) break;
00465                 PULLBYTE();
00466             }
00467             if (this.op && (this.op & 0xf0) == 0) {
00468                 last = this;
00469                 for (;;) {
00470                     this = lencode[last.val +
00471                             (BITS(last.bits + last.op) >> last.bits)];
00472                     if ((unsigned)(last.bits + this.bits) <= bits) break;
00473                     PULLBYTE();
00474                 }
00475                 DROPBITS(last.bits);
00476             }
00477             DROPBITS(this.bits);
00478             length = (unsigned)this.val;
00479 
00480             /* process literal */
00481             if (this.op == 0) {
00482                 Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
00483                         "inflate:         literal '%c'\n" :
00484                         "inflate:         literal 0x%02x\n", this.val));
00485                 ROOM();
00486                 *put++ = (unsigned char)(length);
00487                 left--;
00488                 mode = LEN;
00489                 break;
00490             }
00491 
00492             /* process end of block */
00493             if (this.op & 32) {
00494                 Tracevv((stderr, "inflate:         end of block\n"));
00495                 mode = TYPE;
00496                 break;
00497             }
00498 
00499             /* invalid code */
00500             if (this.op & 64) {
00501                 strm->msg = (char *)"invalid literal/length code";
00502                 mode = BAD;
00503                 break;
00504             }
00505 
00506             /* length code -- get extra bits, if any */
00507             extra = (unsigned)(this.op) & 31;
00508             if (extra != 0) {
00509                 NEEDBITS(extra);
00510                 length += BITS(extra);
00511                 DROPBITS(extra);
00512             }
00513             Tracevv((stderr, "inflate:         length %lu\n", length));
00514 
00515             /* get distance code */
00516             for (;;) {
00517                 this = distcode[BITS(distbits)];
00518                 if ((unsigned)(this.bits) <= bits) break;
00519                 PULLBYTE();
00520             }
00521             if ((this.op & 0xf0) == 0) {
00522                 last = this;
00523                 for (;;) {
00524                     this = distcode[last.val +
00525                             (BITS(last.bits + last.op) >> last.bits)];
00526                     if ((unsigned)(last.bits + this.bits) <= bits) break;
00527                     PULLBYTE();
00528                 }
00529                 DROPBITS(last.bits);
00530             }
00531             DROPBITS(this.bits);
00532             if (this.op & 64) {
00533                 strm->msg = (char *)"invalid distance code";
00534                 mode = BAD;
00535                 break;
00536             }
00537             offset = (unsigned)this.val;
00538 
00539             /* get distance extra bits, if any */
00540             extra = (unsigned)(this.op) & 15;
00541             if (extra != 0) {
00542                 NEEDBITS(extra);
00543                 offset += BITS(extra);
00544                 DROPBITS(extra);
00545             }
00546             if (offset > WSIZE - (wrap ? 0: left)) {
00547                 strm->msg = (char *)"invalid distance too far back";
00548                 mode = BAD;
00549                 break;
00550             }
00551             Tracevv((stderr, "inflate:         distance %lu\n", offset));
00552 
00553             /* copy match from window to output */
00554             do {
00555                 ROOM();
00556                 copy = WSIZE - offset;
00557                 if (copy < left) {
00558                     from = put + copy;
00559                     copy = left - copy;
00560                 }
00561                 else {
00562                     from = put - offset;
00563                     copy = left;
00564                 }
00565                 if (copy > length) copy = length;
00566                 length -= copy;
00567                 left -= copy;
00568                 do {
00569                     *put++ = *from++;
00570                 } while (--copy);
00571             } while (length != 0);
00572             break;
00573 
00574         case DONE:
00575             /* inflate stream terminated properly -- write leftover output */
00576             ret = Z_STREAM_END;
00577             if (left < WSIZE) {
00578                 if (out(out_desc, window, (unsigned)(WSIZE - left)))
00579                     ret = Z_BUF_ERROR;
00580             }
00581             goto inf_leave;
00582 
00583         case BAD:
00584             ret = Z_DATA_ERROR;
00585             goto inf_leave;
00586 
00587         default:                /* can't happen, but makes compilers happy */
00588             ret = Z_STREAM_ERROR;
00589             goto inf_leave;
00590         }
00591 
00592     /* Return unused input */
00593   inf_leave:
00594     strm->next_in = next;
00595     strm->avail_in = have;
00596     return ret;
00597 }
00598 
00599 int ZEXPORT inflateBack9End(strm)
00600 z_stream FAR *strm;
00601 {
00602     if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
00603         return Z_STREAM_ERROR;
00604     ZFREE(strm, strm->state);
00605     strm->state = Z_NULL;
00606     Tracev((stderr, "inflate: end\n"));
00607     return Z_OK;
00608 }

Generated on Fri Apr 14 22:57:28 2006 for minix by  doxygen 1.4.6