diff options
Diffstat (limited to 'deflate.c')
-rw-r--r-- | deflate.c | 93 |
1 files changed, 85 insertions, 8 deletions
@@ -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.0.9 Copyright 1995-1998 Jean-loup Gailly "; | 55 | " deflate 1.1.0 Copyright 1995-1998 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 |
@@ -160,14 +160,23 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */ | |||
160 | * Insert string str in the dictionary and set match_head to the previous head | 160 | * Insert string str in the dictionary and set match_head to the previous head |
161 | * of the hash chain (the most recent string with same hash key). Return | 161 | * of the hash chain (the most recent string with same hash key). Return |
162 | * the previous length of the hash chain. | 162 | * the previous length of the hash chain. |
163 | * If this file is compiled with -DFASTEST, the compression level is forced | ||
164 | * to 1, and no hash chains are maintained. | ||
163 | * IN assertion: all calls to to INSERT_STRING are made with consecutive | 165 | * IN assertion: all calls to to INSERT_STRING are made with consecutive |
164 | * input characters and the first MIN_MATCH bytes of str are valid | 166 | * input characters and the first MIN_MATCH bytes of str are valid |
165 | * (except for the last MIN_MATCH-1 bytes of the input file). | 167 | * (except for the last MIN_MATCH-1 bytes of the input file). |
166 | */ | 168 | */ |
169 | #ifdef FASTEST | ||
170 | #define INSERT_STRING(s, str, match_head) \ | ||
171 | (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ | ||
172 | match_head = s->head[s->ins_h], \ | ||
173 | s->head[s->ins_h] = (Pos)(str)) | ||
174 | #else | ||
167 | #define INSERT_STRING(s, str, match_head) \ | 175 | #define INSERT_STRING(s, str, match_head) \ |
168 | (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ | 176 | (UPDATE_HASH(s, s->ins_h, s->window[(str) + (MIN_MATCH-1)]), \ |
169 | s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ | 177 | s->prev[(str) & s->w_mask] = match_head = s->head[s->ins_h], \ |
170 | s->head[s->ins_h] = (Pos)(str)) | 178 | s->head[s->ins_h] = (Pos)(str)) |
179 | #endif | ||
171 | 180 | ||
172 | /* =========================================================================== | 181 | /* =========================================================================== |
173 | * Initialize the hash table (avoiding 64K overflow for 16 bit systems). | 182 | * Initialize the hash table (avoiding 64K overflow for 16 bit systems). |
@@ -224,6 +233,9 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, | |||
224 | if (strm->zfree == Z_NULL) strm->zfree = zcfree; | 233 | if (strm->zfree == Z_NULL) strm->zfree = zcfree; |
225 | 234 | ||
226 | if (level == Z_DEFAULT_COMPRESSION) level = 6; | 235 | if (level == Z_DEFAULT_COMPRESSION) level = 6; |
236 | #ifdef FASTEST | ||
237 | level = 1; | ||
238 | #endif | ||
227 | 239 | ||
228 | if (windowBits < 0) { /* undocumented feature: suppress zlib header */ | 240 | if (windowBits < 0) { /* undocumented feature: suppress zlib header */ |
229 | noheader = 1; | 241 | noheader = 1; |
@@ -708,6 +720,7 @@ local void lm_init (s) | |||
708 | /* For 80x86 and 680x0, an optimized version will be provided in match.asm or | 720 | /* For 80x86 and 680x0, an optimized version will be provided in match.asm or |
709 | * match.S. The code will be functionally equivalent. | 721 | * match.S. The code will be functionally equivalent. |
710 | */ | 722 | */ |
723 | #ifndef FASTEST | ||
711 | local uInt longest_match(s, cur_match) | 724 | local uInt longest_match(s, cur_match) |
712 | deflate_state *s; | 725 | deflate_state *s; |
713 | IPos cur_match; /* current match */ | 726 | IPos cur_match; /* current match */ |
@@ -845,6 +858,64 @@ local uInt longest_match(s, cur_match) | |||
845 | if ((uInt)best_len <= s->lookahead) return (uInt)best_len; | 858 | if ((uInt)best_len <= s->lookahead) return (uInt)best_len; |
846 | return s->lookahead; | 859 | return s->lookahead; |
847 | } | 860 | } |
861 | |||
862 | #else /* FASTEST */ | ||
863 | /* --------------------------------------------------------------------------- | ||
864 | * Optimized version for level == 1 only | ||
865 | */ | ||
866 | local uInt longest_match(s, cur_match) | ||
867 | deflate_state *s; | ||
868 | IPos cur_match; /* current match */ | ||
869 | { | ||
870 | register Bytef *scan = s->window + s->strstart; /* current string */ | ||
871 | register Bytef *match; /* matched string */ | ||
872 | register int len; /* length of current match */ | ||
873 | register Bytef *strend = s->window + s->strstart + MAX_MATCH; | ||
874 | |||
875 | /* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16. | ||
876 | * It is easy to get rid of this optimization if necessary. | ||
877 | */ | ||
878 | Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever"); | ||
879 | |||
880 | Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead"); | ||
881 | |||
882 | Assert(cur_match < s->strstart, "no future"); | ||
883 | |||
884 | match = s->window + cur_match; | ||
885 | |||
886 | /* Return failure if the match length is less than 2: | ||
887 | */ | ||
888 | if (match[0] != scan[0] || match[1] != scan[1]) return MIN_MATCH-1; | ||
889 | |||
890 | /* The check at best_len-1 can be removed because it will be made | ||
891 | * again later. (This heuristic is not always a win.) | ||
892 | * It is not necessary to compare scan[2] and match[2] since they | ||
893 | * are always equal when the other bytes match, given that | ||
894 | * the hash keys are equal and that HASH_BITS >= 8. | ||
895 | */ | ||
896 | scan += 2, match += 2; | ||
897 | Assert(*scan == *match, "match[2]?"); | ||
898 | |||
899 | /* We check for insufficient lookahead only every 8th comparison; | ||
900 | * the 256th check will be made at strstart+258. | ||
901 | */ | ||
902 | do { | ||
903 | } while (*++scan == *++match && *++scan == *++match && | ||
904 | *++scan == *++match && *++scan == *++match && | ||
905 | *++scan == *++match && *++scan == *++match && | ||
906 | *++scan == *++match && *++scan == *++match && | ||
907 | scan < strend); | ||
908 | |||
909 | Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan"); | ||
910 | |||
911 | len = MAX_MATCH - (int)(strend - scan); | ||
912 | |||
913 | if (len < MIN_MATCH) return MIN_MATCH - 1; | ||
914 | |||
915 | s->match_start = cur_match; | ||
916 | return len <= s->lookahead ? len : s->lookahead; | ||
917 | } | ||
918 | #endif /* FASTEST */ | ||
848 | #endif /* ASMV */ | 919 | #endif /* ASMV */ |
849 | 920 | ||
850 | #ifdef DEBUG | 921 | #ifdef DEBUG |
@@ -930,6 +1001,7 @@ local void fill_window(s) | |||
930 | } while (--n); | 1001 | } while (--n); |
931 | 1002 | ||
932 | n = wsize; | 1003 | n = wsize; |
1004 | #ifndef FASTEST | ||
933 | p = &s->prev[n]; | 1005 | p = &s->prev[n]; |
934 | do { | 1006 | do { |
935 | m = *--p; | 1007 | m = *--p; |
@@ -938,6 +1010,7 @@ local void fill_window(s) | |||
938 | * its value will never be used. | 1010 | * its value will never be used. |
939 | */ | 1011 | */ |
940 | } while (--n); | 1012 | } while (--n); |
1013 | #endif | ||
941 | more += wsize; | 1014 | more += wsize; |
942 | } | 1015 | } |
943 | if (s->strm->avail_in == 0) return; | 1016 | if (s->strm->avail_in == 0) return; |
@@ -1105,14 +1178,15 @@ local block_state deflate_fast(s, flush) | |||
1105 | if (s->match_length >= MIN_MATCH) { | 1178 | if (s->match_length >= MIN_MATCH) { |
1106 | check_match(s, s->strstart, s->match_start, s->match_length); | 1179 | check_match(s, s->strstart, s->match_start, s->match_length); |
1107 | 1180 | ||
1108 | bflush = _tr_tally(s, s->strstart - s->match_start, | 1181 | _tr_tally_dist(s, s->strstart - s->match_start, |
1109 | s->match_length - MIN_MATCH); | 1182 | s->match_length - MIN_MATCH, bflush); |
1110 | 1183 | ||
1111 | s->lookahead -= s->match_length; | 1184 | s->lookahead -= s->match_length; |
1112 | 1185 | ||
1113 | /* Insert new strings in the hash table only if the match length | 1186 | /* Insert new strings in the hash table only if the match length |
1114 | * is not too large. This saves time but degrades compression. | 1187 | * is not too large. This saves time but degrades compression. |
1115 | */ | 1188 | */ |
1189 | #ifndef FASTEST | ||
1116 | if (s->match_length <= s->max_insert_length && | 1190 | if (s->match_length <= s->max_insert_length && |
1117 | s->lookahead >= MIN_MATCH) { | 1191 | s->lookahead >= MIN_MATCH) { |
1118 | s->match_length--; /* string at strstart already in hash table */ | 1192 | s->match_length--; /* string at strstart already in hash table */ |
@@ -1124,7 +1198,9 @@ local block_state deflate_fast(s, flush) | |||
1124 | */ | 1198 | */ |
1125 | } while (--s->match_length != 0); | 1199 | } while (--s->match_length != 0); |
1126 | s->strstart++; | 1200 | s->strstart++; |
1127 | } else { | 1201 | } else |
1202 | #endif | ||
1203 | { | ||
1128 | s->strstart += s->match_length; | 1204 | s->strstart += s->match_length; |
1129 | s->match_length = 0; | 1205 | s->match_length = 0; |
1130 | s->ins_h = s->window[s->strstart]; | 1206 | s->ins_h = s->window[s->strstart]; |
@@ -1139,7 +1215,7 @@ local block_state deflate_fast(s, flush) | |||
1139 | } else { | 1215 | } else { |
1140 | /* No match, output a literal byte */ | 1216 | /* No match, output a literal byte */ |
1141 | Tracevv((stderr,"%c", s->window[s->strstart])); | 1217 | Tracevv((stderr,"%c", s->window[s->strstart])); |
1142 | bflush = _tr_tally (s, 0, s->window[s->strstart]); | 1218 | _tr_tally_lit (s, s->window[s->strstart], bflush); |
1143 | s->lookahead--; | 1219 | s->lookahead--; |
1144 | s->strstart++; | 1220 | s->strstart++; |
1145 | } | 1221 | } |
@@ -1219,7 +1295,7 @@ local block_state deflate_slow(s, flush) | |||
1219 | check_match(s, s->strstart-1, s->prev_match, s->prev_length); | 1295 | check_match(s, s->strstart-1, s->prev_match, s->prev_length); |
1220 | 1296 | ||
1221 | bflush = _tr_tally(s, s->strstart -1 - s->prev_match, | 1297 | bflush = _tr_tally(s, s->strstart -1 - s->prev_match, |
1222 | s->prev_length - MIN_MATCH); | 1298 | s->prev_length - MIN_MATCH); |
1223 | 1299 | ||
1224 | /* Insert in hash table all strings up to the end of the match. | 1300 | /* Insert in hash table all strings up to the end of the match. |
1225 | * strstart-1 and strstart are already inserted. If there is not | 1301 | * strstart-1 and strstart are already inserted. If there is not |
@@ -1245,7 +1321,8 @@ local block_state deflate_slow(s, flush) | |||
1245 | * is longer, truncate the previous match to a single literal. | 1321 | * is longer, truncate the previous match to a single literal. |
1246 | */ | 1322 | */ |
1247 | Tracevv((stderr,"%c", s->window[s->strstart-1])); | 1323 | Tracevv((stderr,"%c", s->window[s->strstart-1])); |
1248 | if (_tr_tally (s, 0, s->window[s->strstart-1])) { | 1324 | _tr_tally_lit(s, s->window[s->strstart-1], bflush); |
1325 | if (bflush) { | ||
1249 | FLUSH_BLOCK_ONLY(s, 0); | 1326 | FLUSH_BLOCK_ONLY(s, 0); |
1250 | } | 1327 | } |
1251 | s->strstart++; | 1328 | s->strstart++; |
@@ -1263,7 +1340,7 @@ local block_state deflate_slow(s, flush) | |||
1263 | Assert (flush != Z_NO_FLUSH, "no flush?"); | 1340 | Assert (flush != Z_NO_FLUSH, "no flush?"); |
1264 | if (s->match_available) { | 1341 | if (s->match_available) { |
1265 | Tracevv((stderr,"%c", s->window[s->strstart-1])); | 1342 | Tracevv((stderr,"%c", s->window[s->strstart-1])); |
1266 | _tr_tally (s, 0, s->window[s->strstart-1]); | 1343 | _tr_tally_lit(s, s->window[s->strstart-1], bflush); |
1267 | s->match_available = 0; | 1344 | s->match_available = 0; |
1268 | } | 1345 | } |
1269 | FLUSH_BLOCK(s, flush == Z_FINISH); | 1346 | FLUSH_BLOCK(s, flush == Z_FINISH); |