Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
26 | pmbaty | 1 | /* ucl_swd.c -- sliding window dictionary |
2 | |||
3 | This file is part of the UCL data compression library. |
||
4 | |||
5 | Copyright (C) 1996-2004 Markus Franz Xaver Johannes Oberhumer |
||
6 | All Rights Reserved. |
||
7 | |||
8 | The UCL library is free software; you can redistribute it and/or |
||
9 | modify it under the terms of the GNU General Public License as |
||
10 | published by the Free Software Foundation; either version 2 of |
||
11 | the License, or (at your option) any later version. |
||
12 | |||
13 | The UCL library is distributed in the hope that it will be useful, |
||
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
16 | GNU General Public License for more details. |
||
17 | |||
18 | You should have received a copy of the GNU General Public License |
||
19 | along with the UCL library; see the file COPYING. |
||
20 | If not, write to the Free Software Foundation, Inc., |
||
21 | 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||
22 | |||
23 | Markus F.X.J. Oberhumer |
||
24 | <markus@oberhumer.com> |
||
25 | http://www.oberhumer.com/opensource/ucl/ |
||
26 | */ |
||
27 | |||
28 | |||
29 | #if (UCL_UINT_MAX < UCL_0xffffffffL) |
||
30 | # error "UCL_UINT_MAX" |
||
31 | #endif |
||
32 | |||
33 | |||
34 | /*********************************************************************** |
||
35 | // |
||
36 | ************************************************************************/ |
||
37 | |||
38 | /* unsigned type for dictionary access - don't waste memory here */ |
||
39 | #if (0UL + SWD_N + SWD_F + SWD_F < 0UL + USHRT_MAX) |
||
40 | typedef unsigned short swd_uint; |
||
41 | # define SWD_UINT_MAX USHRT_MAX |
||
42 | #else |
||
43 | typedef ucl_uint swd_uint; |
||
44 | # define SWD_UINT_MAX UCL_UINT_MAX |
||
45 | #endif |
||
46 | #define swd_uintp swd_uint __UCL_MMODEL * |
||
47 | #define SWD_UINT(x) ((swd_uint)(x)) |
||
48 | |||
49 | |||
50 | #ifndef SWD_MAX_CHAIN |
||
51 | # define SWD_MAX_CHAIN 2048 |
||
52 | #endif |
||
53 | #define SWD_HSIZE (SWD_HMASK + 1) |
||
54 | |||
55 | #if !defined(HEAD3) |
||
56 | #if 1 |
||
57 | # define HEAD3(b,p) \ |
||
58 | (((0x9f5f*(((((ucl_uint32)b[p]<<5)^b[p+1])<<5)^b[p+2]))>>5) & SWD_HMASK) |
||
59 | #else |
||
60 | # define HEAD3(b,p) \ |
||
61 | (((0x9f5f*(((((ucl_uint32)b[p+2]<<5)^b[p+1])<<5)^b[p]))>>5) & SWD_HMASK) |
||
62 | #endif |
||
63 | #endif |
||
64 | |||
65 | #if !defined(HEAD2) |
||
66 | #if (SWD_THRESHOLD == 1) |
||
67 | # if 1 && defined(UA_GET2) |
||
68 | # define HEAD2(b,p) UA_GET2(&(b[p])) |
||
69 | # else |
||
70 | # define HEAD2(b,p) (b[p] ^ ((unsigned)b[p+1]<<8)) |
||
71 | # endif |
||
72 | # define NIL2 SWD_UINT_MAX |
||
73 | #endif |
||
74 | #endif |
||
75 | |||
76 | |||
77 | #if defined(__UCL_CHECKER) |
||
78 | /* malloc arrays of the exact size to detect any overrun */ |
||
79 | # ifndef SWD_USE_MALLOC |
||
80 | # define SWD_USE_MALLOC |
||
81 | # endif |
||
82 | #endif |
||
83 | |||
84 | |||
85 | typedef struct |
||
86 | { |
||
87 | /* public - "built-in" */ |
||
88 | ucl_uint n; |
||
89 | ucl_uint f; |
||
90 | ucl_uint threshold; |
||
91 | ucl_uint hmask; |
||
92 | |||
93 | /* public - configuration */ |
||
94 | ucl_uint max_chain; |
||
95 | ucl_uint nice_length; |
||
96 | ucl_bool use_best_off; |
||
97 | ucl_uint lazy_insert; |
||
98 | |||
99 | /* public - output */ |
||
100 | ucl_uint m_len; |
||
101 | ucl_uint m_off; |
||
102 | ucl_uint look; |
||
103 | int b_char; |
||
104 | #if defined(SWD_BEST_OFF) |
||
105 | ucl_uint best_off[ SWD_BEST_OFF ]; |
||
106 | #endif |
||
107 | |||
108 | /* semi public */ |
||
109 | UCL_COMPRESS_T *c; |
||
110 | ucl_uint m_pos; |
||
111 | #if defined(SWD_BEST_OFF) |
||
112 | ucl_uint best_pos[ SWD_BEST_OFF ]; |
||
113 | #endif |
||
114 | |||
115 | /* private */ |
||
116 | const ucl_bytep dict; |
||
117 | const ucl_bytep dict_end; |
||
118 | ucl_uint dict_len; |
||
119 | |||
120 | /* private */ |
||
121 | ucl_uint ip; /* input pointer (lookahead) */ |
||
122 | ucl_uint bp; /* buffer pointer */ |
||
123 | ucl_uint rp; /* remove pointer */ |
||
124 | ucl_uint b_size; |
||
125 | |||
126 | ucl_bytep b_wrap; |
||
127 | |||
128 | ucl_uint node_count; |
||
129 | ucl_uint first_rp; |
||
130 | |||
131 | #if defined(SWD_USE_MALLOC) |
||
132 | ucl_bytep b; |
||
133 | swd_uintp head3; |
||
134 | swd_uintp succ3; |
||
135 | swd_uintp best3; |
||
136 | swd_uintp llen3; |
||
137 | #ifdef HEAD2 |
||
138 | swd_uintp head2; |
||
139 | #ifdef HEAD2_VAR |
||
140 | int use_head2; |
||
141 | #endif |
||
142 | #endif |
||
143 | #else |
||
144 | unsigned char b [ SWD_N + SWD_F + SWD_F ]; |
||
145 | swd_uint head3 [ SWD_HSIZE ]; |
||
146 | swd_uint succ3 [ SWD_N + SWD_F ]; |
||
147 | swd_uint best3 [ SWD_N + SWD_F ]; |
||
148 | swd_uint llen3 [ SWD_HSIZE ]; |
||
149 | #ifdef HEAD2 |
||
150 | swd_uint head2 [ UCL_UINT32_C(65536) ]; |
||
151 | #endif |
||
152 | #endif |
||
153 | } |
||
154 | ucl_swd_t; |
||
155 | |||
156 | |||
157 | /* Access macro for head3. |
||
158 | * head3[key] may be uninitialized if the list is emtpy, |
||
159 | * but then its value will never be used. |
||
160 | */ |
||
161 | #if defined(__UCL_CHECKER) |
||
162 | # define s_get_head3(s,key) \ |
||
163 | ((s->llen3[key] == 0) ? SWD_UINT_MAX : s->head3[key]) |
||
164 | #else |
||
165 | # define s_get_head3(s,key) s->head3[key] |
||
166 | #endif |
||
167 | |||
168 | |||
169 | /*********************************************************************** |
||
170 | // |
||
171 | ************************************************************************/ |
||
172 | |||
173 | static |
||
174 | void swd_initdict(ucl_swd_t *s, const ucl_bytep dict, ucl_uint dict_len) |
||
175 | { |
||
176 | s->dict = s->dict_end = NULL; |
||
177 | s->dict_len = 0; |
||
178 | |||
179 | if (!dict || dict_len <= 0) |
||
180 | return; |
||
181 | if (dict_len > s->n) |
||
182 | { |
||
183 | dict += dict_len - s->n; |
||
184 | dict_len = s->n; |
||
185 | } |
||
186 | |||
187 | s->dict = dict; |
||
188 | s->dict_len = dict_len; |
||
189 | s->dict_end = dict + dict_len; |
||
190 | ucl_memcpy(s->b,dict,dict_len); |
||
191 | s->ip = dict_len; |
||
192 | } |
||
193 | |||
194 | |||
195 | static |
||
196 | void swd_insertdict(ucl_swd_t *s, ucl_uint node, ucl_uint len) |
||
197 | { |
||
198 | ucl_uint key; |
||
199 | |||
200 | s->node_count = s->n - len; |
||
201 | s->first_rp = node; |
||
202 | |||
203 | while (len-- > 0) |
||
204 | { |
||
205 | key = HEAD3(s->b,node); |
||
206 | s->succ3[node] = s_get_head3(s,key); |
||
207 | s->head3[key] = SWD_UINT(node); |
||
208 | s->best3[node] = SWD_UINT(s->f + 1); |
||
209 | s->llen3[key]++; |
||
210 | assert(s->llen3[key] <= s->n); |
||
211 | |||
212 | #ifdef HEAD2 |
||
213 | IF_HEAD2(s) { |
||
214 | key = HEAD2(s->b,node); |
||
215 | s->head2[key] = SWD_UINT(node); |
||
216 | } |
||
217 | #endif |
||
218 | |||
219 | node++; |
||
220 | } |
||
221 | } |
||
222 | |||
223 | |||
224 | /*********************************************************************** |
||
225 | // |
||
226 | ************************************************************************/ |
||
227 | |||
228 | static |
||
229 | int swd_init(ucl_swd_t *s, const ucl_bytep dict, ucl_uint dict_len) |
||
230 | { |
||
231 | #if defined(SWD_USE_MALLOC) |
||
232 | s->b = NULL; |
||
233 | s->head3 = NULL; |
||
234 | s->succ3 = NULL; |
||
235 | s->best3 = NULL; |
||
236 | s->llen3 = NULL; |
||
237 | #ifdef HEAD2 |
||
238 | s->head2 = NULL; |
||
239 | #endif |
||
240 | #endif |
||
241 | |||
242 | if (s->n == 0) |
||
243 | s->n = SWD_N; |
||
244 | if (s->f == 0) |
||
245 | s->f = SWD_F; |
||
246 | s->threshold = SWD_THRESHOLD; |
||
247 | if (s->n > SWD_N || s->f > SWD_F) |
||
248 | return UCL_E_INVALID_ARGUMENT; |
||
249 | |||
250 | #if defined(SWD_USE_MALLOC) |
||
251 | s->b = (ucl_bytep) ucl_malloc(s->n + s->f + s->f); |
||
252 | s->head3 = (swd_uintp) ucl_alloc(SWD_HSIZE, sizeof(*s->head3)); |
||
253 | s->succ3 = (swd_uintp) ucl_alloc(s->n + s->f, sizeof(*s->succ3)); |
||
254 | s->best3 = (swd_uintp) ucl_alloc(s->n + s->f, sizeof(*s->best3)); |
||
255 | s->llen3 = (swd_uintp) ucl_alloc(SWD_HSIZE, sizeof(*s->llen3)); |
||
256 | if (!s->b || !s->head3 || !s->succ3 || !s->best3 || !s->llen3) |
||
257 | return UCL_E_OUT_OF_MEMORY; |
||
258 | #ifdef HEAD2 |
||
259 | IF_HEAD2(s) { |
||
260 | s->head2 = (swd_uintp) ucl_alloc(UCL_UINT32_C(65536), sizeof(*s->head2)); |
||
261 | if (!s->head2) |
||
262 | return UCL_E_OUT_OF_MEMORY; |
||
263 | } |
||
264 | #endif |
||
265 | #endif |
||
266 | |||
267 | /* defaults */ |
||
268 | s->max_chain = SWD_MAX_CHAIN; |
||
269 | s->nice_length = s->f; |
||
270 | s->use_best_off = 0; |
||
271 | s->lazy_insert = 0; |
||
272 | |||
273 | s->b_size = s->n + s->f; |
||
274 | if (s->b_size + s->f >= SWD_UINT_MAX) |
||
275 | return UCL_E_ERROR; |
||
276 | s->b_wrap = s->b + s->b_size; |
||
277 | s->node_count = s->n; |
||
278 | |||
279 | ucl_memset(s->llen3, 0, (ucl_uint)sizeof(s->llen3[0]) * SWD_HSIZE); |
||
280 | #ifdef HEAD2 |
||
281 | IF_HEAD2(s) { |
||
282 | #if 1 |
||
283 | ucl_memset(s->head2, 0xff, (ucl_uint)sizeof(s->head2[0]) * UCL_UINT32_C(65536)); |
||
284 | assert(s->head2[0] == NIL2); |
||
285 | #else |
||
286 | ucl_uint32 i; |
||
287 | for (i = 0; i < UCL_UINT32_C(65536); i++) |
||
288 | s->head2[i] = NIL2; |
||
289 | #endif |
||
290 | } |
||
291 | #endif |
||
292 | |||
293 | s->ip = 0; |
||
294 | swd_initdict(s,dict,dict_len); |
||
295 | s->bp = s->ip; |
||
296 | s->first_rp = s->ip; |
||
297 | |||
298 | assert(s->ip + s->f <= s->b_size); |
||
299 | #if 1 |
||
300 | s->look = (ucl_uint) (s->c->in_end - s->c->ip); |
||
301 | if (s->look > 0) |
||
302 | { |
||
303 | if (s->look > s->f) |
||
304 | s->look = s->f; |
||
305 | ucl_memcpy(&s->b[s->ip],s->c->ip,s->look); |
||
306 | s->c->ip += s->look; |
||
307 | s->ip += s->look; |
||
308 | } |
||
309 | #else |
||
310 | s->look = 0; |
||
311 | while (s->look < s->f) |
||
312 | { |
||
313 | int c; |
||
314 | if ((c = getbyte(*(s->c))) < 0) |
||
315 | break; |
||
316 | s->b[s->ip] = UCL_BYTE(c); |
||
317 | s->ip++; |
||
318 | s->look++; |
||
319 | } |
||
320 | #endif |
||
321 | if (s->ip == s->b_size) |
||
322 | s->ip = 0; |
||
323 | |||
324 | if (s->look >= 2 && s->dict_len > 0) |
||
325 | swd_insertdict(s,0,s->dict_len); |
||
326 | |||
327 | s->rp = s->first_rp; |
||
328 | if (s->rp >= s->node_count) |
||
329 | s->rp -= s->node_count; |
||
330 | else |
||
331 | s->rp += s->b_size - s->node_count; |
||
332 | |||
333 | #if defined(__UCL_CHECKER) |
||
334 | /* initialize memory for the first few HEAD3 (if s->ip is not far |
||
335 | * enough ahead to do this job for us). The value doesn't matter. */ |
||
336 | if (s->look < 3) |
||
337 | ucl_memset(&s->b[s->bp+s->look],0,3); |
||
338 | #endif |
||
339 | |||
340 | return UCL_E_OK; |
||
341 | } |
||
342 | |||
343 | |||
344 | static |
||
345 | void swd_exit(ucl_swd_t *s) |
||
346 | { |
||
347 | #if defined(SWD_USE_MALLOC) |
||
348 | /* free in reverse order of allocations */ |
||
349 | #ifdef HEAD2 |
||
350 | ucl_free(s->head2); s->head2 = NULL; |
||
351 | #endif |
||
352 | ucl_free(s->llen3); s->llen3 = NULL; |
||
353 | ucl_free(s->best3); s->best3 = NULL; |
||
354 | ucl_free(s->succ3); s->succ3 = NULL; |
||
355 | ucl_free(s->head3); s->head3 = NULL; |
||
356 | ucl_free(s->b); s->b = NULL; |
||
357 | #else |
||
358 | ACC_UNUSED(s); |
||
359 | #endif |
||
360 | } |
||
361 | |||
362 | |||
363 | #define swd_pos2off(s,pos) \ |
||
364 | (s->bp > (pos) ? s->bp - (pos) : s->b_size - ((pos) - s->bp)) |
||
365 | |||
366 | |||
367 | /*********************************************************************** |
||
368 | // |
||
369 | ************************************************************************/ |
||
370 | |||
371 | static |
||
372 | void swd_getbyte(ucl_swd_t *s) |
||
373 | { |
||
374 | int c; |
||
375 | |||
376 | if ((c = getbyte(*(s->c))) < 0) |
||
377 | { |
||
378 | if (s->look > 0) |
||
379 | --s->look; |
||
380 | #if defined(__UCL_CHECKER) |
||
381 | /* initialize memory - value doesn't matter */ |
||
382 | s->b[s->ip] = 0; |
||
383 | if (s->ip < s->f) |
||
384 | s->b_wrap[s->ip] = 0; |
||
385 | #endif |
||
386 | } |
||
387 | else |
||
388 | { |
||
389 | s->b[s->ip] = UCL_BYTE(c); |
||
390 | if (s->ip < s->f) |
||
391 | s->b_wrap[s->ip] = UCL_BYTE(c); |
||
392 | } |
||
393 | if (++s->ip == s->b_size) |
||
394 | s->ip = 0; |
||
395 | if (++s->bp == s->b_size) |
||
396 | s->bp = 0; |
||
397 | if (++s->rp == s->b_size) |
||
398 | s->rp = 0; |
||
399 | } |
||
400 | |||
401 | |||
402 | /*********************************************************************** |
||
403 | // remove node from lists |
||
404 | ************************************************************************/ |
||
405 | |||
406 | static |
||
407 | void swd_remove_node(ucl_swd_t *s, ucl_uint node) |
||
408 | { |
||
409 | if (s->node_count == 0) |
||
410 | { |
||
411 | ucl_uint key; |
||
412 | |||
413 | #ifdef UCL_DEBUG |
||
414 | if (s->first_rp != UCL_UINT_MAX) |
||
415 | { |
||
416 | if (node != s->first_rp) |
||
417 | printf("Remove %5u: %5u %5u %5u %5u %6u %6u\n", |
||
418 | node, s->rp, s->ip, s->bp, s->first_rp, |
||
419 | s->ip - node, s->ip - s->bp); |
||
420 | assert(node == s->first_rp); |
||
421 | s->first_rp = UCL_UINT_MAX; |
||
422 | } |
||
423 | #endif |
||
424 | |||
425 | key = HEAD3(s->b,node); |
||
426 | assert(s->llen3[key] > 0); |
||
427 | --s->llen3[key]; |
||
428 | |||
429 | #ifdef HEAD2 |
||
430 | IF_HEAD2(s) { |
||
431 | key = HEAD2(s->b,node); |
||
432 | assert(s->head2[key] != NIL2); |
||
433 | if ((ucl_uint) s->head2[key] == node) |
||
434 | s->head2[key] = NIL2; |
||
435 | } |
||
436 | #endif |
||
437 | } |
||
438 | else |
||
439 | --s->node_count; |
||
440 | } |
||
441 | |||
442 | |||
443 | /*********************************************************************** |
||
444 | // |
||
445 | ************************************************************************/ |
||
446 | |||
447 | static |
||
448 | void swd_accept(ucl_swd_t *s, ucl_uint n) |
||
449 | { |
||
450 | assert(n <= s->look); |
||
451 | |||
452 | if (n > 0) do |
||
453 | { |
||
454 | ucl_uint key; |
||
455 | |||
456 | swd_remove_node(s,s->rp); |
||
457 | |||
458 | /* add bp into HEAD3 */ |
||
459 | key = HEAD3(s->b,s->bp); |
||
460 | s->succ3[s->bp] = s_get_head3(s,key); |
||
461 | s->head3[key] = SWD_UINT(s->bp); |
||
462 | s->best3[s->bp] = SWD_UINT(s->f + 1); |
||
463 | s->llen3[key]++; |
||
464 | assert(s->llen3[key] <= s->n); |
||
465 | |||
466 | #ifdef HEAD2 |
||
467 | IF_HEAD2(s) { |
||
468 | /* add bp into HEAD2 */ |
||
469 | key = HEAD2(s->b,s->bp); |
||
470 | s->head2[key] = SWD_UINT(s->bp); |
||
471 | } |
||
472 | #endif |
||
473 | |||
474 | swd_getbyte(s); |
||
475 | } while (--n > 0); |
||
476 | } |
||
477 | |||
478 | |||
479 | /*********************************************************************** |
||
480 | // |
||
481 | ************************************************************************/ |
||
482 | |||
483 | static |
||
484 | void swd_search(ucl_swd_t *s, ucl_uint node, ucl_uint cnt) |
||
485 | { |
||
486 | const ucl_bytep p1; |
||
487 | const ucl_bytep p2; |
||
488 | const ucl_bytep px; |
||
489 | ucl_uint m_len = s->m_len; |
||
490 | const ucl_bytep b = s->b; |
||
491 | const ucl_bytep bp = s->b + s->bp; |
||
492 | const ucl_bytep bx = s->b + s->bp + s->look; |
||
493 | unsigned char scan_end1; |
||
494 | |||
495 | assert(s->m_len > 0); |
||
496 | |||
497 | scan_end1 = bp[m_len - 1]; |
||
498 | for ( ; cnt-- > 0; node = s->succ3[node]) |
||
499 | { |
||
500 | p1 = bp; |
||
501 | p2 = b + node; |
||
502 | px = bx; |
||
503 | |||
504 | assert(m_len < s->look); |
||
505 | |||
506 | if ( |
||
507 | #if 1 |
||
508 | p2[m_len - 1] == scan_end1 && |
||
509 | p2[m_len] == p1[m_len] && |
||
510 | #endif |
||
511 | p2[0] == p1[0] && |
||
512 | p2[1] == p1[1]) |
||
513 | { |
||
514 | ucl_uint i; |
||
515 | assert(ucl_memcmp(bp,&b[node],3) == 0); |
||
516 | |||
517 | #if 0 && defined(UA_GET4) |
||
518 | p1 += 3; p2 += 3; |
||
519 | while (p1 < px && UA_GET4(p1) == UA_GET4(p2)) |
||
520 | p1 += 4, p2 += 4; |
||
521 | while (p1 < px && *p1 == *p2) |
||
522 | p1 += 1, p2 += 1; |
||
523 | #else |
||
524 | p1 += 2; p2 += 2; |
||
525 | do {} while (++p1 < px && *p1 == *++p2); |
||
526 | #endif |
||
527 | i = (ucl_uint) (p1 - bp); |
||
528 | |||
529 | #ifdef UCL_DEBUG |
||
530 | if (ucl_memcmp(bp,&b[node],i) != 0) |
||
531 | printf("%5ld %5ld %02x%02x %02x%02x\n", |
||
532 | (long)s->bp, (long) node, |
||
533 | bp[0], bp[1], b[node], b[node+1]); |
||
534 | #endif |
||
535 | assert(ucl_memcmp(bp,&b[node],i) == 0); |
||
536 | |||
537 | #if defined(SWD_BEST_OFF) |
||
538 | if (i < SWD_BEST_OFF) |
||
539 | { |
||
540 | if (s->best_pos[i] == 0) |
||
541 | s->best_pos[i] = node + 1; |
||
542 | } |
||
543 | #endif |
||
544 | if (i > m_len) |
||
545 | { |
||
546 | s->m_len = m_len = i; |
||
547 | s->m_pos = node; |
||
548 | if (m_len == s->look) |
||
549 | return; |
||
550 | if (m_len >= s->nice_length) |
||
551 | return; |
||
552 | if (m_len > (ucl_uint) s->best3[node]) |
||
553 | return; |
||
554 | scan_end1 = bp[m_len - 1]; |
||
555 | } |
||
556 | } |
||
557 | } |
||
558 | } |
||
559 | |||
560 | |||
561 | /*********************************************************************** |
||
562 | // |
||
563 | ************************************************************************/ |
||
564 | |||
565 | #ifdef HEAD2 |
||
566 | |||
567 | static |
||
568 | ucl_bool swd_search2(ucl_swd_t *s) |
||
569 | { |
||
570 | ucl_uint key; |
||
571 | |||
572 | assert(s->look >= 2); |
||
573 | assert(s->m_len > 0); |
||
574 | |||
575 | key = s->head2[ HEAD2(s->b,s->bp) ]; |
||
576 | if (key == NIL2) |
||
577 | return 0; |
||
578 | #ifdef UCL_DEBUG |
||
579 | if (ucl_memcmp(&s->b[s->bp],&s->b[key],2) != 0) |
||
580 | printf("%5ld %5ld %02x%02x %02x%02x\n", (long)s->bp, (long)key, |
||
581 | s->b[s->bp], s->b[s->bp+1], s->b[key], s->b[key+1]); |
||
582 | #endif |
||
583 | assert(ucl_memcmp(&s->b[s->bp],&s->b[key],2) == 0); |
||
584 | #if defined(SWD_BEST_OFF) |
||
585 | if (s->best_pos[2] == 0) |
||
586 | s->best_pos[2] = key + 1; |
||
587 | #endif |
||
588 | |||
589 | if (s->m_len < 2) |
||
590 | { |
||
591 | s->m_len = 2; |
||
592 | s->m_pos = key; |
||
593 | } |
||
594 | return 1; |
||
595 | } |
||
596 | |||
597 | #endif |
||
598 | |||
599 | |||
600 | /*********************************************************************** |
||
601 | // |
||
602 | ************************************************************************/ |
||
603 | |||
604 | static |
||
605 | void swd_findbest(ucl_swd_t *s) |
||
606 | { |
||
607 | ucl_uint key; |
||
608 | ucl_uint cnt, node; |
||
609 | ucl_uint len; |
||
610 | |||
611 | assert(s->m_len > 0); |
||
612 | |||
613 | /* get current head, add bp into HEAD3 */ |
||
614 | key = HEAD3(s->b,s->bp); |
||
615 | node = s->succ3[s->bp] = s_get_head3(s,key); |
||
616 | cnt = s->llen3[key]++; |
||
617 | assert(s->llen3[key] <= s->n + s->f); |
||
618 | if (cnt > s->max_chain && s->max_chain > 0) |
||
619 | cnt = s->max_chain; |
||
620 | s->head3[key] = SWD_UINT(s->bp); |
||
621 | |||
622 | s->b_char = s->b[s->bp]; |
||
623 | len = s->m_len; |
||
624 | if (s->m_len >= s->look) |
||
625 | { |
||
626 | if (s->look == 0) |
||
627 | s->b_char = -1; |
||
628 | s->m_off = 0; |
||
629 | s->best3[s->bp] = SWD_UINT(s->f + 1); |
||
630 | } |
||
631 | else |
||
632 | { |
||
633 | #if defined(HEAD2_VAR) |
||
634 | if (s->use_head2) { |
||
635 | if (swd_search2(s) && s->look >= 3) |
||
636 | swd_search(s,node,cnt); |
||
637 | } else { |
||
638 | if (s->look >= 3) |
||
639 | swd_search(s,node,cnt); |
||
640 | } |
||
641 | #elif defined(HEAD2) |
||
642 | if (swd_search2(s) && s->look >= 3) |
||
643 | swd_search(s,node,cnt); |
||
644 | #else |
||
645 | if (s->look >= 3) |
||
646 | swd_search(s,node,cnt); |
||
647 | #endif |
||
648 | if (s->m_len > len) |
||
649 | s->m_off = swd_pos2off(s,s->m_pos); |
||
650 | s->best3[s->bp] = SWD_UINT(s->m_len); |
||
651 | |||
652 | #if defined(SWD_BEST_OFF) |
||
653 | if (s->use_best_off) |
||
654 | { |
||
655 | int i; |
||
656 | for (i = 2; i < SWD_BEST_OFF; i++) |
||
657 | if (s->best_pos[i] > 0) |
||
658 | s->best_off[i] = swd_pos2off(s,s->best_pos[i]-1); |
||
659 | else |
||
660 | s->best_off[i] = 0; |
||
661 | } |
||
662 | #endif |
||
663 | } |
||
664 | |||
665 | swd_remove_node(s,s->rp); |
||
666 | |||
667 | #ifdef HEAD2 |
||
668 | /* add bp into HEAD2 */ |
||
669 | IF_HEAD2(s) { |
||
670 | key = HEAD2(s->b,s->bp); |
||
671 | s->head2[key] = SWD_UINT(s->bp); |
||
672 | } |
||
673 | #endif |
||
674 | } |
||
675 | |||
676 | |||
677 | #undef HEAD3 |
||
678 | #undef HEAD2 |
||
679 | #undef IF_HEAD2 |
||
680 | #undef s_get_head3 |
||
681 | |||
682 | |||
683 | /* |
||
684 | vi:ts=4:et |
||
685 | */ |
||
686 |