/* deflate.c -- compress data using the deflation algorithm
- Copyright (C) 1999, 2006, 2009-2012 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));
strstart = 0;
block_start = 0L;
- rsync_chunk_end = 0xFFFFFFFFUL;
#ifdef ASMV
match_init(); /* initialize the asm code */
#endif
/* 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(start, num)
- 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;
}
}
*/
#define FLUSH_BLOCK(eof) \
flush_block(block_start >= 0L ? (char*)&window[(unsigned)block_start] : \
- (char*)NULL, (long)strstart - block_start, (eof))
+ (char*)NULL, (long)strstart - block_start, flush-1, (eof))
/* ===========================================================================
* Processes a new input file and return its compressed length. This
local off_t deflate_fast()
{
IPos hash_head; /* head of the hash chain */
- int flush; /* set if current block must be flushed */
+ 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) {
- ush attr = 0; /* ascii/binary flag */
-
- flush = 1;
- /* Reset huffman tree */
- ct_init(&attr, &method);
rsync_chunk_end = 0xFFFFFFFFUL;
+ flush = 2;
}
if (flush) FLUSH_BLOCK(0), block_start = strstart;
{
IPos hash_head; /* head of hash chain */
IPos prev_match; /* previous match */
- int flush; /* set if current block must be flushed */
+ 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 */
*/
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) {
- ush attr = 0; /* ascii/binary flag */
-
- /* Reset huffman tree */
- ct_init(&attr, &method);
- rsync_chunk_end = 0xFFFFFFFFUL;
- flush = 1;
- }
+ 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) {
- ush attr = 0; /* ascii/binary flag */
-
- /* Reset huffman tree */
- ct_init(&attr, &method);
- rsync_chunk_end = 0xFFFFFFFFUL;
-
- flush = 1;
- }
+ 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) {
- ush attr = 0; /* ascii/binary flag */
-
- /* Reset huffman tree */
- ct_init(&attr, &method);
- rsync_chunk_end = 0xFFFFFFFFUL;
+ if (rsync && strstart > rsync_chunk_end) {
+ /* Reset huffman tree */
+ rsync_chunk_end = 0xFFFFFFFFUL;
+ flush = 2;
+ FLUSH_BLOCK(0), block_start = strstart;
+ }
- FLUSH_BLOCK(0), block_start = strstart;
- }
match_available = 1;
- RSYNC_ROLL(strstart, 1);
+ RSYNC_ROLL(strstart, 1);
strstart++;
lookahead--;
}