diff options
Diffstat (limited to 'deflate.c')
-rw-r--r-- | deflate.c | 273 |
1 files changed, 150 insertions, 123 deletions
@@ -1,6 +1,6 @@ | |||
1 | /* deflate.c -- compress data using the deflation algorithm | 1 | /* deflate.c -- compress data using the deflation algorithm |
2 | * Copyright (C) 1995-2003 Jean-loup Gailly. | 2 | * Copyright (C) 1995-2003 Jean-loup Gailly. |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
6 | /* | 6 | /* |
@@ -52,7 +52,7 @@ | |||
52 | #include "deflate.h" | 52 | #include "deflate.h" |
53 | 53 | ||
54 | const char deflate_copyright[] = | 54 | const char deflate_copyright[] = |
55 | " deflate 1.2.0 Copyright 1995-2003 Jean-loup Gailly "; | 55 | " deflate 1.2.0.1 Copyright 1995-2003 Jean-loup Gailly "; |
56 | /* | 56 | /* |
57 | If you use the zlib library in a product, an acknowledgment is welcome | 57 | If you use the zlib library in a product, an acknowledgment is welcome |
58 | in the documentation of your product. If for some reason you cannot | 58 | in the documentation of your product. If for some reason you cannot |
@@ -76,17 +76,22 @@ typedef block_state (*compress_func) OF((deflate_state *s, int flush)); | |||
76 | local void fill_window OF((deflate_state *s)); | 76 | local void fill_window OF((deflate_state *s)); |
77 | local block_state deflate_stored OF((deflate_state *s, int flush)); | 77 | local block_state deflate_stored OF((deflate_state *s, int flush)); |
78 | local block_state deflate_fast OF((deflate_state *s, int flush)); | 78 | local block_state deflate_fast OF((deflate_state *s, int flush)); |
79 | #ifndef FASTEST | ||
79 | local block_state deflate_slow OF((deflate_state *s, int flush)); | 80 | local block_state deflate_slow OF((deflate_state *s, int flush)); |
81 | #endif | ||
80 | local void lm_init OF((deflate_state *s)); | 82 | local void lm_init OF((deflate_state *s)); |
81 | local void putShortMSB OF((deflate_state *s, uInt b)); | 83 | local void putShortMSB OF((deflate_state *s, uInt b)); |
82 | local void flush_pending OF((z_streamp strm)); | 84 | local void flush_pending OF((z_streamp strm)); |
83 | local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); | 85 | local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); |
86 | #ifndef FASTEST | ||
84 | #ifdef ASMV | 87 | #ifdef ASMV |
85 | void match_init OF((void)); /* asm code initialization */ | 88 | void match_init OF((void)); /* asm code initialization */ |
86 | uInt longest_match OF((deflate_state *s, IPos cur_match)); | 89 | uInt longest_match OF((deflate_state *s, IPos cur_match)); |
87 | #else | 90 | #else |
88 | local uInt longest_match OF((deflate_state *s, IPos cur_match)); | 91 | local uInt longest_match OF((deflate_state *s, IPos cur_match)); |
89 | #endif | 92 | #endif |
93 | #endif | ||
94 | local uInt longest_match_fast OF((deflate_state *s, IPos cur_match)); | ||
90 | 95 | ||
91 | #ifdef DEBUG | 96 | #ifdef DEBUG |
92 | local void check_match OF((deflate_state *s, IPos start, IPos match, | 97 | local void check_match OF((deflate_state *s, IPos start, IPos match, |
@@ -123,6 +128,12 @@ typedef struct config_s { | |||
123 | compress_func func; | 128 | compress_func func; |
124 | } config; | 129 | } config; |
125 | 130 | ||
131 | #ifdef FASTEST | ||
132 | local const config configuration_table[2] = { | ||
133 | /* good lazy nice chain */ | ||
134 | /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ | ||
135 | /* 1 */ {4, 4, 8, 4, deflate_fast}}; /* maximum speed, no lazy matches */ | ||
136 | #else | ||
126 | local const config configuration_table[10] = { | 137 | local const config configuration_table[10] = { |
127 | /* good lazy nice chain */ | 138 | /* good lazy nice chain */ |
128 | /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ | 139 | /* 0 */ {0, 0, 0, 0, deflate_stored}, /* store only */ |
@@ -136,6 +147,7 @@ local const config configuration_table[10] = { | |||
136 | /* 7 */ {8, 32, 128, 256, deflate_slow}, | 147 | /* 7 */ {8, 32, 128, 256, deflate_slow}, |
137 | /* 8 */ {32, 128, 258, 1024, deflate_slow}, | 148 | /* 8 */ {32, 128, 258, 1024, deflate_slow}, |
138 | /* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */ | 149 | /* 9 */ {32, 258, 258, 4096, deflate_slow}}; /* maximum compression */ |
150 | #endif | ||
139 | 151 | ||
140 | /* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 | 152 | /* Note: the deflate() code requires max_lazy >= MIN_MATCH and max_chain >= 4 |
141 | * For deflate_fast() (levels <= 3) good is ignored and lazy has a different | 153 | * For deflate_fast() (levels <= 3) good is ignored and lazy has a different |
@@ -194,13 +206,13 @@ int ZEXPORT deflateInit_(strm, level, version, stream_size) | |||
194 | int stream_size; | 206 | int stream_size; |
195 | { | 207 | { |
196 | return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, | 208 | return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, |
197 | Z_DEFAULT_STRATEGY, version, stream_size); | 209 | Z_DEFAULT_STRATEGY, version, stream_size); |
198 | /* To do: ignore strm->next_in if we use it as window */ | 210 | /* To do: ignore strm->next_in if we use it as window */ |
199 | } | 211 | } |
200 | 212 | ||
201 | /* ========================================================================= */ | 213 | /* ========================================================================= */ |
202 | int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, | 214 | int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, |
203 | version, stream_size) | 215 | version, stream_size) |
204 | z_streamp strm; | 216 | z_streamp strm; |
205 | int level; | 217 | int level; |
206 | int method; | 218 | int method; |
@@ -221,20 +233,21 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, | |||
221 | 233 | ||
222 | if (version == Z_NULL || version[0] != my_version[0] || | 234 | if (version == Z_NULL || version[0] != my_version[0] || |
223 | stream_size != sizeof(z_stream)) { | 235 | stream_size != sizeof(z_stream)) { |
224 | return Z_VERSION_ERROR; | 236 | return Z_VERSION_ERROR; |
225 | } | 237 | } |
226 | if (strm == Z_NULL) return Z_STREAM_ERROR; | 238 | if (strm == Z_NULL) return Z_STREAM_ERROR; |
227 | 239 | ||
228 | strm->msg = Z_NULL; | 240 | strm->msg = Z_NULL; |
229 | if (strm->zalloc == Z_NULL) { | 241 | if (strm->zalloc == Z_NULL) { |
230 | strm->zalloc = zcalloc; | 242 | strm->zalloc = zcalloc; |
231 | strm->opaque = (voidpf)0; | 243 | strm->opaque = (voidpf)0; |
232 | } | 244 | } |
233 | if (strm->zfree == Z_NULL) strm->zfree = zcfree; | 245 | if (strm->zfree == Z_NULL) strm->zfree = zcfree; |
234 | 246 | ||
235 | if (level == Z_DEFAULT_COMPRESSION) level = 6; | ||
236 | #ifdef FASTEST | 247 | #ifdef FASTEST |
237 | level = 1; | 248 | if (level != 0) level = 1; |
249 | #else | ||
250 | if (level == Z_DEFAULT_COMPRESSION) level = 6; | ||
238 | #endif | 251 | #endif |
239 | 252 | ||
240 | if (windowBits < 0) { /* undocumented feature: suppress zlib header */ | 253 | if (windowBits < 0) { /* undocumented feature: suppress zlib header */ |
@@ -243,7 +256,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, | |||
243 | } | 256 | } |
244 | if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || | 257 | if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || |
245 | windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || | 258 | windowBits < 9 || windowBits > 15 || level < 0 || level > 9 || |
246 | strategy < 0 || strategy > Z_HUFFMAN_ONLY) { | 259 | strategy < 0 || strategy > Z_RLE) { |
247 | return Z_STREAM_ERROR; | 260 | return Z_STREAM_ERROR; |
248 | } | 261 | } |
249 | s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); | 262 | s = (deflate_state *) ZALLOC(strm, 1, sizeof(deflate_state)); |
@@ -309,9 +322,9 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) | |||
309 | 322 | ||
310 | if (length < MIN_MATCH) return Z_OK; | 323 | if (length < MIN_MATCH) return Z_OK; |
311 | if (length > MAX_DIST(s)) { | 324 | if (length > MAX_DIST(s)) { |
312 | length = MAX_DIST(s); | 325 | length = MAX_DIST(s); |
313 | #ifndef USE_DICT_HEAD | 326 | #ifndef USE_DICT_HEAD |
314 | dictionary += dictLength - length; /* use the tail of the dictionary */ | 327 | dictionary += dictLength - length; /* use the tail of the dictionary */ |
315 | #endif | 328 | #endif |
316 | } | 329 | } |
317 | zmemcpy(s->window, dictionary, length); | 330 | zmemcpy(s->window, dictionary, length); |
@@ -325,7 +338,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) | |||
325 | s->ins_h = s->window[0]; | 338 | s->ins_h = s->window[0]; |
326 | UPDATE_HASH(s, s->ins_h, s->window[1]); | 339 | UPDATE_HASH(s, s->ins_h, s->window[1]); |
327 | for (n = 0; n <= length - MIN_MATCH; n++) { | 340 | for (n = 0; n <= length - MIN_MATCH; n++) { |
328 | INSERT_STRING(s, n, hash_head); | 341 | INSERT_STRING(s, n, hash_head); |
329 | } | 342 | } |
330 | if (hash_head) hash_head = 0; /* to make compiler happy */ | 343 | if (hash_head) hash_head = 0; /* to make compiler happy */ |
331 | return Z_OK; | 344 | return Z_OK; |
@@ -336,7 +349,7 @@ int ZEXPORT deflateReset (strm) | |||
336 | z_streamp strm; | 349 | z_streamp strm; |
337 | { | 350 | { |
338 | deflate_state *s; | 351 | deflate_state *s; |
339 | 352 | ||
340 | if (strm == Z_NULL || strm->state == Z_NULL || | 353 | if (strm == Z_NULL || strm->state == Z_NULL || |
341 | strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; | 354 | strm->zalloc == Z_NULL || strm->zfree == Z_NULL) return Z_STREAM_ERROR; |
342 | 355 | ||
@@ -374,24 +387,26 @@ int ZEXPORT deflateParams(strm, level, strategy) | |||
374 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | 387 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; |
375 | s = strm->state; | 388 | s = strm->state; |
376 | 389 | ||
377 | if (level == Z_DEFAULT_COMPRESSION) { | 390 | #ifdef FASTEST |
378 | level = 6; | 391 | if (level != 0) level = 1; |
379 | } | 392 | #else |
380 | if (level < 0 || level > 9 || strategy < 0 || strategy > Z_HUFFMAN_ONLY) { | 393 | if (level == Z_DEFAULT_COMPRESSION) level = 6; |
381 | return Z_STREAM_ERROR; | 394 | #endif |
395 | if (level < 0 || level > 9 || strategy < 0 || strategy > Z_RLE) { | ||
396 | return Z_STREAM_ERROR; | ||
382 | } | 397 | } |
383 | func = configuration_table[s->level].func; | 398 | func = configuration_table[s->level].func; |
384 | 399 | ||
385 | if (func != configuration_table[level].func && strm->total_in != 0) { | 400 | if (func != configuration_table[level].func && strm->total_in != 0) { |
386 | /* Flush the last buffer: */ | 401 | /* Flush the last buffer: */ |
387 | err = deflate(strm, Z_PARTIAL_FLUSH); | 402 | err = deflate(strm, Z_PARTIAL_FLUSH); |
388 | } | 403 | } |
389 | if (s->level != level) { | 404 | if (s->level != level) { |
390 | s->level = level; | 405 | s->level = level; |
391 | s->max_lazy_match = configuration_table[level].max_lazy; | 406 | s->max_lazy_match = configuration_table[level].max_lazy; |
392 | s->good_match = configuration_table[level].good_length; | 407 | s->good_match = configuration_table[level].good_length; |
393 | s->nice_match = configuration_table[level].nice_length; | 408 | s->nice_match = configuration_table[level].nice_length; |
394 | s->max_chain_length = configuration_table[level].max_chain; | 409 | s->max_chain_length = configuration_table[level].max_chain; |
395 | } | 410 | } |
396 | s->strategy = strategy; | 411 | s->strategy = strategy; |
397 | return err; | 412 | return err; |
@@ -449,7 +464,7 @@ local void putShortMSB (s, b) | |||
449 | { | 464 | { |
450 | put_byte(s, (Byte)(b >> 8)); | 465 | put_byte(s, (Byte)(b >> 8)); |
451 | put_byte(s, (Byte)(b & 0xff)); | 466 | put_byte(s, (Byte)(b & 0xff)); |
452 | } | 467 | } |
453 | 468 | ||
454 | /* ========================================================================= | 469 | /* ========================================================================= |
455 | * Flush as much pending output as possible. All deflate() output goes | 470 | * Flush as much pending output as possible. All deflate() output goes |
@@ -485,14 +500,14 @@ int ZEXPORT deflate (strm, flush) | |||
485 | deflate_state *s; | 500 | deflate_state *s; |
486 | 501 | ||
487 | if (strm == Z_NULL || strm->state == Z_NULL || | 502 | if (strm == Z_NULL || strm->state == Z_NULL || |
488 | flush > Z_FINISH || flush < 0) { | 503 | flush > Z_FINISH || flush < 0) { |
489 | return Z_STREAM_ERROR; | 504 | return Z_STREAM_ERROR; |
490 | } | 505 | } |
491 | s = strm->state; | 506 | s = strm->state; |
492 | 507 | ||
493 | if (strm->next_out == Z_NULL || | 508 | if (strm->next_out == Z_NULL || |
494 | (strm->next_in == Z_NULL && strm->avail_in != 0) || | 509 | (strm->next_in == Z_NULL && strm->avail_in != 0) || |
495 | (s->status == FINISH_STATE && flush != Z_FINISH)) { | 510 | (s->status == FINISH_STATE && flush != Z_FINISH)) { |
496 | ERR_RETURN(strm, Z_STREAM_ERROR); | 511 | ERR_RETURN(strm, Z_STREAM_ERROR); |
497 | } | 512 | } |
498 | if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); | 513 | if (strm->avail_out == 0) ERR_RETURN(strm, Z_BUF_ERROR); |
@@ -509,40 +524,40 @@ int ZEXPORT deflate (strm, flush) | |||
509 | 524 | ||
510 | if (level_flags > 3) level_flags = 3; | 525 | if (level_flags > 3) level_flags = 3; |
511 | header |= (level_flags << 6); | 526 | header |= (level_flags << 6); |
512 | if (s->strstart != 0) header |= PRESET_DICT; | 527 | if (s->strstart != 0) header |= PRESET_DICT; |
513 | header += 31 - (header % 31); | 528 | header += 31 - (header % 31); |
514 | 529 | ||
515 | s->status = BUSY_STATE; | 530 | s->status = BUSY_STATE; |
516 | putShortMSB(s, header); | 531 | putShortMSB(s, header); |
517 | 532 | ||
518 | /* Save the adler32 of the preset dictionary: */ | 533 | /* Save the adler32 of the preset dictionary: */ |
519 | if (s->strstart != 0) { | 534 | if (s->strstart != 0) { |
520 | putShortMSB(s, (uInt)(strm->adler >> 16)); | 535 | putShortMSB(s, (uInt)(strm->adler >> 16)); |
521 | putShortMSB(s, (uInt)(strm->adler & 0xffff)); | 536 | putShortMSB(s, (uInt)(strm->adler & 0xffff)); |
522 | } | 537 | } |
523 | strm->adler = 1L; | 538 | strm->adler = 1L; |
524 | } | 539 | } |
525 | 540 | ||
526 | /* Flush as much pending output as possible */ | 541 | /* Flush as much pending output as possible */ |
527 | if (s->pending != 0) { | 542 | if (s->pending != 0) { |
528 | flush_pending(strm); | 543 | flush_pending(strm); |
529 | if (strm->avail_out == 0) { | 544 | if (strm->avail_out == 0) { |
530 | /* Since avail_out is 0, deflate will be called again with | 545 | /* Since avail_out is 0, deflate will be called again with |
531 | * more output space, but possibly with both pending and | 546 | * more output space, but possibly with both pending and |
532 | * avail_in equal to zero. There won't be anything to do, | 547 | * avail_in equal to zero. There won't be anything to do, |
533 | * but this is not an error situation so make sure we | 548 | * but this is not an error situation so make sure we |
534 | * return OK instead of BUF_ERROR at next call of deflate: | 549 | * return OK instead of BUF_ERROR at next call of deflate: |
535 | */ | 550 | */ |
536 | s->last_flush = -1; | 551 | s->last_flush = -1; |
537 | return Z_OK; | 552 | return Z_OK; |
538 | } | 553 | } |
539 | 554 | ||
540 | /* Make sure there is something to do and avoid duplicate consecutive | 555 | /* Make sure there is something to do and avoid duplicate consecutive |
541 | * flushes. For repeated and useless calls with Z_FINISH, we keep | 556 | * flushes. For repeated and useless calls with Z_FINISH, we keep |
542 | * returning Z_STREAM_END instead of Z_BUFF_ERROR. | 557 | * returning Z_STREAM_END instead of Z_BUF_ERROR. |
543 | */ | 558 | */ |
544 | } else if (strm->avail_in == 0 && flush <= old_flush && | 559 | } else if (strm->avail_in == 0 && flush <= old_flush && |
545 | flush != Z_FINISH) { | 560 | flush != Z_FINISH) { |
546 | ERR_RETURN(strm, Z_BUF_ERROR); | 561 | ERR_RETURN(strm, Z_BUF_ERROR); |
547 | } | 562 | } |
548 | 563 | ||
@@ -557,24 +572,24 @@ int ZEXPORT deflate (strm, flush) | |||
557 | (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { | 572 | (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { |
558 | block_state bstate; | 573 | block_state bstate; |
559 | 574 | ||
560 | bstate = (*(configuration_table[s->level].func))(s, flush); | 575 | bstate = (*(configuration_table[s->level].func))(s, flush); |
561 | 576 | ||
562 | if (bstate == finish_started || bstate == finish_done) { | 577 | if (bstate == finish_started || bstate == finish_done) { |
563 | s->status = FINISH_STATE; | 578 | s->status = FINISH_STATE; |
564 | } | 579 | } |
565 | if (bstate == need_more || bstate == finish_started) { | 580 | if (bstate == need_more || bstate == finish_started) { |
566 | if (strm->avail_out == 0) { | 581 | if (strm->avail_out == 0) { |
567 | s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ | 582 | s->last_flush = -1; /* avoid BUF_ERROR next call, see above */ |
568 | } | 583 | } |
569 | return Z_OK; | 584 | return Z_OK; |
570 | /* If flush != Z_NO_FLUSH && avail_out == 0, the next call | 585 | /* If flush != Z_NO_FLUSH && avail_out == 0, the next call |
571 | * of deflate should use the same flush parameter to make sure | 586 | * of deflate should use the same flush parameter to make sure |
572 | * that the flush is complete. So we don't have to output an | 587 | * that the flush is complete. So we don't have to output an |
573 | * empty block here, this will be done at next call. This also | 588 | * empty block here, this will be done at next call. This also |
574 | * ensures that for a very small output buffer, we emit at most | 589 | * ensures that for a very small output buffer, we emit at most |
575 | * one empty block. | 590 | * one empty block. |
576 | */ | 591 | */ |
577 | } | 592 | } |
578 | if (bstate == block_done) { | 593 | if (bstate == block_done) { |
579 | if (flush == Z_PARTIAL_FLUSH) { | 594 | if (flush == Z_PARTIAL_FLUSH) { |
580 | _tr_align(s); | 595 | _tr_align(s); |
@@ -588,10 +603,10 @@ int ZEXPORT deflate (strm, flush) | |||
588 | } | 603 | } |
589 | } | 604 | } |
590 | flush_pending(strm); | 605 | flush_pending(strm); |
591 | if (strm->avail_out == 0) { | 606 | if (strm->avail_out == 0) { |
592 | s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ | 607 | s->last_flush = -1; /* avoid BUF_ERROR at next call, see above */ |
593 | return Z_OK; | 608 | return Z_OK; |
594 | } | 609 | } |
595 | } | 610 | } |
596 | } | 611 | } |
597 | Assert(strm->avail_out > 0, "bug2"); | 612 | Assert(strm->avail_out > 0, "bug2"); |
@@ -620,7 +635,7 @@ int ZEXPORT deflateEnd (strm) | |||
620 | 635 | ||
621 | status = strm->state->status; | 636 | status = strm->state->status; |
622 | if (status != INIT_STATE && status != BUSY_STATE && | 637 | if (status != INIT_STATE && status != BUSY_STATE && |
623 | status != FINISH_STATE) { | 638 | status != FINISH_STATE) { |
624 | return Z_STREAM_ERROR; | 639 | return Z_STREAM_ERROR; |
625 | } | 640 | } |
626 | 641 | ||
@@ -693,7 +708,7 @@ int ZEXPORT deflateCopy (dest, source) | |||
693 | ds->bl_desc.dyn_tree = ds->bl_tree; | 708 | ds->bl_desc.dyn_tree = ds->bl_tree; |
694 | 709 | ||
695 | return Z_OK; | 710 | return Z_OK; |
696 | #endif | 711 | #endif /* MAXSEG_64K */ |
697 | } | 712 | } |
698 | 713 | ||
699 | /* =========================================================================== | 714 | /* =========================================================================== |
@@ -753,6 +768,7 @@ local void lm_init (s) | |||
753 | #endif | 768 | #endif |
754 | } | 769 | } |
755 | 770 | ||
771 | #ifndef FASTEST | ||
756 | /* =========================================================================== | 772 | /* =========================================================================== |
757 | * Set match_start to the longest match starting at the given string and | 773 | * Set match_start to the longest match starting at the given string and |
758 | * return its length. Matches shorter or equal to prev_length are discarded, | 774 | * return its length. Matches shorter or equal to prev_length are discarded, |
@@ -766,7 +782,6 @@ local void lm_init (s) | |||
766 | /* For 80x86 and 680x0, an optimized version will be provided in match.asm or | 782 | /* For 80x86 and 680x0, an optimized version will be provided in match.asm or |
767 | * match.S. The code will be functionally equivalent. | 783 | * match.S. The code will be functionally equivalent. |
768 | */ | 784 | */ |
769 | #ifndef FASTEST | ||
770 | local uInt longest_match(s, cur_match) | 785 | local uInt longest_match(s, cur_match) |
771 | deflate_state *s; | 786 | deflate_state *s; |
772 | IPos cur_match; /* current match */ | 787 | IPos cur_match; /* current match */ |
@@ -904,12 +919,13 @@ local uInt longest_match(s, cur_match) | |||
904 | if ((uInt)best_len <= s->lookahead) return (uInt)best_len; | 919 | if ((uInt)best_len <= s->lookahead) return (uInt)best_len; |
905 | return s->lookahead; | 920 | return s->lookahead; |
906 | } | 921 | } |
922 | #endif /* ASMV */ | ||
923 | #endif /* FASTEST */ | ||
907 | 924 | ||
908 | #else /* FASTEST */ | ||
909 | /* --------------------------------------------------------------------------- | 925 | /* --------------------------------------------------------------------------- |
910 | * Optimized version for level == 1 only | 926 | * Optimized version for level == 1 or strategy == Z_RLE only |
911 | */ | 927 | */ |
912 | local uInt longest_match(s, cur_match) | 928 | local uInt longest_match_fast(s, cur_match) |
913 | deflate_state *s; | 929 | deflate_state *s; |
914 | IPos cur_match; /* current match */ | 930 | IPos cur_match; /* current match */ |
915 | { | 931 | { |
@@ -947,10 +963,10 @@ local uInt longest_match(s, cur_match) | |||
947 | */ | 963 | */ |
948 | do { | 964 | do { |
949 | } while (*++scan == *++match && *++scan == *++match && | 965 | } while (*++scan == *++match && *++scan == *++match && |
950 | *++scan == *++match && *++scan == *++match && | 966 | *++scan == *++match && *++scan == *++match && |
951 | *++scan == *++match && *++scan == *++match && | 967 | *++scan == *++match && *++scan == *++match && |
952 | *++scan == *++match && *++scan == *++match && | 968 | *++scan == *++match && *++scan == *++match && |
953 | scan < strend); | 969 | scan < strend); |
954 | 970 | ||
955 | Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); | 971 | Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); |
956 | 972 | ||
@@ -961,8 +977,6 @@ local uInt longest_match(s, cur_match) | |||
961 | s->match_start = cur_match; | 977 | s->match_start = cur_match; |
962 | return len <= s->lookahead ? len : s->lookahead; | 978 | return len <= s->lookahead ? len : s->lookahead; |
963 | } | 979 | } |
964 | #endif /* FASTEST */ | ||
965 | #endif /* ASMV */ | ||
966 | 980 | ||
967 | #ifdef DEBUG | 981 | #ifdef DEBUG |
968 | /* =========================================================================== | 982 | /* =========================================================================== |
@@ -977,10 +991,10 @@ local void check_match(s, start, match, length) | |||
977 | if (zmemcmp(s->window + match, | 991 | if (zmemcmp(s->window + match, |
978 | s->window + start, length) != EQUAL) { | 992 | s->window + start, length) != EQUAL) { |
979 | fprintf(stderr, " start %u, match %u, length %d\n", | 993 | fprintf(stderr, " start %u, match %u, length %d\n", |
980 | start, match, length); | 994 | start, match, length); |
981 | do { | 995 | do { |
982 | fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); | 996 | fprintf(stderr, "%c%c", s->window[match++], s->window[start++]); |
983 | } while (--length != 0); | 997 | } while (--length != 0); |
984 | z_error("invalid match"); | 998 | z_error("invalid match"); |
985 | } | 999 | } |
986 | if (z_verbose > 1) { | 1000 | if (z_verbose > 1) { |
@@ -990,7 +1004,7 @@ local void check_match(s, start, match, length) | |||
990 | } | 1004 | } |
991 | #else | 1005 | #else |
992 | # define check_match(s, start, match, length) | 1006 | # define check_match(s, start, match, length) |
993 | #endif | 1007 | #endif /* DEBUG */ |
994 | 1008 | ||
995 | /* =========================================================================== | 1009 | /* =========================================================================== |
996 | * Fill the window when the lookahead becomes insufficient. | 1010 | * Fill the window when the lookahead becomes insufficient. |
@@ -1039,23 +1053,23 @@ local void fill_window(s) | |||
1039 | later. (Using level 0 permanently is not an optimal usage of | 1053 | later. (Using level 0 permanently is not an optimal usage of |
1040 | zlib, so we don't care about this pathological case.) | 1054 | zlib, so we don't care about this pathological case.) |
1041 | */ | 1055 | */ |
1042 | n = s->hash_size; | 1056 | n = s->hash_size; |
1043 | p = &s->head[n]; | 1057 | p = &s->head[n]; |
1044 | do { | 1058 | do { |
1045 | m = *--p; | 1059 | m = *--p; |
1046 | *p = (Pos)(m >= wsize ? m-wsize : NIL); | 1060 | *p = (Pos)(m >= wsize ? m-wsize : NIL); |
1047 | } while (--n); | 1061 | } while (--n); |
1048 | 1062 | ||
1049 | n = wsize; | 1063 | n = wsize; |
1050 | #ifndef FASTEST | 1064 | #ifndef FASTEST |
1051 | p = &s->prev[n]; | 1065 | p = &s->prev[n]; |
1052 | do { | 1066 | do { |
1053 | m = *--p; | 1067 | m = *--p; |
1054 | *p = (Pos)(m >= wsize ? m-wsize : NIL); | 1068 | *p = (Pos)(m >= wsize ? m-wsize : NIL); |
1055 | /* If n is not on any hash chain, prev[n] is garbage but | 1069 | /* If n is not on any hash chain, prev[n] is garbage but |
1056 | * its value will never be used. | 1070 | * its value will never be used. |
1057 | */ | 1071 | */ |
1058 | } while (--n); | 1072 | } while (--n); |
1059 | #endif | 1073 | #endif |
1060 | more += wsize; | 1074 | more += wsize; |
1061 | } | 1075 | } |
@@ -1100,8 +1114,8 @@ local void fill_window(s) | |||
1100 | _tr_flush_block(s, (s->block_start >= 0L ? \ | 1114 | _tr_flush_block(s, (s->block_start >= 0L ? \ |
1101 | (charf *)&s->window[(unsigned)s->block_start] : \ | 1115 | (charf *)&s->window[(unsigned)s->block_start] : \ |
1102 | (charf *)Z_NULL), \ | 1116 | (charf *)Z_NULL), \ |
1103 | (ulg)((long)s->strstart - s->block_start), \ | 1117 | (ulg)((long)s->strstart - s->block_start), \ |
1104 | (eof)); \ | 1118 | (eof)); \ |
1105 | s->block_start = s->strstart; \ | 1119 | s->block_start = s->strstart; \ |
1106 | flush_pending(s->strm); \ | 1120 | flush_pending(s->strm); \ |
1107 | Tracev((stderr,"[FLUSH]")); \ | 1121 | Tracev((stderr,"[FLUSH]")); \ |
@@ -1142,32 +1156,32 @@ local block_state deflate_stored(s, flush) | |||
1142 | if (s->lookahead <= 1) { | 1156 | if (s->lookahead <= 1) { |
1143 | 1157 | ||
1144 | Assert(s->strstart < s->w_size+MAX_DIST(s) || | 1158 | Assert(s->strstart < s->w_size+MAX_DIST(s) || |
1145 | s->block_start >= (long)s->w_size, "slide too late"); | 1159 | s->block_start >= (long)s->w_size, "slide too late"); |
1146 | 1160 | ||
1147 | fill_window(s); | 1161 | fill_window(s); |
1148 | if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; | 1162 | if (s->lookahead == 0 && flush == Z_NO_FLUSH) return need_more; |
1149 | 1163 | ||
1150 | if (s->lookahead == 0) break; /* flush the current block */ | 1164 | if (s->lookahead == 0) break; /* flush the current block */ |
1151 | } | 1165 | } |
1152 | Assert(s->block_start >= 0L, "block gone"); | 1166 | Assert(s->block_start >= 0L, "block gone"); |
1153 | 1167 | ||
1154 | s->strstart += s->lookahead; | 1168 | s->strstart += s->lookahead; |
1155 | s->lookahead = 0; | 1169 | s->lookahead = 0; |
1156 | 1170 | ||
1157 | /* Emit a stored block if pending_buf will be full: */ | 1171 | /* Emit a stored block if pending_buf will be full: */ |
1158 | max_start = s->block_start + max_block_size; | 1172 | max_start = s->block_start + max_block_size; |
1159 | if (s->strstart == 0 || (ulg)s->strstart >= max_start) { | 1173 | if (s->strstart == 0 || (ulg)s->strstart >= max_start) { |
1160 | /* strstart == 0 is possible when wraparound on 16-bit machine */ | 1174 | /* strstart == 0 is possible when wraparound on 16-bit machine */ |
1161 | s->lookahead = (uInt)(s->strstart - max_start); | 1175 | s->lookahead = (uInt)(s->strstart - max_start); |
1162 | s->strstart = (uInt)max_start; | 1176 | s->strstart = (uInt)max_start; |
1163 | FLUSH_BLOCK(s, 0); | 1177 | FLUSH_BLOCK(s, 0); |
1164 | } | 1178 | } |
1165 | /* Flush if we may have to slide, otherwise block_start may become | 1179 | /* Flush if we may have to slide, otherwise block_start may become |
1166 | * negative and the data will be gone: | 1180 | * negative and the data will be gone: |
1167 | */ | 1181 | */ |
1168 | if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { | 1182 | if (s->strstart - (uInt)s->block_start >= MAX_DIST(s)) { |
1169 | FLUSH_BLOCK(s, 0); | 1183 | FLUSH_BLOCK(s, 0); |
1170 | } | 1184 | } |
1171 | } | 1185 | } |
1172 | FLUSH_BLOCK(s, flush == Z_FINISH); | 1186 | FLUSH_BLOCK(s, flush == Z_FINISH); |
1173 | return flush == Z_FINISH ? finish_done : block_done; | 1187 | return flush == Z_FINISH ? finish_done : block_done; |
@@ -1196,8 +1210,8 @@ local block_state deflate_fast(s, flush) | |||
1196 | if (s->lookahead < MIN_LOOKAHEAD) { | 1210 | if (s->lookahead < MIN_LOOKAHEAD) { |
1197 | fill_window(s); | 1211 | fill_window(s); |
1198 | if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { | 1212 | if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { |
1199 | return need_more; | 1213 | return need_more; |
1200 | } | 1214 | } |
1201 | if (s->lookahead == 0) break; /* flush the current block */ | 1215 | if (s->lookahead == 0) break; /* flush the current block */ |
1202 | } | 1216 | } |
1203 | 1217 | ||
@@ -1216,10 +1230,19 @@ local block_state deflate_fast(s, flush) | |||
1216 | * of window index 0 (in particular we have to avoid a match | 1230 | * of window index 0 (in particular we have to avoid a match |
1217 | * of the string with itself at the start of the input file). | 1231 | * of the string with itself at the start of the input file). |
1218 | */ | 1232 | */ |
1219 | if (s->strategy != Z_HUFFMAN_ONLY) { | 1233 | #ifdef FASTEST |
1234 | if ((s->strategy < Z_HUFFMAN_ONLY) || | ||
1235 | (s->strategy == Z_RLE && s->strstart - hash_head == 1)) { | ||
1236 | s->match_length = longest_match_fast (s, hash_head); | ||
1237 | } | ||
1238 | #else | ||
1239 | if (s->strategy < Z_HUFFMAN_ONLY) { | ||
1220 | s->match_length = longest_match (s, hash_head); | 1240 | s->match_length = longest_match (s, hash_head); |
1241 | } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { | ||
1242 | s->match_length = longest_match_fast (s, hash_head); | ||
1221 | } | 1243 | } |
1222 | /* longest_match() sets match_start */ | 1244 | #endif |
1245 | /* longest_match() or longest_match_fast() sets match_start */ | ||
1223 | } | 1246 | } |
1224 | if (s->match_length >= MIN_MATCH) { | 1247 | if (s->match_length >= MIN_MATCH) { |
1225 | check_match(s, s->strstart, s->match_start, s->match_length); | 1248 | check_match(s, s->strstart, s->match_start, s->match_length); |
@@ -1243,10 +1266,10 @@ local block_state deflate_fast(s, flush) | |||
1243 | * always MIN_MATCH bytes ahead. | 1266 | * always MIN_MATCH bytes ahead. |
1244 | */ | 1267 | */ |
1245 | } while (--s->match_length != 0); | 1268 | } while (--s->match_length != 0); |
1246 | s->strstart++; | 1269 | s->strstart++; |
1247 | } else | 1270 | } else |
1248 | #endif | 1271 | #endif |
1249 | { | 1272 | { |
1250 | s->strstart += s->match_length; | 1273 | s->strstart += s->match_length; |
1251 | s->match_length = 0; | 1274 | s->match_length = 0; |
1252 | s->ins_h = s->window[s->strstart]; | 1275 | s->ins_h = s->window[s->strstart]; |
@@ -1263,7 +1286,7 @@ local block_state deflate_fast(s, flush) | |||
1263 | Tracevv((stderr,"%c", s->window[s->strstart])); | 1286 | Tracevv((stderr,"%c", s->window[s->strstart])); |
1264 | _tr_tally_lit (s, s->window[s->strstart], bflush); | 1287 | _tr_tally_lit (s, s->window[s->strstart], bflush); |
1265 | s->lookahead--; | 1288 | s->lookahead--; |
1266 | s->strstart++; | 1289 | s->strstart++; |
1267 | } | 1290 | } |
1268 | if (bflush) FLUSH_BLOCK(s, 0); | 1291 | if (bflush) FLUSH_BLOCK(s, 0); |
1269 | } | 1292 | } |
@@ -1271,6 +1294,7 @@ local block_state deflate_fast(s, flush) | |||
1271 | return flush == Z_FINISH ? finish_done : block_done; | 1294 | return flush == Z_FINISH ? finish_done : block_done; |
1272 | } | 1295 | } |
1273 | 1296 | ||
1297 | #ifndef FASTEST | ||
1274 | /* =========================================================================== | 1298 | /* =========================================================================== |
1275 | * Same as above, but achieves better compression. We use a lazy | 1299 | * Same as above, but achieves better compression. We use a lazy |
1276 | * evaluation for matches: a match is finally adopted only if there is | 1300 | * evaluation for matches: a match is finally adopted only if there is |
@@ -1293,8 +1317,8 @@ local block_state deflate_slow(s, flush) | |||
1293 | if (s->lookahead < MIN_LOOKAHEAD) { | 1317 | if (s->lookahead < MIN_LOOKAHEAD) { |
1294 | fill_window(s); | 1318 | fill_window(s); |
1295 | if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { | 1319 | if (s->lookahead < MIN_LOOKAHEAD && flush == Z_NO_FLUSH) { |
1296 | return need_more; | 1320 | return need_more; |
1297 | } | 1321 | } |
1298 | if (s->lookahead == 0) break; /* flush the current block */ | 1322 | if (s->lookahead == 0) break; /* flush the current block */ |
1299 | } | 1323 | } |
1300 | 1324 | ||
@@ -1316,10 +1340,12 @@ local block_state deflate_slow(s, flush) | |||
1316 | * of window index 0 (in particular we have to avoid a match | 1340 | * of window index 0 (in particular we have to avoid a match |
1317 | * of the string with itself at the start of the input file). | 1341 | * of the string with itself at the start of the input file). |
1318 | */ | 1342 | */ |
1319 | if (s->strategy != Z_HUFFMAN_ONLY) { | 1343 | if (s->strategy < Z_HUFFMAN_ONLY) { |
1320 | s->match_length = longest_match (s, hash_head); | 1344 | s->match_length = longest_match (s, hash_head); |
1345 | } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { | ||
1346 | s->match_length = longest_match_fast (s, hash_head); | ||
1321 | } | 1347 | } |
1322 | /* longest_match() sets match_start */ | 1348 | /* longest_match() or longest_match_fast() sets match_start */ |
1323 | 1349 | ||
1324 | if (s->match_length <= 5 && (s->strategy == Z_FILTERED || | 1350 | if (s->match_length <= 5 && (s->strategy == Z_FILTERED || |
1325 | (s->match_length == MIN_MATCH && | 1351 | (s->match_length == MIN_MATCH && |
@@ -1341,7 +1367,7 @@ local block_state deflate_slow(s, flush) | |||
1341 | check_match(s, s->strstart-1, s->prev_match, s->prev_length); | 1367 | check_match(s, s->strstart-1, s->prev_match, s->prev_length); |
1342 | 1368 | ||
1343 | _tr_tally_dist(s, s->strstart -1 - s->prev_match, | 1369 | _tr_tally_dist(s, s->strstart -1 - s->prev_match, |
1344 | s->prev_length - MIN_MATCH, bflush); | 1370 | s->prev_length - MIN_MATCH, bflush); |
1345 | 1371 | ||
1346 | /* Insert in hash table all strings up to the end of the match. | 1372 | /* Insert in hash table all strings up to the end of the match. |
1347 | * strstart-1 and strstart are already inserted. If there is not | 1373 | * strstart-1 and strstart are already inserted. If there is not |
@@ -1367,8 +1393,8 @@ local block_state deflate_slow(s, flush) | |||
1367 | * is longer, truncate the previous match to a single literal. | 1393 | * is longer, truncate the previous match to a single literal. |
1368 | */ | 1394 | */ |
1369 | Tracevv((stderr,"%c", s->window[s->strstart-1])); | 1395 | Tracevv((stderr,"%c", s->window[s->strstart-1])); |
1370 | _tr_tally_lit(s, s->window[s->strstart-1], bflush); | 1396 | _tr_tally_lit(s, s->window[s->strstart-1], bflush); |
1371 | if (bflush) { | 1397 | if (bflush) { |
1372 | FLUSH_BLOCK_ONLY(s, 0); | 1398 | FLUSH_BLOCK_ONLY(s, 0); |
1373 | } | 1399 | } |
1374 | s->strstart++; | 1400 | s->strstart++; |
@@ -1392,3 +1418,4 @@ local block_state deflate_slow(s, flush) | |||
1392 | FLUSH_BLOCK(s, flush == Z_FINISH); | 1418 | FLUSH_BLOCK(s, flush == Z_FINISH); |
1393 | return flush == Z_FINISH ? finish_done : block_done; | 1419 | return flush == Z_FINISH ? finish_done : block_done; |
1394 | } | 1420 | } |
1421 | #endif /* FASTEST */ | ||