- block_start -= WSIZE;
-
- for (n = 0; n < HASH_SIZE; n++) {
- m = head[n];
- head[n] = (Pos) (m >= WSIZE ? m - WSIZE : 0);
- }
- for (n = 0; n < WSIZE; n++) {
- m = prev[n];
- prev[n] = (Pos) (m >= WSIZE ? m - WSIZE : 0);
- /* 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 = file_read(window + strstart + lookahead, more);
- if (n == 0 || n == (unsigned) -1) {
- eofile = 1;
- } else {
- lookahead += n;
- }
- }
-}
-
-
-/* ===========================================================================
- * 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.
- *
- * Processes a new input file and return its compressed length. Sets
- * the compressed length, crc, deflate flags and internal file
- * attributes.
- */
-
-/* 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, \
- (eof) \
- )
-
-/* 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); \
-}
-
-static ulg deflate(void)
-{
- IPos hash_head; /* head of hash chain */
- IPos prev_match; /* previous match */
- int flush; /* set if current block must be flushed */
- int match_available = 0; /* set if previous match exists */
- unsigned match_length = MIN_MATCH - 1; /* length of best match */
-
- /* 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 != 0 && prev_length < max_lazy_match
- && strstart - hash_head <= MAX_DIST
- ) {
- /* 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) {
- check_match(strstart - 1, prev_match, prev_length);
- flush = ct_tally(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;
- 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 (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]));
- if (ct_tally(0, window[strstart - 1])) {
- FLUSH_BLOCK(0);
- block_start = strstart;
- }
- strstart++;
- lookahead--;
- } else {
- /* There is no previous match to compare with, wait for
- * the next step to decide.
- */
- match_available = 1;
- strstart++;
- lookahead--;
- }
- Assert(strstart <= isize && lookahead <= isize, "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(0, window[strstart - 1]);
-
- return FLUSH_BLOCK(1); /* eof */
-}
-/* trees.c -- output deflated data using Huffman coding
- * Copyright (C) 1992-1993 Jean-loup Gailly
- * This is free software; you can redistribute it and/or modify it under the
- * terms of the GNU General Public License, see the file COPYING.
- */
-
-/*
- * PURPOSE
- *
- * Encode various sets of source values using variable-length
- * binary code trees.
- *
- * DISCUSSION
- *
- * The PKZIP "deflation" process uses several Huffman trees. The more
- * common source values are represented by shorter bit sequences.
- *
- * Each code tree is stored in the ZIP file in a compressed form
- * which is itself a Huffman encoding of the lengths of
- * all the code strings (in ascending order by source values).
- * The actual code strings are reconstructed from the lengths in
- * the UNZIP process, as described in the "application note"
- * (APPNOTE.TXT) distributed as part of PKWARE's PKZIP program.
- *
- * REFERENCES
- *
- * Lynch, Thomas J.
- * Data Compression: Techniques and Applications, pp. 53-55.
- * Lifetime Learning Publications, 1985. ISBN 0-534-03418-7.
- *
- * Storer, James A.
- * Data Compression: Methods and Theory, pp. 49-50.
- * Computer Science Press, 1988. ISBN 0-7167-8156-5.
- *
- * Sedgewick, R.
- * Algorithms, p290.
- * Addison-Wesley, 1983. ISBN 0-201-06672-6.
- *
- * INTERFACE
- *
- * void ct_init(ush *attr, int *methodp)
- * Allocate the match buffer, initialize the various tables and save
- * the location of the internal file attribute (ascii/binary) and
- * method (DEFLATE/STORE)
- *
- * void ct_tally(int dist, int lc);
- * Save the match info and tally the frequency counts.
- *
- * long flush_block (char *buf, ulg stored_len, int eof)
- * Determine the best encoding for the current block: dynamic trees,
- * static trees or store, and output the encoded block to the zip
- * file. Returns the total compressed length for the file so far.
- *
- */
-
-/* ===========================================================================
- * Constants
- */
-
-#define MAX_BITS 15
-/* All codes must not exceed MAX_BITS bits */
-
-#define MAX_BL_BITS 7
-/* Bit length codes must not exceed MAX_BL_BITS bits */