123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808 |
- /* deflate.c -- compress data using the deflation algorithm
- Copyright (C) 1999, 2006, 2012 Free Software Foundation, Inc.
- Copyright (C) 1992-1993 Jean-loup Gailly
- Copyright (C) 2008 Josh Triplett
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
- /*
- * PURPOSE
- *
- * Identify new text as repetitions of old text within a fixed-
- * length sliding window trailing behind the new text.
- *
- * DISCUSSION
- *
- * The "deflation" process depends on being able to identify portions
- * of the input text which are identical to earlier input (within a
- * sliding window trailing behind the input currently being processed).
- *
- * The most straightforward technique turns out to be the fastest for
- * most input files: try all possible matches and select the longest.
- * The key feature of this algorithm is that insertions into the string
- * dictionary are very simple and thus fast, and deletions are avoided
- * completely. Insertions are performed at each input character, whereas
- * string matches are performed only when the previous match ends. So it
- * is preferable to spend more time in matches to allow very fast string
- * insertions and avoid deletions. The matching algorithm for small
- * strings is inspired from that of Rabin & Karp. A brute force approach
- * is used to find longer strings when a small match has been found.
- * A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
- * (by Leonid Broukhis).
- * A previous version of this file used a more sophisticated algorithm
- * (by Fiala and Greene) which is guaranteed to run in linear amortized
- * time, but has a larger average cost, uses more memory and is patented.
- * However the F&G algorithm may be faster for some highly redundant
- * files if the parameter max_chain_length (described below) is too large.
- *
- * ACKNOWLEDGEMENTS
- *
- * The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
- * I found it in 'freeze' written by Leonid Broukhis.
- * Thanks to many info-zippers for bug reports and testing.
- *
- * REFERENCES
- *
- * APPNOTE.TXT documentation file in PKZIP 1.93a distribution.
- *
- * A description of the Rabin and Karp algorithm is given in the book
- * "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
- *
- * Fiala,E.R., and Greene,D.H.
- * Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
- *
- * INTERFACE
- *
- * void lm_init (int pack_level, ush *flags)
- * Initialize the "longest match" routines for a new file
- *
- * void deflate (void)
- * Processes a new input file. Sets the compressed length, crc,
- * deflate flags and internal file attributes.
- */
- #include <stdio.h>
- #include "gzip.h"
- /* ===========================================================================
- * Configuration parameters
- */
- #define HASH_BITS 15
- #define HASH_SIZE (unsigned)(1<<HASH_BITS)
- #define HASH_MASK (HASH_SIZE-1)
- #define WMASK (WSIZE-1)
- /* HASH_SIZE and WSIZE must be powers of two */
- #define NIL 0
- /* Tail of hash chains */
- #define FAST 4
- #define SLOW 2
- /* speed options for the general purpose bit flag */
- #ifndef TOO_FAR
- # define TOO_FAR 4096
- #endif
- /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
- int RSYNC_WIN = 4096;
- /* Size of rsync window, must be < MAX_DIST */
- /* Whether to enable compatibility with Debian's old rsyncable patch. */
- int debian_rsyncable = 1;
- void set_14_rsyncable () {
- debian_rsyncable = 0;
- RSYNC_WIN = 8192;
- }
- /* gzip 1.6 uses a different rsyncable that is a hybrid between the
- * original and the gzip 1.4 version
- */
- void set_16_rsyncable () {
- debian_rsyncable = 2;
- RSYNC_WIN = 8192;
- }
- #define RSYNC_SUM_MATCH_DEBIAN(sum) ((sum) % RSYNC_WIN == 0)
- #define RSYNC_SUM_MATCH(sum) (((sum) & (RSYNC_WIN - 1)) == 0)
- /* Whether window sum matches magic value */
- /* ===========================================================================
- * Local data used by the "longest match" routines.
- */
- typedef ush Pos;
- typedef unsigned IPos;
- /* A Pos is an index in the character window. We use short instead of int to
- * save space in the various tables. IPos is used only for parameter passing.
- */
- static uch window[2L*WSIZE];
- /* Sliding window. Input bytes are read into the second half of the window,
- * and move to the first half later to keep a dictionary of at least WSIZE
- * bytes. With this organization, matches are limited to a distance of
- * WSIZE-MAX_MATCH bytes, but this ensures that IO is always
- * performed with a length multiple of the block size. Also, it limits
- * the window size to 64K, which is quite useful on MSDOS.
- */
- Pos prev[WSIZE];
- /* Link to older string with same hash index. To limit the size of this
- * array to 64K, this link is maintained only for the last 32K strings.
- * An index in this array is thus a window index modulo 32K.
- */
- Pos head[1<<HASH_BITS];
- /* Heads of the hash chains or NIL. */
- ulg window_size = (ulg)2*WSIZE;
- /* window size, 2*WSIZE except for MMAP or BIG_MEM, where it is the
- * input file length plus MIN_LOOKAHEAD.
- */
- long block_start;
- /* window position at the beginning of the current output block. Gets
- * negative when the window is moved backwards.
- */
- static unsigned ins_h; /* hash index of string to be inserted */
- #define H_SHIFT ((HASH_BITS+MIN_MATCH-1)/MIN_MATCH)
- /* Number of bits by which ins_h and del_h must be shifted at each
- * input step. It must be such that after MIN_MATCH steps, the oldest
- * byte no longer takes part in the hash key, that is:
- * H_SHIFT * MIN_MATCH >= HASH_BITS
- */
- unsigned int prev_length;
- /* Length of the best match at previous step. Matches not greater than this
- * are discarded. This is used in the lazy match evaluation.
- */
- unsigned strstart; /* start of string to insert */
- unsigned match_start; /* start of matching string */
- static int eofile; /* flag set at end of input file */
- static unsigned lookahead; /* number of valid bytes ahead in window */
- unsigned max_chain_length;
- /* To speed up deflation, hash chains are never searched beyond this length.
- * A higher limit improves compression ratio but degrades the speed.
- */
- static unsigned int max_lazy_match;
- /* Attempt to find a better match only when the current match is strictly
- * smaller than this value. This mechanism is used only for compression
- * levels >= 4.
- */
- #define max_insert_length max_lazy_match
- /* Insert new strings in the hash table only if the match length
- * is not greater than this length. This saves time but degrades compression.
- * max_insert_length is used only for compression levels <= 3.
- */
- static unsigned good_match;
- /* Use a faster search when the previous match is longer than this */
- static ulg rsync_sum; /* rolling sum of rsync window */
- static ulg rsync_chunk_end; /* next rsync sequence point */
- /* Values for max_lazy_match, good_match and max_chain_length, depending on
- * the desired pack level (0..9). The values given below have been tuned to
- * exclude worst case performance for pathological files. Better values may be
- * found for specific files.
- */
- typedef struct config {
- ush good_length; /* reduce lazy search above this match length */
- ush max_lazy; /* do not perform lazy search above this match length */
- ush nice_length; /* quit search above this match length */
- ush max_chain;
- } config;
- #ifdef FULL_SEARCH
- # define nice_match MAX_MATCH
- #else
- int nice_match; /* Stop searching when current match exceeds this */
- #endif
- static config configuration_table[10] = {
- /* good lazy nice chain */
- /* 0 */ {0, 0, 0, 0}, /* store only */
- /* 1 */ {4, 4, 8, 4}, /* maximum speed, no lazy matches */
- /* 2 */ {4, 5, 16, 8},
- /* 3 */ {4, 6, 32, 32},
- /* 4 */ {4, 4, 16, 16}, /* lazy matches */
- /* 5 */ {8, 16, 32, 32},
- /* 6 */ {8, 16, 128, 128},
- /* 7 */ {8, 32, 128, 256},
- /* 8 */ {32, 128, 258, 1024},
- /* 9 */ {32, 258, 258, 4096}}; /* maximum compression */
- /* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4
- * For deflate_fast() (levels <= 3) good is ignored and lazy has a different
- * meaning.
- */
- #define EQUAL 0
- /* result of memcmp for equal strings */
- /* ===========================================================================
- * Prototypes for local functions.
- */
- static void fill_window(void);
- int longest_match(IPos cur_match);
- /* ===========================================================================
- * Update a hash value with the given input byte
- * IN assertion: all calls to to UPDATE_HASH are made with consecutive
- * input characters, so that a running hash key can be computed from the
- * previous key instead of complete recalculation each time.
- */
- #define UPDATE_HASH(h,c) (h = (((h)<<H_SHIFT) ^ (c)) & HASH_MASK)
- /* ===========================================================================
- * Insert string s in the dictionary and set match_head to the previous head
- * of the hash chain (the most recent string with same hash key). Return
- * the previous length of the hash chain.
- * IN assertion: all calls to to INSERT_STRING are made with consecutive
- * input characters and the first MIN_MATCH bytes of s are valid
- * (except for the last MIN_MATCH-1 bytes of the input file).
- */
- #define INSERT_STRING(s, match_head) \
- (UPDATE_HASH(ins_h, window[(s) + MIN_MATCH-1]), \
- prev[(s) & WMASK] = match_head = head[ins_h], \
- head[ins_h] = (s))
- /* ===========================================================================
- * Initialize the "longest match" routines for a new file
- */
- void lm_init (int pack_level, /* 1: best speed, 9: best compression */
- ush *flags) /* general purpose bit flag */
- {
- register unsigned j;
- if (pack_level < 1 || pack_level > 9) gzip_error ("bad pack level");
- /* Initialize the hash table. */
- memzero((char*)head, HASH_SIZE*sizeof(*head));
- /* prev will be initialized on the fly */
- /* rsync params */
- rsync_chunk_end = 0xFFFFFFFFUL;
- rsync_sum = 0;
- /* Set the default configuration parameters:
- */
- max_lazy_match = configuration_table[pack_level].max_lazy;
- good_match = configuration_table[pack_level].good_length;
- #ifndef FULL_SEARCH
- nice_match = configuration_table[pack_level].nice_length;
- #endif
- max_chain_length = configuration_table[pack_level].max_chain;
- if (pack_level == 1) {
- *flags |= FAST;
- } else if (pack_level == 9) {
- *flags |= SLOW;
- }
- /* ??? reduce max_chain_length for binary files */
- strstart = 0;
- block_start = 0L;
- lookahead = read_buf((char*)window,
- sizeof(int) <= 2 ? (unsigned)WSIZE : 2*WSIZE);
- if (lookahead == 0 || lookahead == (unsigned)EOF) {
- eofile = 1, lookahead = 0;
- return;
- }
- eofile = 0;
- /* Make sure that we always have enough lookahead. This is important
- * if input comes from a device such as a tty.
- */
- while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window();
- ins_h = 0;
- for (j=0; j<MIN_MATCH-1; j++) UPDATE_HASH(ins_h, window[j]);
- /* If lookahead < MIN_MATCH, ins_h is garbage, but this is
- * not important since only literal bytes will be emitted.
- */
- }
- /* ===========================================================================
- * Set match_start to the longest match starting at the given string and
- * return its length. Matches shorter or equal to prev_length are discarded,
- * in which case the result is equal to prev_length and match_start is
- * garbage.
- * IN assertions: cur_match is the head of the hash chain for the current
- * string (strstart) and its distance is <= MAX_DIST, and prev_length >= 1
- */
- int longest_match(IPos cur_match)
- {
- unsigned chain_length = max_chain_length; /* max hash chain length */
- register uch *scan = window + strstart; /* current string */
- register uch *match; /* matched string */
- register int len; /* length of current match */
- int best_len = prev_length; /* best match length so far */
- IPos limit = strstart > (IPos)MAX_DIST ? strstart - (IPos)MAX_DIST : NIL;
- /* Stop when cur_match becomes <= limit. To simplify the code,
- * we prevent matches with the string of window index 0.
- */
- /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
- * It is easy to get rid of this optimization if necessary.
- */
- #if HASH_BITS < 8 || MAX_MATCH != 258
- error: Code too clever
- #endif
- #ifdef UNALIGNED_OK
- /* Compare two bytes at a time. Note: this is not always beneficial.
- * Try with and without -DUNALIGNED_OK to check.
- */
- register uch *strend = window + strstart + MAX_MATCH - 1;
- register ush scan_start = *(ush*)scan;
- register ush scan_end = *(ush*)(scan+best_len-1);
- #else
- register uch *strend = window + strstart + MAX_MATCH;
- register uch scan_end1 = scan[best_len-1];
- register uch scan_end = scan[best_len];
- #endif
- /* Do not waste too much time if we already have a good match: */
- if (prev_length >= good_match) {
- chain_length >>= 2;
- }
- Assert(strstart <= window_size-MIN_LOOKAHEAD, "insufficient lookahead");
- do {
- Assert(cur_match < strstart, "no future");
- match = window + cur_match;
- /* Skip to next match if the match length cannot increase
- * or if the match length is less than 2:
- */
- #if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
- /* This code assumes sizeof(unsigned short) == 2. Do not use
- * UNALIGNED_OK if your compiler uses a different size.
- */
- if (*(ush*)(match+best_len-1) != scan_end ||
- *(ush*)match != scan_start) continue;
- /* It is not necessary to compare scan[2] and match[2] since they are
- * always equal when the other bytes match, given that the hash keys
- * are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
- * strstart+3, +5, ... up to strstart+257. We check for insufficient
- * lookahead only every 4th comparison; the 128th check will be made
- * at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
- * necessary to put more guard bytes at the end of the window, or
- * to check more often for insufficient lookahead.
- */
- scan++, match++;
- do {
- } while (*(ush*)(scan+=2) == *(ush*)(match+=2) &&
- *(ush*)(scan+=2) == *(ush*)(match+=2) &&
- *(ush*)(scan+=2) == *(ush*)(match+=2) &&
- *(ush*)(scan+=2) == *(ush*)(match+=2) &&
- scan < strend);
- /* The funny "do {}" generates better code on most compilers */
- /* Here, scan <= window+strstart+257 */
- Assert(scan <= window+(unsigned)(window_size-1), "wild scan");
- if (*scan == *match) scan++;
- len = (MAX_MATCH - 1) - (int)(strend-scan);
- scan = strend - (MAX_MATCH-1);
- #else /* UNALIGNED_OK */
- if (match[best_len] != scan_end ||
- match[best_len-1] != scan_end1 ||
- *match != *scan ||
- *++match != scan[1]) continue;
- /* The check at best_len-1 can be removed because it will be made
- * again later. (This heuristic is not always a win.)
- * It is not necessary to compare scan[2] and match[2] since they
- * are always equal when the other bytes match, given that
- * the hash keys are equal and that HASH_BITS >= 8.
- */
- scan += 2, match++;
- /* We check for insufficient lookahead only every 8th comparison;
- * the 256th check will be made at strstart+258.
- */
- do {
- } while (*++scan == *++match && *++scan == *++match &&
- *++scan == *++match && *++scan == *++match &&
- *++scan == *++match && *++scan == *++match &&
- *++scan == *++match && *++scan == *++match &&
- scan < strend);
- len = MAX_MATCH - (int)(strend - scan);
- scan = strend - MAX_MATCH;
- #endif /* UNALIGNED_OK */
- if (len > best_len) {
- match_start = cur_match;
- best_len = len;
- if (len >= nice_match) break;
- #ifdef UNALIGNED_OK
- scan_end = *(ush*)(scan+best_len-1);
- #else
- scan_end1 = scan[best_len-1];
- scan_end = scan[best_len];
- #endif
- }
- } while ((cur_match = prev[cur_match & WMASK]) > limit
- && --chain_length != 0);
- return best_len;
- }
- /* ===========================================================================
- * Fill the window when the lookahead becomes insufficient.
- * Updates strstart and lookahead, and sets eofile if end of input file.
- * IN assertion: lookahead < MIN_LOOKAHEAD && strstart + lookahead > 0
- * OUT assertions: at least one byte has been read, or eofile is set;
- * file reads are performed for at least two bytes (required for the
- * translate_eol option).
- */
- static void fill_window(void)
- {
- register unsigned n, m;
- unsigned more = (unsigned)(window_size - (ulg)lookahead - (ulg)strstart);
- /* Amount of free space at the end of the window. */
- /* If the window is almost full and there is insufficient lookahead,
- * move the upper half to the lower one to make room in the upper half.
- */
- if (more == (unsigned)EOF) {
- /* Very unlikely, but possible on 16 bit machine if strstart == 0
- * and lookahead == 1 (input done one byte at time)
- */
- more--;
- } else if (strstart >= WSIZE+MAX_DIST) {
- /* By the IN assertion, the window is not empty so we can't confuse
- * more == 0 with more == 64K on a 16 bit machine.
- */
- Assert(window_size == (ulg)2*WSIZE, "no sliding with BIG_MEM");
- memcpy((char*)window, (char*)window+WSIZE, (unsigned)WSIZE);
- match_start -= WSIZE;
- strstart -= WSIZE; /* we now have strstart >= MAX_DIST: */
- if (rsync_chunk_end != 0xFFFFFFFFUL)
- rsync_chunk_end -= WSIZE;
- block_start -= (long) WSIZE;
- for (n = 0; n < HASH_SIZE; n++) {
- m = head[n];
- head[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL);
- }
- for (n = 0; n < WSIZE; n++) {
- m = prev[n];
- prev[n] = (Pos)(m >= WSIZE ? m-WSIZE : NIL);
- /* If n is not on any hash chain, prev[n] is garbage but
- * its value will never be used.
- */
- }
- more += WSIZE;
- }
- /* At this point, more >= 2 */
- if (!eofile) {
- n = read_buf((char*)window+strstart+lookahead, more);
- if (n == 0 || n == (unsigned)EOF) {
- eofile = 1;
- /* Don't let garbage pollute the dictionary. */
- memzero (window + strstart + lookahead, MIN_MATCH - 1);
- } else {
- lookahead += n;
- }
- }
- }
- static void rsync_roll(unsigned start, unsigned num)
- {
- unsigned i;
- if (start < RSYNC_WIN) {
- /* before window fills. */
- for (i = start; i < RSYNC_WIN; i++) {
- if (i == start + num) return;
- rsync_sum += (ulg)window[i];
- }
- num -= (RSYNC_WIN - start);
- start = RSYNC_WIN;
- }
- /* buffer after window full */
- for (i = start; i < start+num; i++) {
- /* New character in */
- rsync_sum += (ulg)window[i];
- /* Old character out */
- rsync_sum -= (ulg)window[i - RSYNC_WIN];
- if (debian_rsyncable == 1 && rsync_chunk_end == 0xFFFFFFFFUL && RSYNC_SUM_MATCH_DEBIAN(rsync_sum))
- rsync_chunk_end = i;
- if (debian_rsyncable != 1 && rsync_chunk_end == 0xFFFFFFFFUL && RSYNC_SUM_MATCH(rsync_sum))
- rsync_chunk_end = i;
- }
- }
- /* ===========================================================================
- * Set rsync_chunk_end if window sum matches magic value.
- */
- #define RSYNC_ROLL(s, n) \
- do { if (rsync) rsync_roll((s), (n)); } while(0)
- /* ===========================================================================
- * Flush the current block, with given end-of-file flag.
- * IN assertion: strstart is set to the end of the current match.
- */
- #define FLUSH_BLOCK(eof) \
- flush_block(block_start >= 0L ? (char*)&window[(unsigned)block_start] : \
- (char*)NULL, (long)strstart - block_start, flush-1, (eof))
- /* ===========================================================================
- * Processes a new input file and return its compressed length. This
- * function does not perform lazy evaluationof matches and inserts
- * new strings in the dictionary only for unmatched strings or for short
- * matches. It is used only for the fast compression options.
- */
- static void deflate_fast(int pack_level, int rsync)
- {
- IPos hash_head; /* head of the hash chain */
- int flush = 0; /* set if current block must be flushed, 2=>and padded */
- unsigned match_length = 0; /* length of best match */
- prev_length = MIN_MATCH-1;
- while (lookahead != 0) {
- /* Insert the string window[strstart .. strstart+2] in the
- * dictionary, and set hash_head to the head of the hash chain:
- */
- INSERT_STRING(strstart, hash_head);
- /* Find the longest match, discarding those <= prev_length.
- * At this point we have always match_length < MIN_MATCH
- */
- if (hash_head != NIL && strstart - hash_head <= MAX_DIST
- && strstart <= window_size - MIN_LOOKAHEAD) {
- /* To simplify the code, we prevent matches with the string
- * of window index 0 (in particular we have to avoid a match
- * of the string with itself at the start of the input file).
- */
- match_length = longest_match (hash_head);
- /* longest_match() sets match_start */
- if (match_length > lookahead) match_length = lookahead;
- }
- if (match_length >= MIN_MATCH) {
- flush = ct_tally(pack_level, strstart-match_start, match_length - MIN_MATCH);
- lookahead -= match_length;
- RSYNC_ROLL(strstart, match_length);
- /* Insert new strings in the hash table only if the match length
- * is not too large. This saves time but degrades compression.
- */
- if (match_length <= max_insert_length) {
- match_length--; /* string at strstart already in hash table */
- do {
- strstart++;
- INSERT_STRING(strstart, hash_head);
- /* strstart never exceeds WSIZE-MAX_MATCH, so there are
- * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH
- * these bytes are garbage, but it does not matter since
- * the next lookahead bytes will be emitted as literals.
- */
- } while (--match_length != 0);
- strstart++;
- } else {
- strstart += match_length;
- match_length = 0;
- ins_h = window[strstart];
- UPDATE_HASH(ins_h, window[strstart+1]);
- #if MIN_MATCH != 3
- Call UPDATE_HASH() MIN_MATCH-3 more times
- #endif
- }
- } else {
- /* No match, output a literal byte */
- Tracevv((stderr,"%c",window[strstart]));
- flush = ct_tally (pack_level, 0, window[strstart]);
- RSYNC_ROLL(strstart, 1);
- lookahead--;
- strstart++;
- }
- if (rsync && debian_rsyncable && strstart > rsync_chunk_end) {
- rsync_chunk_end = 0xFFFFFFFFUL;
- flush = 2;
- }
- if (rsync && ! debian_rsyncable && strstart > rsync_chunk_end) {
- flush = 1;
- ct_init();
- rsync_chunk_end = 0xFFFFFFFFUL;
- }
- if (flush) FLUSH_BLOCK(0), block_start = strstart;
- /* Make sure that we always have enough lookahead, except
- * at the end of the input file. We need MAX_MATCH bytes
- * for the next match, plus MIN_MATCH bytes to insert the
- * string following the next match.
- */
- while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window();
- }
- FLUSH_BLOCK(1); /* eof */
- }
- /* ===========================================================================
- * Same as above, but achieves better compression. We use a lazy
- * evaluation for matches: a match is finally adopted only if there is
- * no better match at the next window position.
- */
- void gnu_deflate(int pack_level, int rsync, int rsync14, int rsync16)
- {
- IPos hash_head; /* head of hash chain */
- IPos prev_match; /* previous match */
- int flush = 0; /* set if current block must be flushed */
- int match_available = 0; /* set if previous match exists */
- register unsigned match_length = MIN_MATCH-1; /* length of best match */
- /* The rsync14 mode superscedes Debian's old, somewhat broken
- * rsync patch. */
- if (rsync14) {
- rsync=1;
- set_14_rsyncable();
- }
- /* The rsync16 mode superscedes the others yet again */
- if (rsync16) {
- rsync=1;
- set_16_rsyncable();
- }
- if (pack_level <= 3) {
- deflate_fast(pack_level, rsync); /* optimized for speed */
- return;
- }
- /* Process the input block. */
- while (lookahead != 0) {
- /* Insert the string window[strstart .. strstart+2] in the
- * dictionary, and set hash_head to the head of the hash chain:
- */
- INSERT_STRING(strstart, hash_head);
- /* Find the longest match, discarding those <= prev_length.
- */
- prev_length = match_length, prev_match = match_start;
- match_length = MIN_MATCH-1;
- if (hash_head != NIL && prev_length < max_lazy_match &&
- strstart - hash_head <= MAX_DIST &&
- strstart <= window_size - MIN_LOOKAHEAD) {
- /* To simplify the code, we prevent matches with the string
- * of window index 0 (in particular we have to avoid a match
- * of the string with itself at the start of the input file).
- */
- match_length = longest_match (hash_head);
- /* longest_match() sets match_start */
- if (match_length > lookahead) match_length = lookahead;
- /* Ignore a length 3 match if it is too distant: */
- if (match_length == MIN_MATCH && strstart-match_start > TOO_FAR){
- /* If prev_match is also MIN_MATCH, match_start is garbage
- * but we will ignore the current match anyway.
- */
- match_length--;
- }
- }
- /* If there was a match at the previous step and the current
- * match is not better, output the previous match:
- */
- if (prev_length >= MIN_MATCH && match_length <= prev_length) {
- flush = ct_tally(pack_level, strstart-1-prev_match, prev_length - MIN_MATCH);
- /* Insert in hash table all strings up to the end of the match.
- * strstart-1 and strstart are already inserted.
- */
- lookahead -= prev_length-1;
- prev_length -= 2;
- RSYNC_ROLL(strstart, prev_length+1);
- do {
- strstart++;
- INSERT_STRING(strstart, hash_head);
- /* strstart never exceeds WSIZE-MAX_MATCH, so there are
- * always MIN_MATCH bytes ahead. If lookahead < MIN_MATCH
- * these bytes are garbage, but it does not matter since the
- * next lookahead bytes will always be emitted as literals.
- */
- } while (--prev_length != 0);
- match_available = 0;
- match_length = MIN_MATCH-1;
- strstart++;
- if (rsync && debian_rsyncable && strstart > rsync_chunk_end) {
- rsync_chunk_end = 0xFFFFFFFFUL;
- flush = 2;
- }
- if (rsync && ! debian_rsyncable && strstart > rsync_chunk_end) {
- ct_init();
- rsync_chunk_end = 0xFFFFFFFFUL;
- flush = 1;
- }
- if (flush) FLUSH_BLOCK(0), block_start = strstart;
- } else if (match_available) {
- /* If there was no match at the previous position, output a
- * single literal. If there was a match but the current match
- * is longer, truncate the previous match to a single literal.
- */
- Tracevv((stderr,"%c",window[strstart-1]));
- flush = ct_tally (pack_level, 0, window[strstart-1]);
- if (rsync && debian_rsyncable && strstart > rsync_chunk_end) {
- rsync_chunk_end = 0xFFFFFFFFUL;
- flush = 2;
- }
- if (rsync && ! debian_rsyncable && strstart > rsync_chunk_end) {
- ct_init();
- rsync_chunk_end = 0xFFFFFFFFUL;
- flush = 1;
- }
- if (flush) FLUSH_BLOCK(0), block_start = strstart;
- RSYNC_ROLL(strstart, 1);
- strstart++;
- lookahead--;
- } else {
- /* There is no previous match to compare with, wait for
- * the next step to decide.
- */
- if (rsync && debian_rsyncable && strstart > rsync_chunk_end) {
- /* Reset huffman tree */
- rsync_chunk_end = 0xFFFFFFFFUL;
- flush = 2;
- FLUSH_BLOCK(0), block_start = strstart;
- }
- if (rsync && ! debian_rsyncable && strstart > rsync_chunk_end) {
- ct_init();
- /* Reset huffman tree */
- rsync_chunk_end = 0xFFFFFFFFUL;
- FLUSH_BLOCK(0), block_start = strstart;
- }
- match_available = 1;
- RSYNC_ROLL(strstart, 1);
- strstart++;
- lookahead--;
- }
- /* Assert (strstart <= bytes_in && lookahead <= bytes_in, "a bit too far"); */
- /* Make sure that we always have enough lookahead, except
- * at the end of the input file. We need MAX_MATCH bytes
- * for the next match, plus MIN_MATCH bytes to insert the
- * string following the next match.
- */
- while (lookahead < MIN_LOOKAHEAD && !eofile) fill_window();
- }
- if (match_available) ct_tally (pack_level, 0, window[strstart-1]);
- FLUSH_BLOCK(1); /* eof */
- }
|