-
-
Notifications
You must be signed in to change notification settings - Fork 270
/
Copy pathmatch.c
258 lines (225 loc) · 7.89 KB
/
match.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
/*
* Set match_start to the longest match starting at the given string and
* return its length. Matches shorter or equal to prev_length are discarded,
* in which case the result is equal to prev_length and match_start is garbage.
*
* IN assertions: cur_match is the head of the hash chain for the current
* string (strstart) and its distance is <= MAX_DIST, and prev_length >=1
* OUT assertion: the match length is not greater than s->lookahead
*/
#include <stdint.h>
#include "deflate.h"
#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
# define longest_match std2_longest_match
#else
# define longest_match std1_longest_match
#endif
/*
* Standard longest_match
*
*/
local unsigned std1_longest_match(deflate_state *z_const s, IPos cur_match)
{
z_const unsigned wmask = s->w_mask;
z_const Pos *prev = s->prev;
unsigned chain_length;
IPos limit;
int len, best_len, nice_match;
unsigned char *scan, *match, *strend, scan_end, scan_end1;
/*
* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple
* of 16. It is easy to get rid of this optimization if necessary.
*/
Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
/*
* Do not waste too much time if we already have a good match
*/
best_len = s->prev_length;
chain_length = s->max_chain_length;
if (best_len >= s->good_match)
chain_length >>= 2;
/*
* Do not looks for matches beyond the end of the input. This is
* necessary to make deflate deterministic
*/
nice_match = (uInt)s->nice_match > s->lookahead ? s->lookahead : s->nice_match;
/*
* Stop when cur_match becomes <= limit. To simplify the code,
* we prevent matches with the string of window index 0
*/
limit = s->strstart > MAX_DIST(s) ? s->strstart - MAX_DIST(s) : 0;
scan = s->window + s->strstart;
strend = s->window + s->strstart + MAX_MATCH;
scan_end1 = scan[best_len-1];
scan_end = scan[best_len];
Assert((unsigned long)s->strstart <= s->window_size - MIN_LOOKAHEAD,
"need lookahead");
do {
Assert(cur_match < s->strstart, "no future");
match = s->window + cur_match;
/*
* Skip to next match if the match length cannot increase
* or if the match length is less than 2. Note that the checks
* below for insufficient lookahead only occur occasionally
* for performance reasons. Therefore uninitialized memory
* will be accessed and conditional jumps will be made that
* depend on those values. However the length of the match
* is limited to the lookahead, so the output of deflate is not
* affected by the uninitialized values.
*/
if (match[best_len] != scan_end ||
match[best_len-1] != scan_end1 ||
*match != *scan ||
*++match != scan[1])
continue;
/*
* The check at best_len-1 can be removed because it will
* be made again later. (This heuristic is not always a win.)
* It is not necessary to compare scan[2] and match[2] since
* they are always equal when the other bytes match, given
* that the hash keys are equal and that HASH_BITS >= 8.
*/
scan += 2;
match++;
Assert(*scan == *match, "match[2]?");
/*
* We check for insufficient lookahead only every 8th
* comparision; the 256th check will be made at strstart + 258.
*/
do {
} while (*++scan == *++match && *++scan == *++match &&
*++scan == *++match && *++scan == *++match &&
*++scan == *++match && *++scan == *++match &&
*++scan == *++match && *++scan == *++match &&
scan < strend);
Assert(scan <= s->window+(unsigned int)(s->window_size-1),
"wild scan");
len = MAX_MATCH - (int)(strend - scan);
scan = strend - MAX_MATCH;
if (len > best_len) {
s->match_start = cur_match;
best_len = len;
if (len >= nice_match)
break;
scan_end1 = scan[best_len-1];
scan_end = scan[best_len];
} else {
/*
* The probability of finding a match later if we here
* is pretty low, so for performance it's best to
* outright stop here for the lower compression levels
*/
if (s->level < 6)
break;
}
} while ((cur_match = prev[cur_match & wmask]) > limit && --chain_length);
if ((unsigned int)best_len <= s->lookahead)
return best_len;
return s->lookahead;
}
/*
* UNALIGNED_OK longest_match
*
*/
local unsigned std2_longest_match(deflate_state *z_const s, IPos cur_match)
{
z_const unsigned wmask = s->w_mask;
z_const Pos *prev = s->prev;
unsigned short scan_start, scan_end;
unsigned chain_length;
IPos limit;
int len, best_len, nice_match;
unsigned char *scan, *strend;
/*
* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple
* of 16. It is easy to get rid of this optimization if necessary.
*/
Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
/*
* Do not waste too much time if we already have a good match
*/
best_len = s->prev_length;
chain_length = s->max_chain_length;
if (best_len >= s->good_match)
chain_length >>= 2;
/*
* Do not looks for matches beyond the end of the input. This is
* necessary to make deflate deterministic
*/
nice_match = (uInt)s->nice_match > s->lookahead ? s->lookahead : s->nice_match;
/*
* Stop when cur_match becomes <= limit. To simplify the code,
* we prevent matches with the string of window index 0
*/
limit = s->strstart > MAX_DIST(s) ? s->strstart - MAX_DIST(s) : 0;
scan = s->window + s->strstart;
strend = s->window + s->strstart + MAX_MATCH - 1;
scan_start = *(unsigned short *)scan;
scan_end = *(unsigned short *)(scan + best_len-1);
Assert((unsigned long)s->strstart <= s->window_size - MIN_LOOKAHEAD,
"need lookahead");
do {
unsigned char *match;
Assert(cur_match < s->strstart, "no future");
match = s->window + cur_match;
/*
* Skip to next match if the match length cannot increase
* or if the match length is less than 2. Note that the checks
* below for insufficient lookahead only occur occasionally
* for performance reasons. Therefore uninitialized memory
* will be accessed and conditional jumps will be made that
* depend on those values. However the length of the match
* is limited to the lookahead, so the output of deflate is not
* affected by the uninitialized values.
*/
if (likely((*(unsigned short *)(match + best_len - 1) != scan_end)))
continue;
if (*(unsigned short *)match != scan_start)
continue;
/* It is not necessary to compare scan[2] and match[2] since
* they are always equal when the other bytes match, given that
* the hash keys are equal and that HASH_BITS >= 8. Compare 2
* bytes at a time at strstart+3, +5, ... up to strstart+257.
* We check for insufficient lookahead only every 4th
* comparison; the 128th check will be made at strstart+257.
* If MAX_MATCH-2 is not a multiple of 8, it is necessary to
* put more guard bytes at the end of the window, or to check
* more often for insufficient lookahead.
*/
Assert(scan[2] == match[2], "scan[2]?");
scan++;
match++;
do {
} while (*(unsigned short *)(scan += 2)== *(unsigned short *)(match += 2)&&
*(unsigned short *)(scan += 2)== *(unsigned short *)(match += 2)&&
*(unsigned short *)(scan += 2)== *(unsigned short *)(match += 2)&&
*(unsigned short *)(scan += 2)== *(unsigned short *)(match += 2)&&
scan < strend);
/*
* Here, scan <= window + strstart + 257
*/
Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
if (*scan == *match)
scan++;
len = (MAX_MATCH -1) - (int)(strend-scan);
scan = strend - (MAX_MATCH-1);
if (len > best_len) {
s->match_start = cur_match;
best_len = len;
if (len >= nice_match)
break;
scan_end = *(unsigned short *)(scan + best_len - 1);
} else {
/*
* The probability of finding a match later if we here
* is pretty low, so for performance it's best to
* outright stop here for the lower compression levels
*/
if (s->level < 6)
break;
}
} while (--chain_length && (cur_match = prev[cur_match & wmask]) > limit);
if ((unsigned)best_len <= s->lookahead)
return best_len;
return s->lookahead;
}