154{
155 uchar * in = (uchar *) void_input;
156 uchar * out = (uchar *) buffer;
157 int buffer_len = BUFFER_SIZE;
158
159 for (int i = 0; i < HASH_SIZE; i++) hash_keys[i] = EMPTY_KEY;
160
161 uchar * in2 = in;
162
163 while (len > 2)
164 {
165
166 int hash = ((in[0] << 16) | (in[1] << 8) | in[2]) % HASH_SIZE;
167
168 if (hash_keys[hash] != EMPTY_KEY)
169
170 {
171 int best_match = 0;
172 uchar * best_pos = NULL;
173
174 EvaluateMatch(in, len, hash, best_pos, best_match);
175
176
177 if (best_match < 3)
178 {
179 in++;
180 len--;
181 continue;
182 }
183
184
185 while (best_match < OKAY_MATCH && len > 3)
186 {
187
188 int next_hash = ((in[1] << 16) | (in[2] << 8) | in[3]) % HASH_SIZE;
189
190 if (hash_keys[next_hash] == EMPTY_KEY) break;
191
192 int next_match = 0;
193 uchar * next_pos = NULL;
194
195 EvaluateMatch(in + 1, len - 1, next_hash, next_pos, next_match);
196
197
198 if (next_match <= best_match + 1) break;
199
200
201 in++;
202 len--;
203 best_match = next_match;
204 best_pos = next_pos;
205 }
206
207 int best_offset = in - best_pos - 1;
208
209
210
211 OutputLiterals(in2, in - in2, out, buffer_len, output);
212
213 in2 = in += best_match;
214 len -= best_match;
215
216 if (best_match < 17 && best_offset < 0x1000)
217 {
218 *out = (uchar)(((best_match - 1) << 4) | (best_offset >> 8));
219 out++;
220 *out = (uchar)(best_offset & 0xFF);
221 out++;
222 buffer_len -= 2;
223 }
224 else if (best_match < 66)
225 {
226 *out = (uchar)(16 | (best_offset >> 10));
227 out++;
228 *out = (uchar)((best_offset >> 2) & 0xFF);
229 out++;
230 *out = (uchar)((best_offset << 6) | (best_match - 2));
231 out++;
232 buffer_len -= 3;
233 }
234 else
235 {
236 *out = (uchar)(16 | (best_offset >> 10));
237 out++;
238 *out = (uchar)((best_offset >> 2) & 0xFF);
239 out++;
240 *out = (uchar)(best_offset << 6);
241 out++;
242 best_match -= 66;
243 *out = (uchar)(best_match >> 8);
244 out++;
245 *out = (uchar)(best_match & 0xFF);
246 out++;
247 buffer_len -= 5;
248 }
249
250 if (buffer_len <= 0)
251 {
252 fwrite(buffer, out - buffer, 1, output);
253 buffer_len = BUFFER_SIZE;
254 out = buffer;
255 }
256 }
257
258 else
259 {
260 hash_keys[hash] = 0;
261 for (int i = 1; i < HASH_DEPTH; i++) hash_values[hash * 8 + i] = NULL;
262 hash_values[hash * 8] = in;
263 in++;
264 len--;
265 }
266 }
267
268
269 in += len;
270 OutputLiterals(in2, in - in2, out, buffer_len, output);
271
272
273 if (out != buffer) fwrite(buffer, out - buffer, 1, output);
274}