Subversion Repositories autosfx

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 daniel-mar 1
#include "stdafx.h"
2
#pragma hdrstop
3
//#include <stdio.h>
4
#include "ZipDflt.h"
5
//#include "Zip.h"
6
//#include "ZipErr.h"
7
#include "dz_errs.h"
8
 
9
#undef _DZ_FILE_
10
#define _DZ_FILE_ DZ_ZDEFLATE_CPP
11
 
12
/* Deflate.c
13
* Copyright (C) 1990-1996 Mark Adler, Richard B. Wales, Jean-loup Gailly,
14
* Kai Uwe Rommel, Onno van der Linden and Igor Mandrichenko.
15
* This version modified by Chris Vleghert and Eric Engler for BCB/Delphi Zip.
16
** distributed under LGPL license ** see license.txt for details
17
*/
18
/*  PURPOSE
19
*      Identify new text as repetitions of old text within a fixed-
20
*      length sliding window trailing behind the new text.
21
**  DISCUSSION
22
*      The "deflation" process depends on being able to identify portions
23
*      of the input text which are identical to earlier input (within a
24
*      sliding window trailing behind the input currently being processed).
25
*
26
*      The most straightforward technique turns out to be the fastest for
27
*      most input files: try all possible matches and select the longest.
28
*      The key feature of this algorithm is that insertions into the string
29
*      dictionary are very simple and thus fast, and deletions are avoided
30
*      completely. Insertions are performed at each input character, whereas
31
*      string matches are performed only when the previous match ends. So it
32
*      is preferable to spend more time in matches to allow very fast string
33
*      insertions and avoid deletions. The matching algorithm for small
34
*      strings is inspired from that of Rabin & Karp. A brute force approach
35
*      is used to find longer strings when a small match has been found.
36
*      A similar algorithm is used in comic (by Jan-Mark Wams) and freeze
37
*      (by Leonid Broukhis).
38
*         A previous version of this file used a more sophisticated algorithm
39
*      (by Fiala and Greene) which is guaranteed to run in linear amortized
40
*      time, but has a larger average cost, uses more memory and is patented.
41
*      However the F&G algorithm may be faster for some highly redundant
42
*      files if the parameter max_chain_length (described below) is too large.
43
 *
44
 *  ACKNOWLEDGEMENTS
45
*      The idea of lazy evaluation of matches is due to Jan-Mark Wams, and
46
*      I found it in 'freeze' written by Leonid Broukhis.
47
*      Thanks to many info-zippers for bug reports and testing.
48
*
49
*  REFERENCES
50
*      APPNOTE.TXT documentation file in PKZIP 1.93a distribution.
51
*
52
*      A description of the Rabin and Karp algorithm is given in the book
53
*         "Algorithms" by R. Sedgewick, Addison-Wesley, p252.
54
*
55
*      Fiala,E.R., and Greene,D.H.
56
*         Data Compression with Finite Windows, Comm.ACM, 32,4 (1989) 490-595
57
*
58
*  INTERFACE
59
*      void lm_init (int pack_level, ush *flags)
60
 *          Initialize the "longest match" routines for a new file
61
 *
62
*      ulg deflate (void)
63
*          Processes a new input file and return its compressed length. Sets
64
*          the compressed length, crc, deflate flags and internal file
65
 *          attributes.
66
 
67
  Copyright (c) 1990-2007 Info-ZIP.  All rights reserved.
68
 
69
  See the accompanying file LICENSE, version 2007-Mar-4 or later
70
  (the contents of which are also included in zip.h) for terms of use.
71
  If, for some reason, all these files are missing, the Info-ZIP license
72
  also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
73
 
74
  parts Copyright (C) 1997 Mike White, Eric W. Engler
75
************************************************************************
76
 Copyright (C) 2009, 2010  by Russell J. Peters, Roger Aelbrecht
77
 
78
   This file is part of TZipMaster Version 1.9.
79
 
80
    TZipMaster is free software: you can redistribute it and/or modify
81
    it under the terms of the GNU Lesser General Public License as published by
82
    the Free Software Foundation, either version 3 of the License, or
83
    (at your option) any later version.
84
 
85
    TZipMaster is distributed in the hope that it will be useful,
86
    but WITHOUT ANY WARRANTY; without even the implied warranty of
87
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
88
    GNU Lesser General Public License for more details.
89
 
90
    You should have received a copy of the GNU Lesser General Public License
91
    along with TZipMaster.  If not, see <http://www.gnu.org/licenses/>.
92
 
93
    contact: problems@delphizip.org (include ZipMaster in the subject).
94
    updates: http://www.delphizip.org
95
    DelphiZip maillist subscribe at http://www.freelists.org/list/delphizip
96
************************************************************************/
97
 
98
// Configuration parameters
99
// Compile with HASH_BITS = 14 to reduce the memory requirements or with
100
//   HASH_BITS = 13 to use as little memory as possible. Otherwise if the
101
//   entire input file can be held in memory (not possible on 16 bit systems).
102
//   Warning: defining this symbol affects the compression ratio. The
103
//   compressed output is still correct, and might even be smaller in some
104
//   cases. For portability to 16 bit machines, do not use values above 15.
105
// #ifndef HASH_BITS
106
// #define HASH_BITS 15  // Number of bits used to hash strings
107
// #endif
108
 
109
//#define HASH_SIZE (unsigned)(1 << HASH_BITS)
110
//#define HASH_MASK (HASH_SIZE - 1)
111
//#define WMASK     (ZWSIZE - 1)
112
// HASH_SIZE and ZWSIZE must be powers of two
113
#define NIL 0
114
 
115
// Tail of hash chains
116
#define FAST  4
117
#define SLOW  2
118
 
119
// speed options for the general purpose bit flag
120
// #ifndef TOO_FAR
121
#define TOO_FAR 4096
122
// #endif
123
 
124
// Matches of length 3 are discarded if their distance exceeds TOO_FAR
125
// Local data used by the "longest match" routines.
126
//typedef ush Pos;
127
typedef unsigned IPos;
128
 
129
// A Pos is an index in the character window. We use short instead of int to
130
//   save space in the various tables. unsigned is used only for parameter passing.
131
#define H_SHIFT ((HASH_BITS + MIN_MATCH - 1) / MIN_MATCH)
132
 
133
// Number of bits by which ins_h and del_h must be shifted at each input
134
//   step. It must be such that after MIN_MATCH steps, the oldest byte no
135
//   longer takes part in the hash key, that is: H_SHIFT * MIN_MATCH >=
136
//   HASH_BITS
137
#define max_insert_length fmax_lazy_match
138
 
139
// Insert new strings in the hash table only if the match length is not
140
//   greater than this length. This saves time but degrades compression.
141
//   max_insert_length is used only for compression levels <= 3.
142
// Values for max_lazy_match, good_match and max_chain_length, depending on
143
//   the desired pack level (0..9). The values given below have been tuned to
144
//   exclude worst case performance for pathological files. Better values may
145
//   be found for specific files.
146
 
147
typedef struct config
148
{
149
    ush good_length; // reduce lazy search above this match length
150
    ush max_lazy; // do not perform lazy search above this match length
151
    ush nice_length; // quit search above this match length
152
    ush max_chain;
153
}
154
 
155
config;
156
 
157
#ifdef FULL_SEARCH
158
#define nice_match  MAX_MATCH
159
#endif
160
static config configuration_table[10] =
161
{
162
    // good lazy nice chain
163
    // 0
164
    { 0, 0, 0, 0 },
165
    // store only
166
    // 1
167
    { 4, 4, 8, 4 },
168
    // maximum speed, no lazy matches
169
    // 2
170
    { 4, 5, 16, 8 },
171
    // 3
172
    { 4, 6, 32, 32 },
173
    // 4
174
    { 4, 4, 16, 16 },
175
    // lazy matches
176
    // 5
177
    { 8, 16, 32, 32 },
178
    // 6
179
    { 8, 16, 128, 128 },
180
    // 7
181
    { 8, 32, 128, 256 },
182
    // 8
183
    { 32, 128, 258, 1024 },
184
    // 9
185
    { 32, 258, 258, 4096 }
186
}
187
; // maximum compression
188
 
189
// Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >=
190
//   4 For deflate_fast() (levels <= 3) good is ignored and lazy has a
191
//   different meaning.
192
#define EQUAL 0
193
 
194
// result of memcmp for equal strings
195
// Prototypes for local functions.
196
//static void fill_window(ZGlobals * pG);
197
//static ZInt64 deflate_fast(ZGlobals * pG);
198
 
199
//extern int __fastcall longest_match(ZGlobals *pG, unsigned cur_match);
200
 
201
//#ifdef DEBUG
202
//static void check_match(ZGlobals *pG, unsigned start, unsigned match, int length);
203
//#endif
204
 
205
// Update a hash value with the given input byte IN assertion: all calls to
206
//   to UPDATE_HASH are made with consecutive input characters, so that a
207
//   running hash key can be computed from the previous key instead of complete
208
//   recalculation each time.
209
#define UPDATE_HASH(h, c) (h = (((h) << H_SHIFT) ^ (c)) & HASH_MASK)
210
 
211
// Insert string s in the dictionary and set match_head to the previous head
212
//   of the hash chain (the most recent string with same hash key). Return the
213
//   previous length of the hash chain. IN assertion: all calls to to
214
//   INSERT_STRING are made with consecutive input characters and the first
215
//   MIN_MATCH bytes of s are valid (except for the last MIN_MATCH-1 bytes of
216
//   the input file).
217
#define INSERT_STRING(s, match_head)      \
218
    (     \
219
          UPDATE_HASH(fins_h, fwindow[(s) + (MIN_MATCH - 1)]), fprev[          \
220
                  (s) & WMASK] = (ush) (match_head = fhead[fins_h]), fhead[fins_h] = \
221
                          (ush) (s)  \
222
    )
223
 
224
// RCV Added 2x (ush)
225
// Initialize the "longest match" routines for a new file IN assertion:
226
//   window_size is > 0 if the input file is already read or mmap'ed in the
227
//   window[] array, 0 otherwise. In the first case, window_size is sufficient
228
//   to contain the whole input file plus MIN_LOOKAHEAD bytes (to avoid
229
//   referencing memory beyond the end of window[] when looking for matches
230
//   towards the end). pack_level :: 0: store, 1: best speed, 9: best
231
//   compression. flags :: General purpose bit flag.
232
void ZipDflt::lm_init(int pack_level, ush * flags)
233
{
234
    register unsigned j;
235
 
236
    if (pack_level < 1 || pack_level > 9)
237
        throw DZException(DZ_ERM_LOGIC_ERROR);
238
 
239
//        FatalError(ZEN_LOGIC03);
240
 
241
    // Do not slide the window if the whole input is already in memory
242
    //   (window_size > 0)
243
    fsliding = 0;
244
 
245
    if (fwindow_size == 0L)
246
    {
247
        fsliding = 1;
248
        fwindow_size = (ulg)2L * ZWSIZE;
249
    }
250
 
251
    // Initialize the hash table (avoiding 64K overflow for 16 bit systems).
252
    //   prev[] will be initialized on the fly.
253
    fhead[HASH_SIZE - 1] = NIL;            
254
    memset((char *) fhead, NIL, (unsigned)(HASH_SIZE - 1) * sizeof(* fhead));
255
 
256
    // Set the default configuration parameters:
257
    fmax_lazy_match = configuration_table[pack_level].max_lazy;
258
    fgood_match = configuration_table[pack_level].good_length;
259
 
260
#ifndef FULL_SEARCH
261
    fnice_match = configuration_table[pack_level].nice_length;
262
#endif
263
 
264
    fmax_chain_length = configuration_table[pack_level].max_chain;
265
 
266
    if (pack_level <= 2)
267
    {
268
        * flags |= FAST;
269
    }
270
    else
271
        if (pack_level >= 8)
272
        {
273
            * flags |= SLOW;
274
        }
275
 
276
    // ??? reduce max_chain_length for binary files
277
    fstrstart = 0;
278
 
279
    fblock_start = 0L;
280
 
281
    j = ZWSIZE;
282
 
283
    j <<= 1; // We Can read 64K in one step.
284
 
285
//  flookahead = (* fread_buf)((uch *) fwindow, j);
286
    flookahead = read_buf((uch *) fwindow, j);
287
 
288
    if (flookahead == 0 || flookahead == (unsigned)EOF)
289
    {
290
        feofile = 1, flookahead = 0;
291
        return;
292
    }
293
 
294
    feofile = 0;
295
 
296
    // Make sure that we always have enough lookahead. This is important if
297
    //   input comes from a device such as a tty.
298
 
299
    if (flookahead < MIN_LOOKAHEAD)
300
        fill_window();
301
 
302
    fins_h = 0;
303
 
304
    for (j = 0; j < MIN_MATCH - 1; j++)
305
        UPDATE_HASH(fins_h, fwindow[j]);
306
 
307
    // If lookahead < MIN_MATCH, ins_h is garbage, but this is not important
308
    //   since only literal bytes will be emitted.
309
}
310
 
311
 
312
#ifdef _DEBUG
313
// Check that the match at match_start is indeed a match.
314
void ZipDflt::check_match(unsigned start, unsigned match, int length)
315
{
316
    // check that the match is indeed a match
317
    if (memcmp((char *)fwindow + match, (char *)fwindow + start, length) != EQUAL)
318
        Notify(DZ_ERM_LOGIC_ERROR, _T("invalid match - start %d, match %d, length %d")
319
               , start, match, length);
320
}
321
 
322
#else
323
#define check_match(start, match, length)
324
#endif
325
 
326
// Fill the window when the lookahead becomes insufficient. Updates strstart
327
//   and lookahead, and sets eofile if end of input file. IN assertion:
328
//   lookahead < MIN_LOOKAHEAD &
329
//   &
330
//   strstart + lookahead > 0 OUT assertions: strstart <=
331
//   window_size-MIN_LOOKAHEAD At least one byte has been read, or eofile is
332
//   set; file reads are performed for at least two bytes (required for the
333
//   translate_eol option).
334
void ZipDflt::fill_window(void)
335
{
336
    register unsigned n, m;
337
    unsigned more; // Amount of free space at the end of the window.
338
 
339
    do
340
    {
341
        more = (unsigned)(fwindow_size - (ulg)flookahead - (ulg)fstrstart);
342
 
343
        // If the window is almost full and there is insufficient lookahead,
344
        //   move the upper half to the lower one to make room in the upper half.
345
 
346
        if (more == (unsigned)EOF)
347
        {
348
            // Very unlikely, but possible on 16 bit machine if strstart == 0 and
349
            //   lookahead == 1 (input done one byte at time)
350
            more--;
351
 
352
            // For MMAP or BIG_MEM, the whole input file is already in memory so
353
            //   we must not perform sliding. We must however call file_read in order
354
            //   to compute the crc, update lookahead and possibly set eofile.
355
        }
356
        else
357
            if (fstrstart >= ZWSIZE + MAX_DIST && fsliding)
358
            {
359
                // By the IN assertion, the window is not empty so we can't confuse
360
                //   more == 0 with more == 64K on a 16 bit machine.
361
                memcpy((char *) fwindow, (char *) fwindow + ZWSIZE, (unsigned)ZWSIZE);
362
                fmatch_start -= ZWSIZE;
363
                fstrstart -= ZWSIZE; // we now have strstart
364
                ///* >= MAX_DIST:
365
                fblock_start -= (long)ZWSIZE;
366
 
367
                for (n = 0; n < HASH_SIZE; n++)
368
                {
369
                    m = fhead[n];
370
                    fhead[n] = (Pos)(m >= ZWSIZE ? m - ZWSIZE : NIL);
371
                }
372
 
373
                for (n = 0; n < ZWSIZE; n++)
374
                {
375
                    m = fprev[n];
376
                    fprev[n] = (Pos)(m >= ZWSIZE ? m - ZWSIZE : NIL);
377
 
378
                    // If n is not on any hash chain, prev[n] is garbage but its value
379
                    //   will never be used.
380
                }
381
 
382
                more += ZWSIZE;
383
 
384
                if (Abort_Flag)
385
                    return; // UPDATE: the ziperr() func in dllzip.c closes file.
386
            }
387
 
388
        if (feofile)
389
            return;
390
 
391
        // If there was no sliding: strstart <= WSIZE+MAX_DIST - 1 &
392
        //   &
393
        //   lookahead <= MIN_LOOKAHEAD - 1 &
394
        //   &
395
        //   more == window_size - lookahead - strstart => more >= window_size -
396
        //   (MIN_LOOKAHEAD - 1 + WSIZE + MAX_DIST - 1) => more >= window_size - 2
397
        //   * WSIZE + 2 In the BIG_MEM or MMAP case (not yet supported in gzip),
398
        //   window_size == input_size + MIN_LOOKAHEAD &
399
        //   &
400
        //   strstart + lookahead <= input_size => more >= MIN_LOOKAHEAD.
401
        //   Otherwise, window_size == 2 * ZWSIZE so more >= 2. If there was
402
        //   sliding, more >= ZWSIZE. So in all cases, more >= 2.
403
        Assert(more >= 2, _T("more < 2"));
404
 
405
//    n = (* fread_buf)((uch *) fwindow + fstrstart + flookahead, more);
406
        n = read_buf((uch *)fwindow + fstrstart + flookahead, more);
407
 
408
        if (n == 0 || n == (unsigned)EOF)
409
        {
410
            feofile = 1;
411
        }
412
        else
413
        {
414
            flookahead += n;
415
        }
416
    }
417
    while (flookahead < MIN_LOOKAHEAD && !feofile);
418
}
419
 
420
/*
421
// Flush the current block, with given end-of-file flag. IN assertion:
422
//   strstart is set to the end of the current match.
423
#define FLUSH_BLOCK(eof)                         \
424
    flush_block(fblock_start >= 0L ? (uch *) &fwindow[(unsigned)fblock_start] : \
425
                (uch *)NULL, (ulg)fstrstart - (ulg)fblock_start, (eof))
426
*/
427
 
428
// Processes a new input file and return its compressed length. This
429
//   function does not perform lazy evaluationof matches and inserts new
430
//   strings in the dictionary only for unmatched strings or for short matches.
431
//   It is used only for the fast compression options.
432
ZInt64 ZipDflt::deflate_fast(void)
433
{
434
    unsigned hash_head; // head of the hash chain
435
    int flush; // set if current block must be flushed
436
    unsigned match_length = 0; // length of best match
437
    fprev_length = MIN_MATCH - 1;
438
 
439
    while (flookahead != 0)
440
    {
441
        // Insert the string window[strstart .. strstart+2] in the dictionary,
442
        //   and set hash_head to the head of the hash chain:
443
        INSERT_STRING(fstrstart, hash_head);
444
 
445
        // Find the longest match, discarding those <= prev_length. At this
446
        //   point we have always match_length < MIN_MATCH
447
 
448
        if (hash_head != NIL && fstrstart - hash_head <= MAX_DIST)
449
        {
450
            // To simplify the code, we prevent matches with the string of window
451
            //   index 0 (in particular we have to avoid a match of the string with
452
            //   itself at the start of the input file).
453
#ifndef HUFFMAN_ONLY
454
            match_length = longest_match(hash_head);
455
#endif
456
            // longest_match() sets match_start
457
 
458
            if (match_length > flookahead)
459
                match_length = flookahead;
460
        }
461
 
462
        if (match_length >= MIN_MATCH)
463
        {
464
#ifdef _DEBUG
465
            check_match(fstrstart, fmatch_start, match_length);
466
#endif
467
            flush = ct_tally(fstrstart - fmatch_start, match_length - MIN_MATCH);
468
 
469
            flookahead -= match_length;
470
 
471
            // Insert new strings in the hash table only if the match length is
472
            //   not too large. This saves time but degrades compression.
473
 
474
            if (match_length <= max_insert_length)
475
            {
476
                match_length--; // string at strstart already in hash table
477
 
478
                do
479
                {
480
                    fstrstart++;
481
                    INSERT_STRING(fstrstart, hash_head);
482
 
483
                    // strstart never exceeds ZWSIZE-MAX_MATCH, so there are always
484
                    //   MIN_MATCH bytes ahead. If lookahead < MIN_MATCH these bytes are
485
                    //   garbage, but it does not matter since the next lookahead bytes
486
                    //   will be emitted as literals.
487
                }
488
                while (--match_length != 0);
489
 
490
                fstrstart++;
491
            }
492
            else
493
            {
494
                fstrstart += match_length;
495
                match_length = 0;
496
                fins_h = fwindow[fstrstart];
497
                UPDATE_HASH(fins_h, fwindow[fstrstart + 1]);
498
#if MIN_MATCH != 3
499
                Call UPDATE_HASH() MIN_MATCH - 3 more times
500
#endif
501
            }
502
        }
503
        else
504
        {
505
            // No match, output a literal byte
506
//      Tracevv(("%c"), (fwindow[fstrstart]));
507
            flush = ct_tally(0, fwindow[fstrstart]);
508
            flookahead--;
509
            fstrstart++;
510
        }
511
 
512
        if (flush)
513
        {
514
            FlushBlock(0);
515
//   FLUSH_BLOCK(0);
516
            fblock_start = fstrstart;
517
        }
518
 
519
        // Make sure that we always have enough lookahead, except at the end of
520
        //   the input file. We need MAX_MATCH bytes for the next match, plus
521
        //   MIN_MATCH bytes to insert the string following the next match.
522
        if (flookahead < MIN_LOOKAHEAD)
523
            fill_window();
524
 
525
        if (Abort_Flag)
526
            Fatal(DZ_ERM_ABORT, 0);
527
//            throw DZAbort(DZ_ERM_ABORT);
528
 
529
//        {
530
        // the ziperr() func in dllzip.c closes file.
531
        //return ZEN_ABORT;
532
//        }
533
    }
534
 
535
//  return FLUSH_BLOCK(1); // eof
536
    return FlushBlock(1); // eof
537
}
538
 
539
// Same as above, but achieves better compression. We use a lazy evaluation
540
//   for matches: a match is finally adopted only if there is no better match
541
//   at the next window position.
542
ZInt64 ZipDflt::deflate(void)
543
{
544
    unsigned hash_head; // head of hash chain
545
    unsigned prev_match; // previous match
546
    int flush; // set if current block
547
    ///* must be flushed
548
    int match_available = 0; // set if previous match
549
    ///* exists
550
    register unsigned match_length = MIN_MATCH - 1; // length of best match
551
 
552
    if (flevel <= 3)
553
        return deflate_fast(); // optimized for speed
554
 
555
    // Process the input block.
556
    while (flookahead != 0)
557
    {        
558
//        if (fout_offset > fout_size || fout_size > sizeof(ffile_outbuf))
559
//        {
560
//            Notify(IWARNING, _T("Write error in flush_outbuf - out_size %d [%d]"),
561
//                fout_offset, fout_size);
562
//            throw DZException(DZ_ERM_ERROR_WRITE);
563
//        }
564
        // Insert the string window[strstart .. strstart+2] in the dictionary,
565
        //   and set hash_head to the head of the hash chain:
566
        INSERT_STRING(fstrstart, hash_head);      
567
//        if (fout_offset > fout_size || fout_size > sizeof(ffile_outbuf))
568
//        {
569
//            Notify(IWARNING, _T("Write error in flush_outbuf - out_size %d [%d]"),
570
//                fout_offset, fout_size);
571
//            throw DZException(DZ_ERM_ERROR_WRITE);
572
//        }
573
 
574
        // Find the longest match, discarding those <= prev_length.
575
        fprev_length = match_length, prev_match = fmatch_start;
576
        match_length = MIN_MATCH - 1;
577
 
578
        if (hash_head != NIL && fprev_length < fmax_lazy_match
579
                && fstrstart - hash_head <= MAX_DIST)
580
        {
581
            // To simplify the code, we prevent matches with the string of window
582
            //   index 0 (in particular we have to avoid a match of the string with
583
            //   itself at the start of the input file).
584
#ifndef HUFFMAN_ONLY
585
            match_length = longest_match(hash_head);
586
#endif
587
            // longest_match() sets match_start
588
 
589
            if (match_length > flookahead)
590
                match_length = flookahead;
591
 
592
            /*
593
            #ifdef FILTERED
594
                  // Ignore matches of length <= 5
595
                  if (match_length <= 5)
596
                  {
597
            #else   */
598
            // Ignore a length 3 match if it is too distant:
599
            if (
600
#ifdef FILTERED
601
                match_length <= 5 &&
602
#endif
603
                match_length == MIN_MATCH && fstrstart - fmatch_start > TOO_FAR)
604
            {
605
                //#endif
606
                // If prev_match is also MIN_MATCH, match_start is garbage but we
607
                //   will ignore the current match anyway.
608
                match_length = MIN_MATCH - 1;
609
            }
610
        }
611
 
612
        // If there was a match at the previous step and the current match is
613
        //   not better, output the previous match:
614
        if (fprev_length >= MIN_MATCH && match_length <= fprev_length)
615
        {
616
#ifdef _DEBUG
617
            check_match(fstrstart - 1, prev_match, fprev_length);
618
#endif
619
            flush = ct_tally(fstrstart - 1 - prev_match, fprev_length - MIN_MATCH);
620
 
621
            // Insert in hash table all strings up to the end of the match.
622
            //   strstart-1 and strstart are already inserted.
623
            flookahead -= fprev_length - 1;
624
            fprev_length -= 2;
625
 
626
            do
627
            {
628
                fstrstart++;
629
                INSERT_STRING(fstrstart, hash_head);
630
 
631
                // strstart never exceeds ZWSIZE-MAX_MATCH, so there are always
632
                //   MIN_MATCH bytes ahead. If lookahead < MIN_MATCH these bytes are
633
                //   garbage, but it does not matter since the next lookahead bytes
634
                //   will always be emitted as literals.
635
            }
636
            while (--fprev_length != 0);
637
 
638
            match_available = 0;
639
            match_length = MIN_MATCH - 1;
640
            fstrstart++;
641
 
642
            if (flush)
643
            {
644
//  FLUSH_BLOCK(0);
645
                FlushBlock(0);
646
                fblock_start = fstrstart;
647
            }
648
//if (fout_offset > fout_size || fout_size > sizeof(ffile_outbuf))
649
//{
650
//    Notify(IWARNING, _T("Write error in flush_outbuf - out_size %d [%d]"),
651
//        fout_offset, fout_size);
652
//    throw DZException(DZ_ERM_ERROR_WRITE);
653
//}
654
 
655
        }
656
        else
657
            if (match_available)
658
            {            
659
//if (fout_offset > fout_size || fout_size > sizeof(ffile_outbuf))
660
//{
661
//    Notify(IWARNING, _T("Write error in flush_outbuf - out_size %d [%d]"),
662
//        fout_offset, fout_size);
663
//    throw DZException(DZ_ERM_ERROR_WRITE);
664
//}
665
 
666
                // If there was no match at the previous position, output a single
667
                //   literal. If there was a match but the current match is longer,
668
                //   truncate the previous match to a single literal.
669
//        Tracevv(("%c"), (fwindow[fstrstart - 1]));
670
                if (ct_tally(0, fwindow[fstrstart - 1]))
671
                {
672
//          FLUSH_BLOCK(0);
673
                    FlushBlock(0);
674
                    fblock_start = fstrstart;
675
                }
676
                fstrstart++;
677
                flookahead--;
678
            }
679
            else
680
            {
681
                // There is no previous match to compare with, wait for the next
682
                //   step to decide.
683
                match_available = 1;
684
                fstrstart++;
685
                flookahead--;
686
            }
687
 
688
        Assert(fstrstart <= fisize && flookahead <= fisize, _T("a bit too far"));
689
 
690
#ifdef _DEBUG
691
        if (!(fstrstart <= fisize && flookahead <= fisize))
692
            Notify(DZ_ERM_LOGIC_ERROR, _T("a bit too far"));
693
#endif
694
        // Make sure that we always have enough lookahead, except at the end
695
        //   of the input file. We need MAX_MATCH bytes for the next match, plus
696
        //   MIN_MATCH bytes to insert the string following the next match.
697
        if (flookahead < MIN_LOOKAHEAD)
698
            fill_window();
699
 
700
        if (Abort_Flag)
701
            Fatal(DZ_ERM_ABORT, 0);
702
//            throw DZAbort(DZ_ERM_ABORT);
703
//        {
704
        // UPDATE: the ziperr() func in dllzip.c closes file.
705
//            return -ZEN_ABORT;
706
        //}
707
    }
708
 
709
    if (match_available)
710
        ct_tally(0, fwindow[fstrstart - 1]);
711
 
712
//  return FLUSH_BLOCK(1); // eof
713
    return FlushBlock(1); //eof
714
}
715
 
716
/* 30/1/07 */
717
 
718
 
719
 
720