/* deflate.c -- compress data using the deflation algorithm
- Copyright (C) 1999, 2006, 2009-2013 Free Software Foundation, Inc.
+ Copyright (C) 1999, 2006, 2009-2018 Free Software Foundation, Inc.
Copyright (C) 1992-1993 Jean-loup Gailly
This program is free software; you can redistribute it and/or modify
#include "tailor.h"
#include "gzip.h"
#include "lzw.h" /* just for consistency checking */
+#include "verify.h"
/* ===========================================================================
* Configuration parameters
/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
#ifndef RSYNC_WIN
-# define RSYNC_WIN 8192
+# define RSYNC_WIN 4096
#endif
-/* Size of rsync window, must be < MAX_DIST */
+verify(RSYNC_WIN < MAX_DIST);
-#define RSYNC_SUM_MATCH(sum) (((sum) & (RSYNC_WIN - 1)) == 0)
+#define RSYNC_SUM_MATCH(sum) ((sum) % RSYNC_WIN == 0)
/* Whether window sum matches magic value */
/* ===========================================================================
compr_level = pack_level;
/* Initialize the hash table. */
-#if defined(MAXSEG_64K) && HASH_BITS == 15
+#if defined MAXSEG_64K && HASH_BITS == 15
for (j = 0; j < HASH_SIZE; j++) head[j] = NIL;
#else
memzero((char*)head, HASH_SIZE*sizeof(*head));
/* 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)
+#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.
*/
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;
+ if (rsync_chunk_end != 0xFFFFFFFFUL)
+ rsync_chunk_end -= WSIZE;
block_start -= (long) WSIZE;
}
}
-local void rsync_roll(unsigned start, unsigned num)
+/* With an initial offset of START, advance rsync's rolling checksum
+ by NUM bytes. */
+local void rsync_roll(unsigned int start, unsigned int 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;
+ /* 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 (rsync_chunk_end == 0xFFFFFFFFUL && RSYNC_SUM_MATCH(rsync_sum))
- rsync_chunk_end = i;
+ /* New character in */
+ rsync_sum += (ulg)window[i];
+ /* Old character out */
+ rsync_sum -= (ulg)window[i - RSYNC_WIN];
+ if (rsync_chunk_end == 0xFFFFFFFFUL && RSYNC_SUM_MATCH(rsync_sum))
+ rsync_chunk_end = i;
}
}
local off_t deflate_fast()
{
IPos hash_head; /* head of the hash chain */
- int flush = 0; /* set if current block must be flushed, 2=>and padded */
+ 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;
lookahead -= match_length;
- RSYNC_ROLL(strstart, match_length);
- /* Insert new strings in the hash table only if the 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) {
/* No match, output a literal byte */
Tracevv((stderr,"%c",window[strstart]));
flush = ct_tally (0, window[strstart]);
- RSYNC_ROLL(strstart, 1);
+ RSYNC_ROLL(strstart, 1);
lookahead--;
strstart++;
}
if (rsync && strstart > rsync_chunk_end) {
- flush = 2;
rsync_chunk_end = 0xFFFFFFFFUL;
+ flush = 2;
}
if (flush) FLUSH_BLOCK(0), block_start = strstart;
*/
lookahead -= prev_length-1;
prev_length -= 2;
- RSYNC_ROLL(strstart, prev_length+1);
+ RSYNC_ROLL(strstart, prev_length+1);
do {
strstart++;
INSERT_STRING(strstart, hash_head);
match_length = MIN_MATCH-1;
strstart++;
- if (rsync && strstart > rsync_chunk_end) {
- rsync_chunk_end = 0xFFFFFFFFUL;
- flush = 2;
- }
+ if (rsync && strstart > rsync_chunk_end) {
+ rsync_chunk_end = 0xFFFFFFFFUL;
+ flush = 2;
+ }
if (flush) FLUSH_BLOCK(0), block_start = strstart;
} else if (match_available) {
/* If there was no match at the previous position, output a
* is longer, truncate the previous match to a single literal.
*/
Tracevv((stderr,"%c",window[strstart-1]));
- flush = ct_tally (0, window[strstart-1]);
- if (rsync && strstart > rsync_chunk_end) {
- rsync_chunk_end = 0xFFFFFFFFUL;
- flush = 2;
- }
+ flush = ct_tally (0, window[strstart-1]);
+ if (rsync && strstart > rsync_chunk_end) {
+ rsync_chunk_end = 0xFFFFFFFFUL;
+ flush = 2;
+ }
if (flush) FLUSH_BLOCK(0), block_start = strstart;
- RSYNC_ROLL(strstart, 1);
+ RSYNC_ROLL(strstart, 1);
strstart++;
lookahead--;
} else {
/* There is no previous match to compare with, wait for
* the next step to decide.
*/
- if (rsync && strstart > rsync_chunk_end) {
- rsync_chunk_end = 0xFFFFFFFFUL;
- flush = 2;
- FLUSH_BLOCK(0), block_start = strstart;
- }
+ if (rsync && strstart > rsync_chunk_end) {
+ /* Reset huffman tree */
+ rsync_chunk_end = 0xFFFFFFFFUL;
+ flush = 2;
+ FLUSH_BLOCK(0), block_start = strstart;
+ }
+
match_available = 1;
- RSYNC_ROLL(strstart, 1);
+ RSYNC_ROLL(strstart, 1);
strstart++;
lookahead--;
}