diff options
Diffstat (limited to 'dep/zlib/deflate.c')
| -rw-r--r-- | dep/zlib/deflate.c | 259 | 
1 files changed, 195 insertions, 64 deletions
diff --git a/dep/zlib/deflate.c b/dep/zlib/deflate.c index 5c4022f3d47..9e4c2cbc8af 100644 --- a/dep/zlib/deflate.c +++ b/dep/zlib/deflate.c @@ -1,5 +1,5 @@  /* deflate.c -- compress data using the deflation algorithm - * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + * Copyright (C) 1995-2012 Jean-loup Gailly and Mark Adler   * For conditions of distribution and use, see copyright notice in zlib.h   */ @@ -37,7 +37,7 @@   *  REFERENCES   *   *      Deutsch, L.P.,"DEFLATE Compressed Data Format Specification". - *      Available in http://www.ietf.org/rfc/rfc1951.txt + *      Available in http://tools.ietf.org/html/rfc1951   *   *      A description of the Rabin and Karp algorithm is given in the book   *         "Algorithms" by R. Sedgewick, Addison-Wesley, p252. @@ -52,7 +52,7 @@  #include "deflate.h"  const char deflate_copyright[] = -   " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler "; +   " deflate 1.2.7 Copyright 1995-2012 Jean-loup Gailly and Mark Adler ";  /*    If you use the zlib library in a product, an acknowledgment is welcome    in the documentation of your product. If for some reason you cannot @@ -155,6 +155,9 @@ local const config configuration_table[10] = {  struct static_tree_desc_s {int dummy;}; /* for buggy compilers */  #endif +/* rank Z_BLOCK between Z_NO_FLUSH and Z_PARTIAL_FLUSH */ +#define RANK(f) (((f) << 1) - ((f) > 4 ? 9 : 0)) +  /* ===========================================================================   * Update a hash value with the given input byte   * IN  assertion: all calls to to UPDATE_HASH are made with consecutive @@ -235,10 +238,19 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,      strm->msg = Z_NULL;      if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO +        return Z_STREAM_ERROR; +#else          strm->zalloc = zcalloc;          strm->opaque = (voidpf)0; +#endif      } -    if (strm->zfree == (free_func)0) strm->zfree = zcfree; +    if (strm->zfree == (free_func)0) +#ifdef Z_SOLO +        return Z_STREAM_ERROR; +#else +        strm->zfree = zcfree; +#endif  #ifdef FASTEST      if (level != 0) level = 1; @@ -314,43 +326,70 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)      uInt  dictLength;  {      deflate_state *s; -    uInt length = dictLength; -    uInt n; -    IPos hash_head = 0; +    uInt str, n; +    int wrap; +    unsigned avail; +    unsigned char *next; -    if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL || -        strm->state->wrap == 2 || -        (strm->state->wrap == 1 && strm->state->status != INIT_STATE)) +    if (strm == Z_NULL || strm->state == Z_NULL || dictionary == Z_NULL)          return Z_STREAM_ERROR; -      s = strm->state; -    if (s->wrap) -        strm->adler = adler32(strm->adler, dictionary, dictLength); +    wrap = s->wrap; +    if (wrap == 2 || (wrap == 1 && s->status != INIT_STATE) || s->lookahead) +        return Z_STREAM_ERROR; -    if (length < MIN_MATCH) return Z_OK; -    if (length > s->w_size) { -        length = s->w_size; -        dictionary += dictLength - length; /* use the tail of the dictionary */ +    /* when using zlib wrappers, compute Adler-32 for provided dictionary */ +    if (wrap == 1) +        strm->adler = adler32(strm->adler, dictionary, dictLength); +    s->wrap = 0;                    /* avoid computing Adler-32 in read_buf */ + +    /* if dictionary would fill window, just replace the history */ +    if (dictLength >= s->w_size) { +        if (wrap == 0) {            /* already empty otherwise */ +            CLEAR_HASH(s); +            s->strstart = 0; +            s->block_start = 0L; +            s->insert = 0; +        } +        dictionary += dictLength - s->w_size;  /* use the tail */ +        dictLength = s->w_size;      } -    zmemcpy(s->window, dictionary, length); -    s->strstart = length; -    s->block_start = (long)length; -    /* Insert all strings in the hash table (except for the last two bytes). -     * s->lookahead stays null, so s->ins_h will be recomputed at the next -     * call of fill_window. -     */ -    s->ins_h = s->window[0]; -    UPDATE_HASH(s, s->ins_h, s->window[1]); -    for (n = 0; n <= length - MIN_MATCH; n++) { -        INSERT_STRING(s, n, hash_head); +    /* insert dictionary into window and hash */ +    avail = strm->avail_in; +    next = strm->next_in; +    strm->avail_in = dictLength; +    strm->next_in = (Bytef *)dictionary; +    fill_window(s); +    while (s->lookahead >= MIN_MATCH) { +        str = s->strstart; +        n = s->lookahead - (MIN_MATCH-1); +        do { +            UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST +            s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif +            s->head[s->ins_h] = (Pos)str; +            str++; +        } while (--n); +        s->strstart = str; +        s->lookahead = MIN_MATCH-1; +        fill_window(s);      } -    if (hash_head) hash_head = 0;  /* to make compiler happy */ +    s->strstart += s->lookahead; +    s->block_start = (long)s->strstart; +    s->insert = s->lookahead; +    s->lookahead = 0; +    s->match_length = s->prev_length = MIN_MATCH-1; +    s->match_available = 0; +    strm->next_in = next; +    strm->avail_in = avail; +    s->wrap = wrap;      return Z_OK;  }  /* ========================================================================= */ -int ZEXPORT deflateReset (strm) +int ZEXPORT deflateResetKeep (strm)      z_streamp strm;  {      deflate_state *s; @@ -380,12 +419,23 @@ int ZEXPORT deflateReset (strm)      s->last_flush = Z_NO_FLUSH;      _tr_init(s); -    lm_init(s);      return Z_OK;  }  /* ========================================================================= */ +int ZEXPORT deflateReset (strm) +    z_streamp strm; +{ +    int ret; + +    ret = deflateResetKeep(strm); +    if (ret == Z_OK) +        lm_init(strm->state); +    return ret; +} + +/* ========================================================================= */  int ZEXPORT deflateSetHeader (strm, head)      z_streamp strm;      gz_headerp head; @@ -397,14 +447,42 @@ int ZEXPORT deflateSetHeader (strm, head)  }  /* ========================================================================= */ +int ZEXPORT deflatePending (strm, pending, bits) +    unsigned *pending; +    int *bits; +    z_streamp strm; +{ +    if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; +    if (pending != Z_NULL) +        *pending = strm->state->pending; +    if (bits != Z_NULL) +        *bits = strm->state->bi_valid; +    return Z_OK; +} + +/* ========================================================================= */  int ZEXPORT deflatePrime (strm, bits, value)      z_streamp strm;      int bits;      int value;  { +    deflate_state *s; +    int put; +      if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; -    strm->state->bi_valid = bits; -    strm->state->bi_buf = (ush)(value & ((1 << bits) - 1)); +    s = strm->state; +    if ((Bytef *)(s->d_buf) < s->pending_out + ((Buf_size + 7) >> 3)) +        return Z_BUF_ERROR; +    do { +        put = Buf_size - s->bi_valid; +        if (put > bits) +            put = bits; +        s->bi_buf |= (ush)((value & ((1 << put) - 1)) << s->bi_valid); +        s->bi_valid += put; +        _tr_flush_bits(s); +        value >>= put; +        bits -= put; +    } while (bits);      return Z_OK;  } @@ -562,19 +640,22 @@ local void putShortMSB (s, b)  local void flush_pending(strm)      z_streamp strm;  { -    unsigned len = strm->state->pending; +    unsigned len; +    deflate_state *s = strm->state; +    _tr_flush_bits(s); +    len = s->pending;      if (len > strm->avail_out) len = strm->avail_out;      if (len == 0) return; -    zmemcpy(strm->next_out, strm->state->pending_out, len); +    zmemcpy(strm->next_out, s->pending_out, len);      strm->next_out  += len; -    strm->state->pending_out  += len; +    s->pending_out  += len;      strm->total_out += len;      strm->avail_out  -= len; -    strm->state->pending -= len; -    if (strm->state->pending == 0) { -        strm->state->pending_out = strm->state->pending_buf; +    s->pending -= len; +    if (s->pending == 0) { +        s->pending_out = s->pending_buf;      }  } @@ -801,7 +882,7 @@ int ZEXPORT deflate (strm, flush)       * flushes. For repeated and useless calls with Z_FINISH, we keep       * returning Z_STREAM_END instead of Z_BUF_ERROR.       */ -    } else if (strm->avail_in == 0 && flush <= old_flush && +    } else if (strm->avail_in == 0 && RANK(flush) <= RANK(old_flush) &&                 flush != Z_FINISH) {          ERR_RETURN(strm, Z_BUF_ERROR);      } @@ -850,6 +931,7 @@ int ZEXPORT deflate (strm, flush)                      if (s->lookahead == 0) {                          s->strstart = 0;                          s->block_start = 0L; +                        s->insert = 0;                      }                  }              } @@ -945,12 +1027,12 @@ int ZEXPORT deflateCopy (dest, source)      ss = source->state; -    zmemcpy(dest, source, sizeof(z_stream)); +    zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream));      ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));      if (ds == Z_NULL) return Z_MEM_ERROR;      dest->state = (struct internal_state FAR *) ds; -    zmemcpy(ds, ss, sizeof(deflate_state)); +    zmemcpy((voidpf)ds, (voidpf)ss, sizeof(deflate_state));      ds->strm = dest;      ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); @@ -966,8 +1048,8 @@ int ZEXPORT deflateCopy (dest, source)      }      /* following zmemcpy do not work for 16-bit MSDOS */      zmemcpy(ds->window, ss->window, ds->w_size * 2 * sizeof(Byte)); -    zmemcpy(ds->prev, ss->prev, ds->w_size * sizeof(Pos)); -    zmemcpy(ds->head, ss->head, ds->hash_size * sizeof(Pos)); +    zmemcpy((voidpf)ds->prev, (voidpf)ss->prev, ds->w_size * sizeof(Pos)); +    zmemcpy((voidpf)ds->head, (voidpf)ss->head, ds->hash_size * sizeof(Pos));      zmemcpy(ds->pending_buf, ss->pending_buf, (uInt)ds->pending_buf_size);      ds->pending_out = ds->pending_buf + (ss->pending_out - ss->pending_buf); @@ -1001,15 +1083,15 @@ local int read_buf(strm, buf, size)      strm->avail_in  -= len; +    zmemcpy(buf, strm->next_in, len);      if (strm->state->wrap == 1) { -        strm->adler = adler32(strm->adler, strm->next_in, len); +        strm->adler = adler32(strm->adler, buf, len);      }  #ifdef GZIP      else if (strm->state->wrap == 2) { -        strm->adler = crc32(strm->adler, strm->next_in, len); +        strm->adler = crc32(strm->adler, buf, len);      }  #endif -    zmemcpy(buf, strm->next_in, len);      strm->next_in  += len;      strm->total_in += len; @@ -1036,6 +1118,7 @@ local void lm_init (s)      s->strstart = 0;      s->block_start = 0L;      s->lookahead = 0; +    s->insert = 0;      s->match_length = s->prev_length = MIN_MATCH-1;      s->match_available = 0;      s->ins_h = 0; @@ -1310,6 +1393,8 @@ local void fill_window(s)      unsigned more;    /* Amount of free space at the end of the window. */      uInt wsize = s->w_size; +    Assert(s->lookahead < MIN_LOOKAHEAD, "already enough lookahead"); +      do {          more = (unsigned)(s->window_size -(ulg)s->lookahead -(ulg)s->strstart); @@ -1362,7 +1447,7 @@ local void fill_window(s)  #endif              more += wsize;          } -        if (s->strm->avail_in == 0) return; +        if (s->strm->avail_in == 0) break;          /* If there was no sliding:           *    strstart <= WSIZE+MAX_DIST-1 && lookahead <= MIN_LOOKAHEAD - 1 && @@ -1381,12 +1466,24 @@ local void fill_window(s)          s->lookahead += n;          /* Initialize the hash value now that we have some input: */ -        if (s->lookahead >= MIN_MATCH) { -            s->ins_h = s->window[s->strstart]; -            UPDATE_HASH(s, s->ins_h, s->window[s->strstart+1]); +        if (s->lookahead + s->insert >= MIN_MATCH) { +            uInt str = s->strstart - s->insert; +            s->ins_h = s->window[str]; +            UPDATE_HASH(s, s->ins_h, s->window[str + 1]);  #if MIN_MATCH != 3              Call UPDATE_HASH() MIN_MATCH-3 more times  #endif +            while (s->insert) { +                UPDATE_HASH(s, s->ins_h, s->window[str + MIN_MATCH-1]); +#ifndef FASTEST +                s->prev[str & s->w_mask] = s->head[s->ins_h]; +#endif +                s->head[s->ins_h] = (Pos)str; +                str++; +                s->insert--; +                if (s->lookahead + s->insert < MIN_MATCH) +                    break; +            }          }          /* If the whole input has less than MIN_MATCH bytes, ins_h is garbage,           * but this is not important since only literal bytes will be emitted. @@ -1427,6 +1524,9 @@ local void fill_window(s)              s->high_water += init;          }      } + +    Assert((ulg)s->strstart <= s->window_size - MIN_LOOKAHEAD, +           "not enough room for search");  }  /* =========================================================================== @@ -1506,8 +1606,14 @@ local block_state deflate_stored(s, flush)              FLUSH_BLOCK(s, 0);          }      } -    FLUSH_BLOCK(s, flush == Z_FINISH); -    return flush == Z_FINISH ? finish_done : block_done; +    s->insert = 0; +    if (flush == Z_FINISH) { +        FLUSH_BLOCK(s, 1); +        return finish_done; +    } +    if ((long)s->strstart > s->block_start) +        FLUSH_BLOCK(s, 0); +    return block_done;  }  /* =========================================================================== @@ -1603,8 +1709,14 @@ local block_state deflate_fast(s, flush)          }          if (bflush) FLUSH_BLOCK(s, 0);      } -    FLUSH_BLOCK(s, flush == Z_FINISH); -    return flush == Z_FINISH ? finish_done : block_done; +    s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; +    if (flush == Z_FINISH) { +        FLUSH_BLOCK(s, 1); +        return finish_done; +    } +    if (s->last_lit) +        FLUSH_BLOCK(s, 0); +    return block_done;  }  #ifndef FASTEST @@ -1728,8 +1840,14 @@ local block_state deflate_slow(s, flush)          _tr_tally_lit(s, s->window[s->strstart-1], bflush);          s->match_available = 0;      } -    FLUSH_BLOCK(s, flush == Z_FINISH); -    return flush == Z_FINISH ? finish_done : block_done; +    s->insert = s->strstart < MIN_MATCH-1 ? s->strstart : MIN_MATCH-1; +    if (flush == Z_FINISH) { +        FLUSH_BLOCK(s, 1); +        return finish_done; +    } +    if (s->last_lit) +        FLUSH_BLOCK(s, 0); +    return block_done;  }  #endif /* FASTEST */ @@ -1749,11 +1867,11 @@ local block_state deflate_rle(s, flush)      for (;;) {          /* Make sure that we always have enough lookahead, except           * at the end of the input file. We need MAX_MATCH bytes -         * for the longest encodable run. +         * for the longest run, plus one for the unrolled loop.           */ -        if (s->lookahead < MAX_MATCH) { +        if (s->lookahead <= MAX_MATCH) {              fill_window(s); -            if (s->lookahead < MAX_MATCH && flush == Z_NO_FLUSH) { +            if (s->lookahead <= MAX_MATCH && flush == Z_NO_FLUSH) {                  return need_more;              }              if (s->lookahead == 0) break; /* flush the current block */ @@ -1776,6 +1894,7 @@ local block_state deflate_rle(s, flush)                  if (s->match_length > s->lookahead)                      s->match_length = s->lookahead;              } +            Assert(scan <= s->window+(uInt)(s->window_size-1), "wild scan");          }          /* Emit match if have run of MIN_MATCH or longer, else emit literal */ @@ -1796,8 +1915,14 @@ local block_state deflate_rle(s, flush)          }          if (bflush) FLUSH_BLOCK(s, 0);      } -    FLUSH_BLOCK(s, flush == Z_FINISH); -    return flush == Z_FINISH ? finish_done : block_done; +    s->insert = 0; +    if (flush == Z_FINISH) { +        FLUSH_BLOCK(s, 1); +        return finish_done; +    } +    if (s->last_lit) +        FLUSH_BLOCK(s, 0); +    return block_done;  }  /* =========================================================================== @@ -1829,6 +1954,12 @@ local block_state deflate_huff(s, flush)          s->strstart++;          if (bflush) FLUSH_BLOCK(s, 0);      } -    FLUSH_BLOCK(s, flush == Z_FINISH); -    return flush == Z_FINISH ? finish_done : block_done; +    s->insert = 0; +    if (flush == Z_FINISH) { +        FLUSH_BLOCK(s, 1); +        return finish_done; +    } +    if (s->last_lit) +        FLUSH_BLOCK(s, 0); +    return block_done;  }  | 
