stdlibs/libz/zlib/infback.cpp
changeset 59 09fa7c3c5079
parent 52 bf6a71c50e42
child 63 a117ad66e027
equal deleted inserted replaced
52:bf6a71c50e42 59:09fa7c3c5079
     1 /* infback.cpp -- inflate using a call-back interface
       
     2  * Copyright (C) 1995-2005 Mark Adler
       
     3  * For conditions of distribution and use, see copyright notice in zlib.h
       
     4  */
       
     5 
       
     6 /*
       
     7    This code is largely copied from inflate.c.  Normally either infback.o or
       
     8    inflate.o would be linked into an application--not both.  The interface
       
     9    with inffast.c is retained so that optimized assembler-coded versions of
       
    10    inflate_fast() can be used with either inflate.c or infback.c.
       
    11  */
       
    12 
       
    13 #include "zutil.h"
       
    14 #include "inftrees.h"
       
    15 #include "inflate.h"
       
    16 #include "inffast.h"
       
    17 
       
    18 /* function prototypes */
       
    19 local void fixedtables OF((struct inflate_state FAR *state));
       
    20 
       
    21 /*
       
    22    strm provides memory allocation functions in zalloc and zfree, or
       
    23    Z_NULL to use the library memory allocation functions.
       
    24 
       
    25    windowBits is in the range 8..15, and window is a user-supplied
       
    26    window and output buffer that is 2**windowBits bytes.
       
    27  */
       
    28 
       
    29 #ifdef __SYMBIAN32__
       
    30 EXPORT_C int inflateBackInit__r(z_streamp strm, int windowBits,unsigned char FAR *  window,const char *  version,int stream_size)
       
    31 #else
       
    32 int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size)
       
    33 z_streamp strm;
       
    34 int windowBits;
       
    35 unsigned char FAR *window;
       
    36 const char *version;
       
    37 int stream_size;
       
    38 #endif //__SYMBIAN32__
       
    39 {
       
    40     struct inflate_state FAR *state;
       
    41 
       
    42     if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
       
    43         stream_size != (int)(sizeof(z_stream)))
       
    44         return Z_VERSION_ERROR;
       
    45     if (strm == Z_NULL || window == Z_NULL ||
       
    46         windowBits < 8 || windowBits > 15)
       
    47         return Z_STREAM_ERROR;
       
    48     strm->msg = Z_NULL;                 /* in case we return an error */
       
    49     if (strm->zalloc == (alloc_func)0) {
       
    50         strm->zalloc = zcalloc;
       
    51         strm->opaque = (voidpf)0;
       
    52     }
       
    53     if (strm->zfree == (free_func)0) strm->zfree = zcfree;
       
    54     state = (struct inflate_state FAR *)ZALLOC(strm, 1,
       
    55                                                sizeof(struct inflate_state));
       
    56     if (state == Z_NULL) return Z_MEM_ERROR;
       
    57     Tracev((stderr, "inflate: allocated\n"));
       
    58     strm->state = (struct internal_state FAR *)state;
       
    59     state->dmax = 32768U;
       
    60     state->wbits = windowBits;
       
    61     state->wsize = 1U << windowBits;
       
    62     state->window = window;
       
    63     state->write = 0;
       
    64     state->whave = 0;
       
    65     return Z_OK;
       
    66 }
       
    67 
       
    68 
       
    69 /*
       
    70    Return state with length and distance decoding tables and index sizes set to
       
    71    fixed code decoding.  Normally this returns fixed tables from inffixed.h.
       
    72    If BUILDFIXED is defined, then instead this routine builds the tables the
       
    73    first time it's called, and returns those tables the first time and
       
    74    thereafter.  This reduces the size of the code by about 2K bytes, in
       
    75    exchange for a little execution time.  However, BUILDFIXED should not be
       
    76    used for threaded applications, since the rewriting of the tables and virgin
       
    77    may not be thread-safe.
       
    78  */
       
    79 
       
    80 #ifdef __SYMBIAN32__
       
    81 local void fixedtables(struct inflate_state FAR * state)
       
    82 #else
       
    83 local void fixedtables(state)
       
    84 struct inflate_state FAR *state;
       
    85 #endif //__SYMBIAN32__
       
    86 {
       
    87 #ifdef BUILDFIXED
       
    88     static int virgin = 1;
       
    89     static code *lenfix, *distfix;
       
    90     static code fixed[544];
       
    91 
       
    92     /* build fixed huffman tables if first call (may not be thread safe) */
       
    93     if (virgin) {
       
    94         unsigned sym, bits;
       
    95         static code *next;
       
    96 
       
    97         /* literal/length table */
       
    98         sym = 0;
       
    99         while (sym < 144) state->lens[sym++] = 8;
       
   100         while (sym < 256) state->lens[sym++] = 9;
       
   101         while (sym < 280) state->lens[sym++] = 7;
       
   102         while (sym < 288) state->lens[sym++] = 8;
       
   103         next = fixed;
       
   104         lenfix = next;
       
   105         bits = 9;
       
   106         inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work);
       
   107 
       
   108         /* distance table */
       
   109         sym = 0;
       
   110         while (sym < 32) state->lens[sym++] = 5;
       
   111         distfix = next;
       
   112         bits = 5;
       
   113         inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work);
       
   114 
       
   115         /* do this just once */
       
   116         virgin = 0;
       
   117     }
       
   118 #else /* !BUILDFIXED */
       
   119 #   include "inffixed.h"
       
   120 #endif /* BUILDFIXED */
       
   121     state->lencode = lenfix;
       
   122     state->lenbits = 9;
       
   123     state->distcode = distfix;
       
   124     state->distbits = 5;
       
   125 }
       
   126 
       
   127 
       
   128 /* Macros for inflateBack(): */
       
   129 
       
   130 /* Load returned state from inflate_fast() */
       
   131 #define LOAD() \
       
   132     do { \
       
   133         put = strm->next_out; \
       
   134         left = strm->avail_out; \
       
   135         next = strm->next_in; \
       
   136         have = strm->avail_in; \
       
   137         hold = state->hold; \
       
   138         bits = state->bits; \
       
   139     } while (0)
       
   140 
       
   141 /* Set state from registers for inflate_fast() */
       
   142 #define RESTORE() \
       
   143     do { \
       
   144         strm->next_out = put; \
       
   145         strm->avail_out = left; \
       
   146         strm->next_in = next; \
       
   147         strm->avail_in = have; \
       
   148         state->hold = hold; \
       
   149         state->bits = bits; \
       
   150     } while (0)
       
   151 
       
   152 /* Clear the input bit accumulator */
       
   153 #define INITBITS() \
       
   154     do { \
       
   155         hold = 0; \
       
   156         bits = 0; \
       
   157     } while (0)
       
   158 
       
   159 /* Assure that some input is available.  If input is requested, but denied,
       
   160    then return a Z_BUF_ERROR from inflateBack(). */
       
   161 #define PULL() \
       
   162     do { \
       
   163         if (have == 0) { \
       
   164             have = in(in_desc, &next); \
       
   165             if (have == 0) { \
       
   166                 next = Z_NULL; \
       
   167                 ret = Z_BUF_ERROR; \
       
   168                 goto inf_leave; \
       
   169             } \
       
   170         } \
       
   171     } while (0)
       
   172 
       
   173 /* Get a byte of input into the bit accumulator, or return from inflateBack()
       
   174    with an error if there is no input available. */
       
   175 #define PULLBYTE() \
       
   176     do { \
       
   177         PULL(); \
       
   178         have--; \
       
   179         hold += (unsigned long)(*next++) << bits; \
       
   180         bits += 8; \
       
   181     } while (0)
       
   182 
       
   183 /* Assure that there are at least n bits in the bit accumulator.  If there is
       
   184    not enough available input to do that, then return from inflateBack() with
       
   185    an error. */
       
   186 #define NEEDBITS(n) \
       
   187     do { \
       
   188         while (bits < (unsigned)(n)) \
       
   189             PULLBYTE(); \
       
   190     } while (0)
       
   191 
       
   192 /* Return the low n bits of the bit accumulator (n < 16) */
       
   193 #define BITS(n) \
       
   194     ((unsigned)hold & ((1U << (n)) - 1))
       
   195 
       
   196 /* Remove n bits from the bit accumulator */
       
   197 #define DROPBITS(n) \
       
   198     do { \
       
   199         hold >>= (n); \
       
   200         bits -= (unsigned)(n); \
       
   201     } while (0)
       
   202 
       
   203 /* Remove zero to seven bits as needed to go to a byte boundary */
       
   204 #define BYTEBITS() \
       
   205     do { \
       
   206         hold >>= bits & 7; \
       
   207         bits -= bits & 7; \
       
   208     } while (0)
       
   209 
       
   210 /* Assure that some output space is available, by writing out the window
       
   211    if it's full.  If the write fails, return from inflateBack() with a
       
   212    Z_BUF_ERROR. */
       
   213 #define ROOM() \
       
   214     do { \
       
   215         if (left == 0) { \
       
   216             put = state->window; \
       
   217             left = state->wsize; \
       
   218             state->whave = left; \
       
   219             if (out(out_desc, put, left)) { \
       
   220                 ret = Z_BUF_ERROR; \
       
   221                 goto inf_leave; \
       
   222             } \
       
   223         } \
       
   224     } while (0)
       
   225 
       
   226 /*
       
   227    strm provides the memory allocation functions and window buffer on input,
       
   228    and provides information on the unused input on return.  For Z_DATA_ERROR
       
   229    returns, strm will also provide an error message.
       
   230 
       
   231    in() and out() are the call-back input and output functions.  When
       
   232    inflateBack() needs more input, it calls in().  When inflateBack() has
       
   233    filled the window with output, or when it completes with data in the
       
   234    window, it calls out() to write out the data.  The application must not
       
   235    change the provided input until in() is called again or inflateBack()
       
   236    returns.  The application must not change the window/output buffer until
       
   237    inflateBack() returns.
       
   238 
       
   239    in() and out() are called with a descriptor parameter provided in the
       
   240    inflateBack() call.  This parameter can be a structure that provides the
       
   241    information required to do the read or write, as well as accumulated
       
   242    information on the input and output such as totals and check values.
       
   243 
       
   244    in() should return zero on failure.  out() should return non-zero on
       
   245    failure.  If either in() or out() fails, than inflateBack() returns a
       
   246    Z_BUF_ERROR.  strm->next_in can be checked for Z_NULL to see whether it
       
   247    was in() or out() that caused in the error.  Otherwise,  inflateBack()
       
   248    returns Z_STREAM_END on success, Z_DATA_ERROR for an deflate format
       
   249    error, or Z_MEM_ERROR if it could not allocate memory for the state.
       
   250    inflateBack() can also return Z_STREAM_ERROR if the input parameters
       
   251    are not correct, i.e. strm is Z_NULL or the state was not initialized.
       
   252  */
       
   253 
       
   254 #ifdef __SYMBIAN32__
       
   255 EXPORT_C int inflateBack_r(z_streamp strm,in_func  in, void FAR * in_desc,out_func  out,void FAR * out_desc)
       
   256 #else
       
   257 int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc)
       
   258 z_streamp strm;
       
   259 in_func in;
       
   260 void FAR *in_desc;
       
   261 out_func out;
       
   262 void FAR *out_desc;
       
   263 #endif //__SYMBIAN32__
       
   264 {
       
   265     struct inflate_state FAR *state;
       
   266     unsigned char FAR *next;    /* next input */
       
   267     unsigned char FAR *put;     /* next output */
       
   268     unsigned have, left;        /* available input and output */
       
   269     unsigned long hold;         /* bit buffer */
       
   270     unsigned bits;              /* bits in bit buffer */
       
   271     unsigned copy;              /* number of stored or match bytes to copy */
       
   272     unsigned char FAR *from;    /* where to copy match bytes from */
       
   273     
       
   274 /*  Need to replace "this" variable with "current" as "this" is a reserved 
       
   275  *  keyword in C++ which is prefectly fine for a c code. As this file
       
   276  *  has been changed to C++ "this" needs to be changed.
       
   277  */ 
       
   278 #   define this current      
       
   279     code this;                  /* current decoding table entry */
       
   280     code last;                  /* parent table entry */
       
   281     unsigned len;               /* length to copy for repeats, bits to drop */
       
   282     int ret;                    /* return code */
       
   283     static const unsigned short order[19] = /* permutation of code lengths */
       
   284         {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
       
   285 
       
   286     /* Check that the strm exists and that the state was initialized */
       
   287     if (strm == Z_NULL || strm->state == Z_NULL)
       
   288         return Z_STREAM_ERROR;
       
   289     state = (struct inflate_state FAR *)strm->state;
       
   290 
       
   291     /* Reset the state */
       
   292     strm->msg = Z_NULL;
       
   293     state->mode = TYPE;
       
   294     state->last = 0;
       
   295     state->whave = 0;
       
   296     next = strm->next_in;
       
   297     have = next != Z_NULL ? strm->avail_in : 0;
       
   298     hold = 0;
       
   299     bits = 0;
       
   300     put = state->window;
       
   301     left = state->wsize;
       
   302 
       
   303     /* Inflate until end of block marked as last */
       
   304     for (;;)
       
   305         switch (state->mode) {
       
   306         case TYPE:
       
   307             /* determine and dispatch block type */
       
   308             if (state->last) {
       
   309                 BYTEBITS();
       
   310                 state->mode = DONE;
       
   311                 break;
       
   312             }
       
   313             NEEDBITS(3);
       
   314             state->last = BITS(1);
       
   315             DROPBITS(1);
       
   316             switch (BITS(2)) {
       
   317             case 0:                             /* stored block */
       
   318                 Tracev((stderr, "inflate:     stored block%s\n",
       
   319                         state->last ? " (last)" : ""));
       
   320                 state->mode = STORED;
       
   321                 break;
       
   322             case 1:                             /* fixed block */
       
   323                 fixedtables(state);
       
   324                 Tracev((stderr, "inflate:     fixed codes block%s\n",
       
   325                         state->last ? " (last)" : ""));
       
   326                 state->mode = LEN;              /* decode codes */
       
   327                 break;
       
   328             case 2:                             /* dynamic block */
       
   329                 Tracev((stderr, "inflate:     dynamic codes block%s\n",
       
   330                         state->last ? " (last)" : ""));
       
   331                 state->mode = TABLE;
       
   332                 break;
       
   333             case 3:
       
   334                 strm->msg = (char *)"invalid block type";
       
   335                 state->mode = BAD;
       
   336             }
       
   337             DROPBITS(2);
       
   338             break;
       
   339 
       
   340         case STORED:
       
   341             /* get and verify stored block length */
       
   342             BYTEBITS();                         /* go to byte boundary */
       
   343             NEEDBITS(32);
       
   344             if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) {
       
   345                 strm->msg = (char *)"invalid stored block lengths";
       
   346                 state->mode = BAD;
       
   347                 break;
       
   348             }
       
   349             state->length = (unsigned)hold & 0xffff;
       
   350             Tracev((stderr, "inflate:       stored length %u\n",
       
   351                     state->length));
       
   352             INITBITS();
       
   353 
       
   354             /* copy stored block from input to output */
       
   355             while (state->length != 0) {
       
   356                 copy = state->length;
       
   357                 PULL();
       
   358                 ROOM();
       
   359                 if (copy > have) copy = have;
       
   360                 if (copy > left) copy = left;
       
   361                 zmemcpy(put, next, copy);
       
   362                 have -= copy;
       
   363                 next += copy;
       
   364                 left -= copy;
       
   365                 put += copy;
       
   366                 state->length -= copy;
       
   367             }
       
   368             Tracev((stderr, "inflate:       stored end\n"));
       
   369             state->mode = TYPE;
       
   370             break;
       
   371 
       
   372         case TABLE:
       
   373             /* get dynamic table entries descriptor */
       
   374             NEEDBITS(14);
       
   375             state->nlen = BITS(5) + 257;
       
   376             DROPBITS(5);
       
   377             state->ndist = BITS(5) + 1;
       
   378             DROPBITS(5);
       
   379             state->ncode = BITS(4) + 4;
       
   380             DROPBITS(4);
       
   381 #ifndef PKZIP_BUG_WORKAROUND
       
   382             if (state->nlen > 286 || state->ndist > 30) {
       
   383                 strm->msg = (char *)"too many length or distance symbols";
       
   384                 state->mode = BAD;
       
   385                 break;
       
   386             }
       
   387 #endif
       
   388             Tracev((stderr, "inflate:       table sizes ok\n"));
       
   389 
       
   390             /* get code length code lengths (not a typo) */
       
   391             state->have = 0;
       
   392             while (state->have < state->ncode) {
       
   393                 NEEDBITS(3);
       
   394                 state->lens[order[state->have++]] = (unsigned short)BITS(3);
       
   395                 DROPBITS(3);
       
   396             }
       
   397             while (state->have < 19)
       
   398                 state->lens[order[state->have++]] = 0;
       
   399             state->next = state->codes;
       
   400             state->lencode = (code const FAR *)(state->next);
       
   401             state->lenbits = 7;
       
   402             ret = inflate_table(CODES, state->lens, 19, &(state->next),
       
   403                                 &(state->lenbits), state->work);
       
   404             if (ret) {
       
   405                 strm->msg = (char *)"invalid code lengths set";
       
   406                 state->mode = BAD;
       
   407                 break;
       
   408             }
       
   409             Tracev((stderr, "inflate:       code lengths ok\n"));
       
   410 
       
   411             /* get length and distance code code lengths */
       
   412             state->have = 0;
       
   413             while (state->have < state->nlen + state->ndist) {
       
   414                 for (;;) {
       
   415                     this = state->lencode[BITS(state->lenbits)];
       
   416                     if ((unsigned)(this.bits) <= bits) break;
       
   417                     PULLBYTE();
       
   418                 }
       
   419                 if (this.val < 16) {
       
   420                     NEEDBITS(this.bits);
       
   421                     DROPBITS(this.bits);
       
   422                     state->lens[state->have++] = this.val;
       
   423                 }
       
   424                 else {
       
   425                     if (this.val == 16) {
       
   426                         NEEDBITS(this.bits + 2);
       
   427                         DROPBITS(this.bits);
       
   428                         if (state->have == 0) {
       
   429                             strm->msg = (char *)"invalid bit length repeat";
       
   430                             state->mode = BAD;
       
   431                             break;
       
   432                         }
       
   433                         len = (unsigned)(state->lens[state->have - 1]);
       
   434                         copy = 3 + BITS(2);
       
   435                         DROPBITS(2);
       
   436                     }
       
   437                     else if (this.val == 17) {
       
   438                         NEEDBITS(this.bits + 3);
       
   439                         DROPBITS(this.bits);
       
   440                         len = 0;
       
   441                         copy = 3 + BITS(3);
       
   442                         DROPBITS(3);
       
   443                     }
       
   444                     else {
       
   445                         NEEDBITS(this.bits + 7);
       
   446                         DROPBITS(this.bits);
       
   447                         len = 0;
       
   448                         copy = 11 + BITS(7);
       
   449                         DROPBITS(7);
       
   450                     }
       
   451                     if (state->have + copy > state->nlen + state->ndist) {
       
   452                         strm->msg = (char *)"invalid bit length repeat";
       
   453                         state->mode = BAD;
       
   454                         break;
       
   455                     }
       
   456                     while (copy--)
       
   457                         state->lens[state->have++] = (unsigned short)len;
       
   458                 }
       
   459             }
       
   460 
       
   461             /* handle error breaks in while */
       
   462             if (state->mode == BAD) break;
       
   463 
       
   464             /* build code tables */
       
   465             state->next = state->codes;
       
   466             state->lencode = (code const FAR *)(state->next);
       
   467             state->lenbits = 9;
       
   468             ret = inflate_table(LENS, state->lens, state->nlen, &(state->next),
       
   469                                 &(state->lenbits), state->work);
       
   470             if (ret) {
       
   471                 strm->msg = (char *)"invalid literal/lengths set";
       
   472                 state->mode = BAD;
       
   473                 break;
       
   474             }
       
   475             state->distcode = (code const FAR *)(state->next);
       
   476             state->distbits = 6;
       
   477             ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist,
       
   478                             &(state->next), &(state->distbits), state->work);
       
   479             if (ret) {
       
   480                 strm->msg = (char *)"invalid distances set";
       
   481                 state->mode = BAD;
       
   482                 break;
       
   483             }
       
   484             Tracev((stderr, "inflate:       codes ok\n"));
       
   485             state->mode = LEN;
       
   486 
       
   487         case LEN:
       
   488             /* use inflate_fast() if we have enough input and output */
       
   489             if (have >= 6 && left >= 258) {
       
   490                 RESTORE();
       
   491                 if (state->whave < state->wsize)
       
   492                     state->whave = state->wsize - left;
       
   493                 inflate_fast(strm, state->wsize);
       
   494                 LOAD();
       
   495                 break;
       
   496             }
       
   497 
       
   498             /* get a literal, length, or end-of-block code */
       
   499             for (;;) {
       
   500                 this = state->lencode[BITS(state->lenbits)];
       
   501                 if ((unsigned)(this.bits) <= bits) break;
       
   502                 PULLBYTE();
       
   503             }
       
   504             if (this.op && (this.op & 0xf0) == 0) {
       
   505                 last = this;
       
   506                 for (;;) {
       
   507                     this = state->lencode[last.val +
       
   508                             (BITS(last.bits + last.op) >> last.bits)];
       
   509                     if ((unsigned)(last.bits + this.bits) <= bits) break;
       
   510                     PULLBYTE();
       
   511                 }
       
   512                 DROPBITS(last.bits);
       
   513             }
       
   514             DROPBITS(this.bits);
       
   515             state->length = (unsigned)this.val;
       
   516 
       
   517             /* process literal */
       
   518             if (this.op == 0) {
       
   519                 Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ?
       
   520                         "inflate:         literal '%c'\n" :
       
   521                         "inflate:         literal 0x%02x\n", this.val));
       
   522                 ROOM();
       
   523                 *put++ = (unsigned char)(state->length);
       
   524                 left--;
       
   525                 state->mode = LEN;
       
   526                 break;
       
   527             }
       
   528 
       
   529             /* process end of block */
       
   530             if (this.op & 32) {
       
   531                 Tracevv((stderr, "inflate:         end of block\n"));
       
   532                 state->mode = TYPE;
       
   533                 break;
       
   534             }
       
   535 
       
   536             /* invalid code */
       
   537             if (this.op & 64) {
       
   538                 strm->msg = (char *)"invalid literal/length code";
       
   539                 state->mode = BAD;
       
   540                 break;
       
   541             }
       
   542 
       
   543             /* length code -- get extra bits, if any */
       
   544             state->extra = (unsigned)(this.op) & 15;
       
   545             if (state->extra != 0) {
       
   546                 NEEDBITS(state->extra);
       
   547                 state->length += BITS(state->extra);
       
   548                 DROPBITS(state->extra);
       
   549             }
       
   550             Tracevv((stderr, "inflate:         length %u\n", state->length));
       
   551 
       
   552             /* get distance code */
       
   553             for (;;) {
       
   554                 this = state->distcode[BITS(state->distbits)];
       
   555                 if ((unsigned)(this.bits) <= bits) break;
       
   556                 PULLBYTE();
       
   557             }
       
   558             if ((this.op & 0xf0) == 0) {
       
   559                 last = this;
       
   560                 for (;;) {
       
   561                     this = state->distcode[last.val +
       
   562                             (BITS(last.bits + last.op) >> last.bits)];
       
   563                     if ((unsigned)(last.bits + this.bits) <= bits) break;
       
   564                     PULLBYTE();
       
   565                 }
       
   566                 DROPBITS(last.bits);
       
   567             }
       
   568             DROPBITS(this.bits);
       
   569             if (this.op & 64) {
       
   570                 strm->msg = (char *)"invalid distance code";
       
   571                 state->mode = BAD;
       
   572                 break;
       
   573             }
       
   574             state->offset = (unsigned)this.val;
       
   575 
       
   576             /* get distance extra bits, if any */
       
   577             state->extra = (unsigned)(this.op) & 15;
       
   578             if (state->extra != 0) {
       
   579                 NEEDBITS(state->extra);
       
   580                 state->offset += BITS(state->extra);
       
   581                 DROPBITS(state->extra);
       
   582             }
       
   583             if (state->offset > state->wsize - (state->whave < state->wsize ?
       
   584                                                 left : 0)) {
       
   585                 strm->msg = (char *)"invalid distance too far back";
       
   586                 state->mode = BAD;
       
   587                 break;
       
   588             }
       
   589             Tracevv((stderr, "inflate:         distance %u\n", state->offset));
       
   590 
       
   591             /* copy match from window to output */
       
   592             do {
       
   593                 ROOM();
       
   594                 copy = state->wsize - state->offset;
       
   595                 if (copy < left) {
       
   596                     from = put + copy;
       
   597                     copy = left - copy;
       
   598                 }
       
   599                 else {
       
   600                     from = put - state->offset;
       
   601                     copy = left;
       
   602                 }
       
   603                 if (copy > state->length) copy = state->length;
       
   604                 state->length -= copy;
       
   605                 left -= copy;
       
   606                 do {
       
   607                     *put++ = *from++;
       
   608                 } while (--copy);
       
   609             } while (state->length != 0);
       
   610             break;
       
   611 
       
   612         case DONE:
       
   613             /* inflate stream terminated properly -- write leftover output */
       
   614             ret = Z_STREAM_END;
       
   615             if (left < state->wsize) {
       
   616                 if (out(out_desc, state->window, state->wsize - left))
       
   617                     ret = Z_BUF_ERROR;
       
   618             }
       
   619             goto inf_leave;
       
   620 
       
   621         case BAD:
       
   622             ret = Z_DATA_ERROR;
       
   623             goto inf_leave;
       
   624 
       
   625         default:                /* can't happen, but makes compilers happy */
       
   626             ret = Z_STREAM_ERROR;
       
   627             goto inf_leave;
       
   628         }
       
   629 
       
   630     /* Return unused input */
       
   631   inf_leave:
       
   632     strm->next_in = next;
       
   633     strm->avail_in = have;
       
   634     return ret;
       
   635 }
       
   636 
       
   637 
       
   638 #ifdef __SYMBIAN32__
       
   639 EXPORT_C int  inflateBackEnd_r(z_streamp strm)
       
   640 #else
       
   641 int ZEXPORT inflateBackEnd(strm)
       
   642 z_streamp strm;
       
   643  #endif //__SYMBIAN32__
       
   644 {
       
   645     if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
       
   646         return Z_STREAM_ERROR;
       
   647     ZFREE(strm, strm->state);
       
   648     strm->state = Z_NULL;
       
   649     Tracev((stderr, "inflate: end\n"));
       
   650     return Z_OK;
       
   651 }