Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / busybox / archival / libarchive / lzo1x_9x.c
blob897132987c5c3e710066895be46e2bd1a00a395d
1 /* lzo1x_9x.c -- implementation of the LZO1X-999 compression algorithm
3 This file is part of the LZO real-time data compression library.
5 Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
6 Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
7 Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
8 Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
9 Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
10 Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
11 Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
12 Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
13 Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
14 Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
15 Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
16 Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
17 Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
18 All Rights Reserved.
20 The LZO library is free software; you can redistribute it and/or
21 modify it under the terms of the GNU General Public License as
22 published by the Free Software Foundation; either version 2 of
23 the License, or (at your option) any later version.
25 The LZO library is distributed in the hope that it will be useful,
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
28 GNU General Public License for more details.
30 You should have received a copy of the GNU General Public License
31 along with the LZO library; see the file COPYING.
32 If not, write to the Free Software Foundation, Inc.,
33 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
35 Markus F.X.J. Oberhumer
36 <markus@oberhumer.com>
37 http://www.oberhumer.com/opensource/lzo/
39 #include "libbb.h"
41 /* The following is probably only safe on Intel-compatible processors ... */
42 #define LZO_UNALIGNED_OK_2
43 #define LZO_UNALIGNED_OK_4
45 #include "liblzo.h"
47 #define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b))
48 #define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b))
49 #define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c))
51 /***********************************************************************
53 ************************************************************************/
54 #define SWD_N M4_MAX_OFFSET /* size of ring buffer */
55 #define SWD_F 2048 /* upper limit for match length */
57 #define SWD_BEST_OFF (LZO_MAX3(M2_MAX_LEN, M3_MAX_LEN, M4_MAX_LEN) + 1)
59 typedef struct {
60 int init;
62 unsigned look; /* bytes in lookahead buffer */
64 unsigned m_len;
65 unsigned m_off;
67 const uint8_t *bp;
68 const uint8_t *ip;
69 const uint8_t *in;
70 const uint8_t *in_end;
71 uint8_t *out;
73 unsigned r1_lit;
75 } lzo1x_999_t;
77 #define getbyte(c) ((c).ip < (c).in_end ? *((c).ip)++ : (-1))
79 /* lzo_swd.c -- sliding window dictionary */
81 /***********************************************************************
83 ************************************************************************/
84 #define SWD_UINT_MAX USHRT_MAX
86 #ifndef SWD_HSIZE
87 # define SWD_HSIZE 16384
88 #endif
89 #ifndef SWD_MAX_CHAIN
90 # define SWD_MAX_CHAIN 2048
91 #endif
93 #define HEAD3(b, p) \
94 ( ((0x9f5f * ((((b[p]<<5)^b[p+1])<<5) ^ b[p+2])) >> 5) & (SWD_HSIZE-1) )
96 #if defined(LZO_UNALIGNED_OK_2)
97 # define HEAD2(b,p) (* (uint16_t *) &(b[p]))
98 #else
99 # define HEAD2(b,p) (b[p] ^ ((unsigned)b[p+1]<<8))
100 #endif
101 #define NIL2 SWD_UINT_MAX
103 typedef struct lzo_swd {
104 /* public - "built-in" */
106 /* public - configuration */
107 unsigned max_chain;
108 int use_best_off;
110 /* public - output */
111 unsigned m_len;
112 unsigned m_off;
113 unsigned look;
114 int b_char;
115 #if defined(SWD_BEST_OFF)
116 unsigned best_off[SWD_BEST_OFF];
117 #endif
119 /* semi public */
120 lzo1x_999_t *c;
121 unsigned m_pos;
122 #if defined(SWD_BEST_OFF)
123 unsigned best_pos[SWD_BEST_OFF];
124 #endif
126 /* private */
127 unsigned ip; /* input pointer (lookahead) */
128 unsigned bp; /* buffer pointer */
129 unsigned rp; /* remove pointer */
131 unsigned node_count;
132 unsigned first_rp;
134 uint8_t b[SWD_N + SWD_F];
135 uint8_t b_wrap[SWD_F]; /* must follow b */
136 uint16_t head3[SWD_HSIZE];
137 uint16_t succ3[SWD_N + SWD_F];
138 uint16_t best3[SWD_N + SWD_F];
139 uint16_t llen3[SWD_HSIZE];
140 #ifdef HEAD2
141 uint16_t head2[65536L];
142 #endif
143 } lzo_swd_t, *lzo_swd_p;
145 #define SIZEOF_LZO_SWD_T (sizeof(lzo_swd_t))
148 /* Access macro for head3.
149 * head3[key] may be uninitialized, but then its value will never be used.
151 #define s_get_head3(s,key) s->head3[key]
154 /***********************************************************************
156 ************************************************************************/
157 #define B_SIZE (SWD_N + SWD_F)
159 static int swd_init(lzo_swd_p s)
161 /* defaults */
162 s->node_count = SWD_N;
164 memset(s->llen3, 0, sizeof(s->llen3[0]) * (unsigned)SWD_HSIZE);
165 #ifdef HEAD2
166 memset(s->head2, 0xff, sizeof(s->head2[0]) * 65536L);
167 assert(s->head2[0] == NIL2);
168 #endif
170 s->ip = 0;
171 s->bp = s->ip;
172 s->first_rp = s->ip;
174 assert(s->ip + SWD_F <= B_SIZE);
175 s->look = (unsigned) (s->c->in_end - s->c->ip);
176 if (s->look > 0) {
177 if (s->look > SWD_F)
178 s->look = SWD_F;
179 memcpy(&s->b[s->ip], s->c->ip, s->look);
180 s->c->ip += s->look;
181 s->ip += s->look;
183 if (s->ip == B_SIZE)
184 s->ip = 0;
186 s->rp = s->first_rp;
187 if (s->rp >= s->node_count)
188 s->rp -= s->node_count;
189 else
190 s->rp += B_SIZE - s->node_count;
192 return LZO_E_OK;
195 #define swd_pos2off(s,pos) \
196 (s->bp > (pos) ? s->bp - (pos) : B_SIZE - ((pos) - s->bp))
199 /***********************************************************************
201 ************************************************************************/
202 static void swd_getbyte(lzo_swd_p s)
204 int c;
206 if ((c = getbyte(*(s->c))) < 0) {
207 if (s->look > 0)
208 --s->look;
209 } else {
210 s->b[s->ip] = c;
211 if (s->ip < SWD_F)
212 s->b_wrap[s->ip] = c;
214 if (++s->ip == B_SIZE)
215 s->ip = 0;
216 if (++s->bp == B_SIZE)
217 s->bp = 0;
218 if (++s->rp == B_SIZE)
219 s->rp = 0;
223 /***********************************************************************
224 // remove node from lists
225 ************************************************************************/
226 static void swd_remove_node(lzo_swd_p s, unsigned node)
228 if (s->node_count == 0) {
229 unsigned key;
231 key = HEAD3(s->b,node);
232 assert(s->llen3[key] > 0);
233 --s->llen3[key];
235 #ifdef HEAD2
236 key = HEAD2(s->b,node);
237 assert(s->head2[key] != NIL2);
238 if ((unsigned) s->head2[key] == node)
239 s->head2[key] = NIL2;
240 #endif
241 } else
242 --s->node_count;
246 /***********************************************************************
248 ************************************************************************/
249 static void swd_accept(lzo_swd_p s, unsigned n)
251 assert(n <= s->look);
253 while (n--) {
254 unsigned key;
256 swd_remove_node(s,s->rp);
258 /* add bp into HEAD3 */
259 key = HEAD3(s->b, s->bp);
260 s->succ3[s->bp] = s_get_head3(s, key);
261 s->head3[key] = s->bp;
262 s->best3[s->bp] = SWD_F + 1;
263 s->llen3[key]++;
264 assert(s->llen3[key] <= SWD_N);
266 #ifdef HEAD2
267 /* add bp into HEAD2 */
268 key = HEAD2(s->b, s->bp);
269 s->head2[key] = s->bp;
270 #endif
272 swd_getbyte(s);
277 /***********************************************************************
279 ************************************************************************/
280 static void swd_search(lzo_swd_p s, unsigned node, unsigned cnt)
282 const uint8_t *p1;
283 const uint8_t *p2;
284 const uint8_t *px;
285 unsigned m_len = s->m_len;
286 const uint8_t *b = s->b;
287 const uint8_t *bp = s->b + s->bp;
288 const uint8_t *bx = s->b + s->bp + s->look;
289 unsigned char scan_end1;
291 assert(s->m_len > 0);
293 scan_end1 = bp[m_len - 1];
294 for ( ; cnt-- > 0; node = s->succ3[node]) {
295 p1 = bp;
296 p2 = b + node;
297 px = bx;
299 assert(m_len < s->look);
301 if (p2[m_len - 1] == scan_end1
302 && p2[m_len] == p1[m_len]
303 && p2[0] == p1[0]
304 && p2[1] == p1[1]
306 unsigned i;
307 assert(lzo_memcmp(bp, &b[node], 3) == 0);
309 p1 += 2; p2 += 2;
310 do {} while (++p1 < px && *p1 == *++p2);
311 i = p1-bp;
313 assert(lzo_memcmp(bp, &b[node], i) == 0);
315 #if defined(SWD_BEST_OFF)
316 if (i < SWD_BEST_OFF) {
317 if (s->best_pos[i] == 0)
318 s->best_pos[i] = node + 1;
320 #endif
321 if (i > m_len) {
322 s->m_len = m_len = i;
323 s->m_pos = node;
324 if (m_len == s->look)
325 return;
326 if (m_len >= SWD_F)
327 return;
328 if (m_len > (unsigned) s->best3[node])
329 return;
330 scan_end1 = bp[m_len - 1];
337 /***********************************************************************
339 ************************************************************************/
340 #ifdef HEAD2
342 static int swd_search2(lzo_swd_p s)
344 unsigned key;
346 assert(s->look >= 2);
347 assert(s->m_len > 0);
349 key = s->head2[HEAD2(s->b, s->bp)];
350 if (key == NIL2)
351 return 0;
352 assert(lzo_memcmp(&s->b[s->bp], &s->b[key], 2) == 0);
353 #if defined(SWD_BEST_OFF)
354 if (s->best_pos[2] == 0)
355 s->best_pos[2] = key + 1;
356 #endif
358 if (s->m_len < 2) {
359 s->m_len = 2;
360 s->m_pos = key;
362 return 1;
365 #endif
368 /***********************************************************************
370 ************************************************************************/
371 static void swd_findbest(lzo_swd_p s)
373 unsigned key;
374 unsigned cnt, node;
375 unsigned len;
377 assert(s->m_len > 0);
379 /* get current head, add bp into HEAD3 */
380 key = HEAD3(s->b,s->bp);
381 node = s->succ3[s->bp] = s_get_head3(s, key);
382 cnt = s->llen3[key]++;
383 assert(s->llen3[key] <= SWD_N + SWD_F);
384 if (cnt > s->max_chain)
385 cnt = s->max_chain;
386 s->head3[key] = s->bp;
388 s->b_char = s->b[s->bp];
389 len = s->m_len;
390 if (s->m_len >= s->look) {
391 if (s->look == 0)
392 s->b_char = -1;
393 s->m_off = 0;
394 s->best3[s->bp] = SWD_F + 1;
395 } else {
396 #ifdef HEAD2
397 if (swd_search2(s))
398 #endif
399 if (s->look >= 3)
400 swd_search(s, node, cnt);
401 if (s->m_len > len)
402 s->m_off = swd_pos2off(s,s->m_pos);
403 s->best3[s->bp] = s->m_len;
405 #if defined(SWD_BEST_OFF)
406 if (s->use_best_off) {
407 int i;
408 for (i = 2; i < SWD_BEST_OFF; i++) {
409 if (s->best_pos[i] > 0)
410 s->best_off[i] = swd_pos2off(s, s->best_pos[i]-1);
411 else
412 s->best_off[i] = 0;
415 #endif
418 swd_remove_node(s,s->rp);
420 #ifdef HEAD2
421 /* add bp into HEAD2 */
422 key = HEAD2(s->b, s->bp);
423 s->head2[key] = s->bp;
424 #endif
427 #undef HEAD3
428 #undef HEAD2
429 #undef s_get_head3
432 /***********************************************************************
434 ************************************************************************/
435 static int init_match(lzo1x_999_t *c, lzo_swd_p s, uint32_t use_best_off)
437 int r;
439 assert(!c->init);
440 c->init = 1;
442 s->c = c;
444 r = swd_init(s);
445 if (r != 0)
446 return r;
448 s->use_best_off = use_best_off;
449 return r;
453 /***********************************************************************
455 ************************************************************************/
456 static int find_match(lzo1x_999_t *c, lzo_swd_p s,
457 unsigned this_len, unsigned skip)
459 assert(c->init);
461 if (skip > 0) {
462 assert(this_len >= skip);
463 swd_accept(s, this_len - skip);
464 } else {
465 assert(this_len <= 1);
468 s->m_len = 1;
469 s->m_len = 1;
470 #ifdef SWD_BEST_OFF
471 if (s->use_best_off)
472 memset(s->best_pos, 0, sizeof(s->best_pos));
473 #endif
474 swd_findbest(s);
475 c->m_len = s->m_len;
476 c->m_off = s->m_off;
478 swd_getbyte(s);
480 if (s->b_char < 0) {
481 c->look = 0;
482 c->m_len = 0;
483 } else {
484 c->look = s->look + 1;
486 c->bp = c->ip - c->look;
488 return LZO_E_OK;
491 /* this is a public functions, but there is no prototype in a header file */
492 static int lzo1x_999_compress_internal(const uint8_t *in , unsigned in_len,
493 uint8_t *out, unsigned *out_len,
494 void *wrkmem,
495 unsigned good_length,
496 unsigned max_lazy,
497 unsigned max_chain,
498 uint32_t use_best_off);
501 /***********************************************************************
503 ************************************************************************/
504 static uint8_t *code_match(lzo1x_999_t *c,
505 uint8_t *op, unsigned m_len, unsigned m_off)
507 assert(op > c->out);
508 if (m_len == 2) {
509 assert(m_off <= M1_MAX_OFFSET);
510 assert(c->r1_lit > 0);
511 assert(c->r1_lit < 4);
512 m_off -= 1;
513 *op++ = M1_MARKER | ((m_off & 3) << 2);
514 *op++ = m_off >> 2;
515 } else if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) {
516 assert(m_len >= 3);
517 m_off -= 1;
518 *op++ = ((m_len - 1) << 5) | ((m_off & 7) << 2);
519 *op++ = m_off >> 3;
520 assert(op[-2] >= M2_MARKER);
521 } else if (m_len == M2_MIN_LEN && m_off <= MX_MAX_OFFSET && c->r1_lit >= 4) {
522 assert(m_len == 3);
523 assert(m_off > M2_MAX_OFFSET);
524 m_off -= 1 + M2_MAX_OFFSET;
525 *op++ = M1_MARKER | ((m_off & 3) << 2);
526 *op++ = m_off >> 2;
527 } else if (m_off <= M3_MAX_OFFSET) {
528 assert(m_len >= 3);
529 m_off -= 1;
530 if (m_len <= M3_MAX_LEN)
531 *op++ = M3_MARKER | (m_len - 2);
532 else {
533 m_len -= M3_MAX_LEN;
534 *op++ = M3_MARKER | 0;
535 while (m_len > 255) {
536 m_len -= 255;
537 *op++ = 0;
539 assert(m_len > 0);
540 *op++ = m_len;
542 *op++ = m_off << 2;
543 *op++ = m_off >> 6;
544 } else {
545 unsigned k;
547 assert(m_len >= 3);
548 assert(m_off > 0x4000);
549 assert(m_off <= 0xbfff);
550 m_off -= 0x4000;
551 k = (m_off & 0x4000) >> 11;
552 if (m_len <= M4_MAX_LEN)
553 *op++ = M4_MARKER | k | (m_len - 2);
554 else {
555 m_len -= M4_MAX_LEN;
556 *op++ = M4_MARKER | k | 0;
557 while (m_len > 255) {
558 m_len -= 255;
559 *op++ = 0;
561 assert(m_len > 0);
562 *op++ = m_len;
564 *op++ = m_off << 2;
565 *op++ = m_off >> 6;
568 return op;
572 static uint8_t *STORE_RUN(lzo1x_999_t *c, uint8_t *op,
573 const uint8_t *ii, unsigned t)
575 if (op == c->out && t <= 238) {
576 *op++ = 17 + t;
577 } else if (t <= 3) {
578 op[-2] |= t;
579 } else if (t <= 18) {
580 *op++ = t - 3;
581 } else {
582 unsigned tt = t - 18;
584 *op++ = 0;
585 while (tt > 255) {
586 tt -= 255;
587 *op++ = 0;
589 assert(tt > 0);
590 *op++ = tt;
592 do *op++ = *ii++; while (--t > 0);
594 return op;
598 static uint8_t *code_run(lzo1x_999_t *c, uint8_t *op, const uint8_t *ii,
599 unsigned lit)
601 if (lit > 0) {
602 assert(m_len >= 2);
603 op = STORE_RUN(c, op, ii, lit);
604 } else {
605 assert(m_len >= 3);
607 c->r1_lit = lit;
609 return op;
613 /***********************************************************************
615 ************************************************************************/
616 static int len_of_coded_match(unsigned m_len, unsigned m_off, unsigned lit)
618 int n = 4;
620 if (m_len < 2)
621 return -1;
622 if (m_len == 2)
623 return (m_off <= M1_MAX_OFFSET && lit > 0 && lit < 4) ? 2 : -1;
624 if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
625 return 2;
626 if (m_len == M2_MIN_LEN && m_off <= MX_MAX_OFFSET && lit >= 4)
627 return 2;
628 if (m_off <= M3_MAX_OFFSET) {
629 if (m_len <= M3_MAX_LEN)
630 return 3;
631 m_len -= M3_MAX_LEN;
632 } else if (m_off <= M4_MAX_OFFSET) {
633 if (m_len <= M4_MAX_LEN)
634 return 3;
635 m_len -= M4_MAX_LEN;
636 } else
637 return -1;
638 while (m_len > 255) {
639 m_len -= 255;
640 n++;
642 return n;
646 static int min_gain(unsigned ahead, unsigned lit1,
647 unsigned lit2, int l1, int l2, int l3)
649 int lazy_match_min_gain = 0;
651 assert (ahead >= 1);
652 lazy_match_min_gain += ahead;
654 if (lit1 <= 3)
655 lazy_match_min_gain += (lit2 <= 3) ? 0 : 2;
656 else if (lit1 <= 18)
657 lazy_match_min_gain += (lit2 <= 18) ? 0 : 1;
659 lazy_match_min_gain += (l2 - l1) * 2;
660 if (l3 > 0)
661 lazy_match_min_gain -= (ahead - l3) * 2;
663 if (lazy_match_min_gain < 0)
664 lazy_match_min_gain = 0;
666 return lazy_match_min_gain;
670 /***********************************************************************
672 ************************************************************************/
673 #if defined(SWD_BEST_OFF)
675 static void better_match(const lzo_swd_p swd,
676 unsigned *m_len, unsigned *m_off)
678 if (*m_len <= M2_MIN_LEN)
679 return;
681 if (*m_off <= M2_MAX_OFFSET)
682 return;
684 /* M3/M4 -> M2 */
685 if (*m_off > M2_MAX_OFFSET
686 && *m_len >= M2_MIN_LEN + 1 && *m_len <= M2_MAX_LEN + 1
687 && swd->best_off[*m_len-1] && swd->best_off[*m_len-1] <= M2_MAX_OFFSET
689 *m_len = *m_len - 1;
690 *m_off = swd->best_off[*m_len];
691 return;
694 /* M4 -> M2 */
695 if (*m_off > M3_MAX_OFFSET
696 && *m_len >= M4_MAX_LEN + 1 && *m_len <= M2_MAX_LEN + 2
697 && swd->best_off[*m_len-2] && swd->best_off[*m_len-2] <= M2_MAX_OFFSET
699 *m_len = *m_len - 2;
700 *m_off = swd->best_off[*m_len];
701 return;
703 /* M4 -> M3 */
704 if (*m_off > M3_MAX_OFFSET
705 && *m_len >= M4_MAX_LEN + 1 && *m_len <= M3_MAX_LEN + 1
706 && swd->best_off[*m_len-1] && swd->best_off[*m_len-1] <= M3_MAX_OFFSET
708 *m_len = *m_len - 1;
709 *m_off = swd->best_off[*m_len];
713 #endif
716 /***********************************************************************
718 ************************************************************************/
719 static int lzo1x_999_compress_internal(const uint8_t *in, unsigned in_len,
720 uint8_t *out, unsigned *out_len,
721 void *wrkmem,
722 unsigned good_length,
723 unsigned max_lazy,
724 unsigned max_chain,
725 uint32_t use_best_off)
727 uint8_t *op;
728 const uint8_t *ii;
729 unsigned lit;
730 unsigned m_len, m_off;
731 lzo1x_999_t cc;
732 lzo1x_999_t *const c = &cc;
733 const lzo_swd_p swd = (lzo_swd_p) wrkmem;
734 int r;
736 c->init = 0;
737 c->ip = c->in = in;
738 c->in_end = in + in_len;
739 c->out = out;
741 op = out;
742 ii = c->ip; /* point to start of literal run */
743 lit = 0;
744 c->r1_lit = 0;
746 r = init_match(c, swd, use_best_off);
747 if (r != 0)
748 return r;
749 swd->max_chain = max_chain;
751 r = find_match(c, swd, 0, 0);
752 if (r != 0)
753 return r;
755 while (c->look > 0) {
756 unsigned ahead;
757 unsigned max_ahead;
758 int l1, l2, l3;
760 m_len = c->m_len;
761 m_off = c->m_off;
763 assert(c->bp == c->ip - c->look);
764 assert(c->bp >= in);
765 if (lit == 0)
766 ii = c->bp;
767 assert(ii + lit == c->bp);
768 assert(swd->b_char == *(c->bp));
770 if (m_len < 2
771 || (m_len == 2 && (m_off > M1_MAX_OFFSET || lit == 0 || lit >= 4))
772 /* Do not accept this match for compressed-data compatibility
773 * with LZO v1.01 and before
774 * [ might be a problem for decompress() and optimize() ]
776 || (m_len == 2 && op == out)
777 || (op == out && lit == 0)
779 /* a literal */
780 m_len = 0;
782 else if (m_len == M2_MIN_LEN) {
783 /* compression ratio improves if we code a literal in some cases */
784 if (m_off > MX_MAX_OFFSET && lit >= 4)
785 m_len = 0;
788 if (m_len == 0) {
789 /* a literal */
790 lit++;
791 swd->max_chain = max_chain;
792 r = find_match(c, swd, 1, 0);
793 assert(r == 0);
794 continue;
797 /* a match */
798 #if defined(SWD_BEST_OFF)
799 if (swd->use_best_off)
800 better_match(swd, &m_len, &m_off);
801 #endif
803 /* shall we try a lazy match ? */
804 ahead = 0;
805 if (m_len >= max_lazy) {
806 /* no */
807 l1 = 0;
808 max_ahead = 0;
809 } else {
810 /* yes, try a lazy match */
811 l1 = len_of_coded_match(m_len, m_off, lit);
812 assert(l1 > 0);
813 max_ahead = LZO_MIN(2, (unsigned)l1 - 1);
817 while (ahead < max_ahead && c->look > m_len) {
818 int lazy_match_min_gain;
820 if (m_len >= good_length)
821 swd->max_chain = max_chain >> 2;
822 else
823 swd->max_chain = max_chain;
824 r = find_match(c, swd, 1, 0);
825 ahead++;
827 assert(r == 0);
828 assert(c->look > 0);
829 assert(ii + lit + ahead == c->bp);
831 if (c->m_len < m_len)
832 continue;
833 if (c->m_len == m_len && c->m_off >= m_off)
834 continue;
835 #if defined(SWD_BEST_OFF)
836 if (swd->use_best_off)
837 better_match(swd, &c->m_len, &c->m_off);
838 #endif
839 l2 = len_of_coded_match(c->m_len, c->m_off, lit+ahead);
840 if (l2 < 0)
841 continue;
843 /* compressed-data compatibility [see above] */
844 l3 = (op == out) ? -1 : len_of_coded_match(ahead, m_off, lit);
846 lazy_match_min_gain = min_gain(ahead, lit, lit+ahead, l1, l2, l3);
847 if (c->m_len >= m_len + lazy_match_min_gain) {
848 if (l3 > 0) {
849 /* code previous run */
850 op = code_run(c, op, ii, lit);
851 lit = 0;
852 /* code shortened match */
853 op = code_match(c, op, ahead, m_off);
854 } else {
855 lit += ahead;
856 assert(ii + lit == c->bp);
858 goto lazy_match_done;
862 assert(ii + lit + ahead == c->bp);
864 /* 1 - code run */
865 op = code_run(c, op, ii, lit);
866 lit = 0;
868 /* 2 - code match */
869 op = code_match(c, op, m_len, m_off);
870 swd->max_chain = max_chain;
871 r = find_match(c, swd, m_len, 1+ahead);
872 assert(r == 0);
874 lazy_match_done: ;
877 /* store final run */
878 if (lit > 0)
879 op = STORE_RUN(c, op, ii, lit);
881 #if defined(LZO_EOF_CODE)
882 *op++ = M4_MARKER | 1;
883 *op++ = 0;
884 *op++ = 0;
885 #endif
887 *out_len = op - out;
889 return LZO_E_OK;
893 /***********************************************************************
895 ************************************************************************/
896 int lzo1x_999_compress_level(const uint8_t *in, unsigned in_len,
897 uint8_t *out, unsigned *out_len,
898 void *wrkmem,
899 int compression_level)
901 static const struct {
902 uint16_t good_length;
903 uint16_t max_lazy;
904 uint16_t max_chain;
905 uint16_t use_best_off;
906 } c[3] = {
907 { 8, 32, 256, 0 },
908 { 32, 128, 2048, 1 },
909 { SWD_F, SWD_F, 4096, 1 } /* max. compression */
912 if (compression_level < 7 || compression_level > 9)
913 return LZO_E_ERROR;
915 compression_level -= 7;
916 return lzo1x_999_compress_internal(in, in_len, out, out_len, wrkmem,
917 c[compression_level].good_length,
918 c[compression_level].max_lazy,
919 c[compression_level].max_chain,
920 c[compression_level].use_best_off);