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
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/
41 /* The following is probably only safe on Intel-compatible processors ... */
42 #define LZO_UNALIGNED_OK_2
43 #define LZO_UNALIGNED_OK_4
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)
62 unsigned look
; /* bytes in lookahead buffer */
70 const uint8_t *in_end
;
76 #define getbyte(c) ((c).ip < (c).in_end ? *((c).ip)++ : (-1))
78 /* lzo_swd.c -- sliding window dictionary */
80 /***********************************************************************
82 ************************************************************************/
83 #define SWD_UINT_MAX USHRT_MAX
86 # define SWD_HSIZE 16384
89 # define SWD_MAX_CHAIN 2048
93 ( ((0x9f5f * ((((b[p]<<5)^b[p+1])<<5) ^ b[p+2])) >> 5) & (SWD_HSIZE-1) )
95 #if defined(LZO_UNALIGNED_OK_2)
96 # define HEAD2(b,p) (* (bb__aliased_uint16_t *) &(b[p]))
98 # define HEAD2(b,p) (b[p] ^ ((unsigned)b[p+1]<<8))
100 #define NIL2 SWD_UINT_MAX
102 typedef struct lzo_swd
{
103 /* public - "built-in" */
105 /* public - configuration */
109 /* public - output */
114 #if defined(SWD_BEST_OFF)
115 unsigned best_off
[SWD_BEST_OFF
];
121 #if defined(SWD_BEST_OFF)
122 unsigned best_pos
[SWD_BEST_OFF
];
126 unsigned ip
; /* input pointer (lookahead) */
127 unsigned bp
; /* buffer pointer */
128 unsigned rp
; /* remove pointer */
133 uint8_t b
[SWD_N
+ SWD_F
];
134 uint8_t b_wrap
[SWD_F
]; /* must follow b */
135 uint16_t head3
[SWD_HSIZE
];
136 uint16_t succ3
[SWD_N
+ SWD_F
];
137 uint16_t best3
[SWD_N
+ SWD_F
];
138 uint16_t llen3
[SWD_HSIZE
];
140 uint16_t head2
[65536L];
142 } lzo_swd_t
, *lzo_swd_p
;
144 #define SIZEOF_LZO_SWD_T (sizeof(lzo_swd_t))
147 /* Access macro for head3.
148 * head3[key] may be uninitialized, but then its value will never be used.
150 #define s_get_head3(s,key) s->head3[key]
153 /***********************************************************************
155 ************************************************************************/
156 #define B_SIZE (SWD_N + SWD_F)
158 static int swd_init(lzo_swd_p s
)
161 s
->node_count
= SWD_N
;
163 memset(s
->llen3
, 0, sizeof(s
->llen3
[0]) * (unsigned)SWD_HSIZE
);
165 memset(s
->head2
, 0xff, sizeof(s
->head2
[0]) * 65536L);
166 assert(s
->head2
[0] == NIL2
);
173 assert(s
->ip
+ SWD_F
<= B_SIZE
);
174 s
->look
= (unsigned) (s
->c
->in_end
- s
->c
->ip
);
178 memcpy(&s
->b
[s
->ip
], s
->c
->ip
, s
->look
);
186 if (s
->rp
>= s
->node_count
)
187 s
->rp
-= s
->node_count
;
189 s
->rp
+= B_SIZE
- s
->node_count
;
194 #define swd_pos2off(s,pos) \
195 (s->bp > (pos) ? s->bp - (pos) : B_SIZE - ((pos) - s->bp))
198 /***********************************************************************
200 ************************************************************************/
201 static void swd_getbyte(lzo_swd_p s
)
205 if ((c
= getbyte(*(s
->c
))) < 0) {
211 s
->b_wrap
[s
->ip
] = c
;
213 if (++s
->ip
== B_SIZE
)
215 if (++s
->bp
== B_SIZE
)
217 if (++s
->rp
== B_SIZE
)
222 /***********************************************************************
223 // remove node from lists
224 ************************************************************************/
225 static void swd_remove_node(lzo_swd_p s
, unsigned node
)
227 if (s
->node_count
== 0) {
230 key
= HEAD3(s
->b
,node
);
231 assert(s
->llen3
[key
] > 0);
235 key
= HEAD2(s
->b
,node
);
236 assert(s
->head2
[key
] != NIL2
);
237 if ((unsigned) s
->head2
[key
] == node
)
238 s
->head2
[key
] = NIL2
;
245 /***********************************************************************
247 ************************************************************************/
248 static void swd_accept(lzo_swd_p s
, unsigned n
)
250 assert(n
<= s
->look
);
255 swd_remove_node(s
,s
->rp
);
257 /* add bp into HEAD3 */
258 key
= HEAD3(s
->b
, s
->bp
);
259 s
->succ3
[s
->bp
] = s_get_head3(s
, key
);
260 s
->head3
[key
] = s
->bp
;
261 s
->best3
[s
->bp
] = SWD_F
+ 1;
263 assert(s
->llen3
[key
] <= SWD_N
);
266 /* add bp into HEAD2 */
267 key
= HEAD2(s
->b
, s
->bp
);
268 s
->head2
[key
] = s
->bp
;
276 /***********************************************************************
278 ************************************************************************/
279 static void swd_search(lzo_swd_p s
, unsigned node
, unsigned cnt
)
284 unsigned m_len
= s
->m_len
;
285 const uint8_t *b
= s
->b
;
286 const uint8_t *bp
= s
->b
+ s
->bp
;
287 const uint8_t *bx
= s
->b
+ s
->bp
+ s
->look
;
288 unsigned char scan_end1
;
290 assert(s
->m_len
> 0);
292 scan_end1
= bp
[m_len
- 1];
293 for ( ; cnt
-- > 0; node
= s
->succ3
[node
]) {
298 assert(m_len
< s
->look
);
300 if (p2
[m_len
- 1] == scan_end1
301 && p2
[m_len
] == p1
[m_len
]
306 assert(lzo_memcmp(bp
, &b
[node
], 3) == 0);
309 do {} while (++p1
< px
&& *p1
== *++p2
);
312 assert(lzo_memcmp(bp
, &b
[node
], i
) == 0);
314 #if defined(SWD_BEST_OFF)
315 if (i
< SWD_BEST_OFF
) {
316 if (s
->best_pos
[i
] == 0)
317 s
->best_pos
[i
] = node
+ 1;
321 s
->m_len
= m_len
= i
;
323 if (m_len
== s
->look
)
327 if (m_len
> (unsigned) s
->best3
[node
])
329 scan_end1
= bp
[m_len
- 1];
336 /***********************************************************************
338 ************************************************************************/
341 static int swd_search2(lzo_swd_p s
)
345 assert(s
->look
>= 2);
346 assert(s
->m_len
> 0);
348 key
= s
->head2
[HEAD2(s
->b
, s
->bp
)];
351 assert(lzo_memcmp(&s
->b
[s
->bp
], &s
->b
[key
], 2) == 0);
352 #if defined(SWD_BEST_OFF)
353 if (s
->best_pos
[2] == 0)
354 s
->best_pos
[2] = key
+ 1;
367 /***********************************************************************
369 ************************************************************************/
370 static void swd_findbest(lzo_swd_p s
)
376 assert(s
->m_len
> 0);
378 /* get current head, add bp into HEAD3 */
379 key
= HEAD3(s
->b
,s
->bp
);
380 node
= s
->succ3
[s
->bp
] = s_get_head3(s
, key
);
381 cnt
= s
->llen3
[key
]++;
382 assert(s
->llen3
[key
] <= SWD_N
+ SWD_F
);
383 if (cnt
> s
->max_chain
)
385 s
->head3
[key
] = s
->bp
;
387 s
->b_char
= s
->b
[s
->bp
];
389 if (s
->m_len
>= s
->look
) {
393 s
->best3
[s
->bp
] = SWD_F
+ 1;
399 swd_search(s
, node
, cnt
);
401 s
->m_off
= swd_pos2off(s
,s
->m_pos
);
402 s
->best3
[s
->bp
] = s
->m_len
;
404 #if defined(SWD_BEST_OFF)
405 if (s
->use_best_off
) {
407 for (i
= 2; i
< SWD_BEST_OFF
; i
++) {
408 if (s
->best_pos
[i
] > 0)
409 s
->best_off
[i
] = swd_pos2off(s
, s
->best_pos
[i
]-1);
417 swd_remove_node(s
,s
->rp
);
420 /* add bp into HEAD2 */
421 key
= HEAD2(s
->b
, s
->bp
);
422 s
->head2
[key
] = s
->bp
;
431 /***********************************************************************
433 ************************************************************************/
434 static int init_match(lzo1x_999_t
*c
, lzo_swd_p s
, uint32_t use_best_off
)
447 s
->use_best_off
= use_best_off
;
452 /***********************************************************************
454 ************************************************************************/
455 static int find_match(lzo1x_999_t
*c
, lzo_swd_p s
,
456 unsigned this_len
, unsigned skip
)
461 assert(this_len
>= skip
);
462 swd_accept(s
, this_len
- skip
);
464 assert(this_len
<= 1);
470 memset(s
->best_pos
, 0, sizeof(s
->best_pos
));
482 c
->look
= s
->look
+ 1;
484 c
->bp
= c
->ip
- c
->look
;
489 /* this is a public functions, but there is no prototype in a header file */
490 static int lzo1x_999_compress_internal(const uint8_t *in
, unsigned in_len
,
491 uint8_t *out
, unsigned *out_len
,
493 unsigned good_length
,
496 uint32_t use_best_off
);
499 /***********************************************************************
501 ************************************************************************/
502 static uint8_t *code_match(lzo1x_999_t
*c
,
503 uint8_t *op
, unsigned m_len
, unsigned m_off
)
507 assert(m_off
<= M1_MAX_OFFSET
);
508 assert(c
->r1_lit
> 0);
509 assert(c
->r1_lit
< 4);
511 *op
++ = M1_MARKER
| ((m_off
& 3) << 2);
513 } else if (m_len
<= M2_MAX_LEN
&& m_off
<= M2_MAX_OFFSET
) {
516 *op
++ = ((m_len
- 1) << 5) | ((m_off
& 7) << 2);
518 assert(op
[-2] >= M2_MARKER
);
519 } else if (m_len
== M2_MIN_LEN
&& m_off
<= MX_MAX_OFFSET
&& c
->r1_lit
>= 4) {
521 assert(m_off
> M2_MAX_OFFSET
);
522 m_off
-= 1 + M2_MAX_OFFSET
;
523 *op
++ = M1_MARKER
| ((m_off
& 3) << 2);
525 } else if (m_off
<= M3_MAX_OFFSET
) {
528 if (m_len
<= M3_MAX_LEN
)
529 *op
++ = M3_MARKER
| (m_len
- 2);
532 *op
++ = M3_MARKER
| 0;
533 while (m_len
> 255) {
546 assert(m_off
> 0x4000);
547 assert(m_off
<= 0xbfff);
549 k
= (m_off
& 0x4000) >> 11;
550 if (m_len
<= M4_MAX_LEN
)
551 *op
++ = M4_MARKER
| k
| (m_len
- 2);
554 *op
++ = M4_MARKER
| k
| 0;
555 while (m_len
> 255) {
570 static uint8_t *STORE_RUN(lzo1x_999_t
*c
, uint8_t *op
,
571 const uint8_t *ii
, unsigned t
)
573 if (op
== c
->out
&& t
<= 238) {
577 } else if (t
<= 18) {
580 unsigned tt
= t
- 18;
590 do *op
++ = *ii
++; while (--t
> 0);
596 static uint8_t *code_run(lzo1x_999_t
*c
, uint8_t *op
, const uint8_t *ii
,
601 op
= STORE_RUN(c
, op
, ii
, lit
);
611 /***********************************************************************
613 ************************************************************************/
614 static int len_of_coded_match(unsigned m_len
, unsigned m_off
, unsigned lit
)
621 return (m_off
<= M1_MAX_OFFSET
&& lit
> 0 && lit
< 4) ? 2 : -1;
622 if (m_len
<= M2_MAX_LEN
&& m_off
<= M2_MAX_OFFSET
)
624 if (m_len
== M2_MIN_LEN
&& m_off
<= MX_MAX_OFFSET
&& lit
>= 4)
626 if (m_off
<= M3_MAX_OFFSET
) {
627 if (m_len
<= M3_MAX_LEN
)
630 } else if (m_off
<= M4_MAX_OFFSET
) {
631 if (m_len
<= M4_MAX_LEN
)
636 while (m_len
> 255) {
644 static int min_gain(unsigned ahead
, unsigned lit1
,
645 unsigned lit2
, int l1
, int l2
, int l3
)
647 int lazy_match_min_gain
= 0;
650 lazy_match_min_gain
+= ahead
;
653 lazy_match_min_gain
+= (lit2
<= 3) ? 0 : 2;
655 lazy_match_min_gain
+= (lit2
<= 18) ? 0 : 1;
657 lazy_match_min_gain
+= (l2
- l1
) * 2;
659 lazy_match_min_gain
-= (ahead
- l3
) * 2;
661 if (lazy_match_min_gain
< 0)
662 lazy_match_min_gain
= 0;
664 return lazy_match_min_gain
;
668 /***********************************************************************
670 ************************************************************************/
671 #if defined(SWD_BEST_OFF)
673 static void better_match(const lzo_swd_p swd
,
674 unsigned *m_len
, unsigned *m_off
)
676 if (*m_len
<= M2_MIN_LEN
)
679 if (*m_off
<= M2_MAX_OFFSET
)
683 if (*m_off
> M2_MAX_OFFSET
684 && *m_len
>= M2_MIN_LEN
+ 1 && *m_len
<= M2_MAX_LEN
+ 1
685 && swd
->best_off
[*m_len
-1] && swd
->best_off
[*m_len
-1] <= M2_MAX_OFFSET
688 *m_off
= swd
->best_off
[*m_len
];
693 if (*m_off
> M3_MAX_OFFSET
694 && *m_len
>= M4_MAX_LEN
+ 1 && *m_len
<= M2_MAX_LEN
+ 2
695 && swd
->best_off
[*m_len
-2] && swd
->best_off
[*m_len
-2] <= M2_MAX_OFFSET
698 *m_off
= swd
->best_off
[*m_len
];
702 if (*m_off
> M3_MAX_OFFSET
703 && *m_len
>= M4_MAX_LEN
+ 1 && *m_len
<= M3_MAX_LEN
+ 1
704 && swd
->best_off
[*m_len
-1] && swd
->best_off
[*m_len
-1] <= M3_MAX_OFFSET
707 *m_off
= swd
->best_off
[*m_len
];
714 /***********************************************************************
716 ************************************************************************/
717 static int lzo1x_999_compress_internal(const uint8_t *in
, unsigned in_len
,
718 uint8_t *out
, unsigned *out_len
,
720 unsigned good_length
,
723 uint32_t use_best_off
)
728 unsigned m_len
, m_off
;
730 lzo1x_999_t
*const c
= &cc
;
731 const lzo_swd_p swd
= (lzo_swd_p
) wrkmem
;
736 c
->in_end
= in
+ in_len
;
740 ii
= c
->ip
; /* point to start of literal run */
744 r
= init_match(c
, swd
, use_best_off
);
747 swd
->max_chain
= max_chain
;
749 r
= find_match(c
, swd
, 0, 0);
753 while (c
->look
> 0) {
761 assert(c
->bp
== c
->ip
- c
->look
);
765 assert(ii
+ lit
== c
->bp
);
766 assert(swd
->b_char
== *(c
->bp
));
769 || (m_len
== 2 && (m_off
> M1_MAX_OFFSET
|| lit
== 0 || lit
>= 4))
770 /* Do not accept this match for compressed-data compatibility
771 * with LZO v1.01 and before
772 * [ might be a problem for decompress() and optimize() ]
774 || (m_len
== 2 && op
== out
)
775 || (op
== out
&& lit
== 0)
780 else if (m_len
== M2_MIN_LEN
) {
781 /* compression ratio improves if we code a literal in some cases */
782 if (m_off
> MX_MAX_OFFSET
&& lit
>= 4)
789 swd
->max_chain
= max_chain
;
790 r
= find_match(c
, swd
, 1, 0);
796 #if defined(SWD_BEST_OFF)
797 if (swd
->use_best_off
)
798 better_match(swd
, &m_len
, &m_off
);
801 /* shall we try a lazy match ? */
803 if (m_len
>= max_lazy
) {
808 /* yes, try a lazy match */
809 l1
= len_of_coded_match(m_len
, m_off
, lit
);
811 max_ahead
= LZO_MIN(2, (unsigned)l1
- 1);
815 while (ahead
< max_ahead
&& c
->look
> m_len
) {
816 int lazy_match_min_gain
;
818 if (m_len
>= good_length
)
819 swd
->max_chain
= max_chain
>> 2;
821 swd
->max_chain
= max_chain
;
822 r
= find_match(c
, swd
, 1, 0);
827 assert(ii
+ lit
+ ahead
== c
->bp
);
829 if (c
->m_len
< m_len
)
831 if (c
->m_len
== m_len
&& c
->m_off
>= m_off
)
833 #if defined(SWD_BEST_OFF)
834 if (swd
->use_best_off
)
835 better_match(swd
, &c
->m_len
, &c
->m_off
);
837 l2
= len_of_coded_match(c
->m_len
, c
->m_off
, lit
+ahead
);
841 /* compressed-data compatibility [see above] */
842 l3
= (op
== out
) ? -1 : len_of_coded_match(ahead
, m_off
, lit
);
844 lazy_match_min_gain
= min_gain(ahead
, lit
, lit
+ahead
, l1
, l2
, l3
);
845 if (c
->m_len
>= m_len
+ lazy_match_min_gain
) {
847 /* code previous run */
848 op
= code_run(c
, op
, ii
, lit
);
850 /* code shortened match */
851 op
= code_match(c
, op
, ahead
, m_off
);
854 assert(ii
+ lit
== c
->bp
);
856 goto lazy_match_done
;
860 assert(ii
+ lit
+ ahead
== c
->bp
);
863 op
= code_run(c
, op
, ii
, lit
);
867 op
= code_match(c
, op
, m_len
, m_off
);
868 swd
->max_chain
= max_chain
;
869 r
= find_match(c
, swd
, m_len
, 1+ahead
);
875 /* store final run */
877 op
= STORE_RUN(c
, op
, ii
, lit
);
879 #if defined(LZO_EOF_CODE)
880 *op
++ = M4_MARKER
| 1;
891 /***********************************************************************
893 ************************************************************************/
894 int lzo1x_999_compress_level(const uint8_t *in
, unsigned in_len
,
895 uint8_t *out
, unsigned *out_len
,
897 int compression_level
)
899 static const struct {
900 uint16_t good_length
;
903 uint16_t use_best_off
;
906 { 32, 128, 2048, 1 },
907 { SWD_F
, SWD_F
, 4096, 1 } /* max. compression */
910 if (compression_level
< 7 || compression_level
> 9)
913 compression_level
-= 7;
914 return lzo1x_999_compress_internal(in
, in_len
, out
, out_len
, wrkmem
,
915 c
[compression_level
].good_length
,
916 c
[compression_level
].max_lazy
,
917 c
[compression_level
].max_chain
,
918 c
[compression_level
].use_best_off
);