1 /* lzo1c_9x.c -- implementation of the LZO1C-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/
44 /***********************************************************************
46 ************************************************************************/
48 #define N 16383 /* size of ring buffer */
49 #define THRESHOLD 2 /* lower limit for match length */
50 #define F 2048 /* upper limit for match length */
54 #define LZO_COMPRESS_T lzo1c_999_t
55 #define lzo_swd_t lzo1c_999_swd_t
56 #include "lzo_mchw.ch"
60 /***********************************************************************
62 ************************************************************************/
65 code_match ( LZO_COMPRESS_T *c, lzo_bytep op, lzo_uint m_len, lzo_uint m_off )
67 if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
69 assert(m_len >= M2_MIN_LEN);
70 assert(m_off >= M2_MIN_OFFSET);
72 m_off -= M2_MIN_OFFSET;
73 /* code match len + low offset bits */
74 *op++ = LZO_BYTE(((m_len - (M2_MIN_LEN - 2)) << M2O_BITS) |
76 /* code high offset bits */
77 *op++ = LZO_BYTE(m_off >> M2O_BITS);
82 assert(m_len >= M3_MIN_LEN);
83 assert(m_off <= M3_MAX_OFFSET);
85 m_off -= M3_MIN_OFFSET - M3_EOF_OFFSET;
87 if (m_len <= M3_MAX_LEN)
88 *op++ = LZO_BYTE(M3_MARKER | (m_len - (M3_MIN_LEN - 1)));
91 assert(m_len >= M4_MIN_LEN);
92 /* code M4 match len flag */
95 m_len -= M4_MIN_LEN - 1;
102 *op++ = LZO_BYTE(m_len);
104 /* code low offset bits */
105 *op++ = LZO_BYTE(m_off & M3O_MASK);
106 /* code high offset bits */
107 *op++ = LZO_BYTE(m_off >> M3O_BITS);
117 /***********************************************************************
118 // this is a public function, but there is no prototype in a header file
119 ************************************************************************/
122 lzo1c_999_compress_callback ( const lzo_bytep in , lzo_uint in_len,
123 lzo_bytep out, lzo_uintp out_len,
126 lzo_uint max_chain );
129 lzo1c_999_compress_callback ( const lzo_bytep in , lzo_uint in_len,
130 lzo_bytep out, lzo_uintp out_len,
138 lzo_uint m_len, m_off;
140 LZO_COMPRESS_T * const c = &cc;
141 lzo_swd_p const swd = (lzo_swd_p) wrkmem;
145 LZO_COMPILE_TIME_ASSERT(LZO1C_999_MEM_COMPRESS >= SIZEOF_LZO_SWD_T)
149 c->in_end = in + in_len;
151 c->r1_r = c->m3_r = c->m2_m = c->m3_m = 0;
154 ii = c->ip; /* point to start of literal run */
157 c->m3 = out + 1; /* pointer after last m3/m4 match */
159 r = init_match(c,swd,NULL,0,0);
163 swd->max_chain = max_chain;
165 r = find_match(c,swd,0,0);
170 int lazy_match_min_gain = -1;
177 printf("%5ld: %5d len:%3d off:%5d\n", (c->ip-c->look)-in, c->look,
181 assert(c->ip - c->look >= in);
183 ii = c->ip - c->look;
184 assert(ii + lit == c->ip - c->look);
185 assert(swd->b_char == *(c->ip - c->look));
187 if ((m_len < M2_MIN_LEN) ||
188 (m_len < M3_MIN_LEN && m_off > M2_MAX_OFFSET))
194 assert(c->ip - c->look - m_off >= in);
195 assert(c->ip - c->look - m_off + m_len < c->ip);
196 assert(lzo_memcmp(c->ip - c->look, c->ip - c->look - m_off,
201 /* we have a current literal run: do not try a lazy match,
202 if the literal could be coded into a r1 or m3 match */
203 if (lit == 1 && c->r1_m_len == M2_MIN_LEN)
204 lazy_match_min_gain = -1;
205 else if (lit == 3 && op == c->m3)
206 lazy_match_min_gain = -1;
207 else if (lit < 3 && op == c->m3)
208 lazy_match_min_gain = 0;
210 lazy_match_min_gain = 1;
212 #if (M2_MIN_LEN == 2)
215 /* don't code a match of len 2 if we have to
216 code a literal run. Code a literal instead. */
220 #if (M2_MIN_LEN == M3_MIN_LEN)
221 if (m_len == M2_MIN_LEN && m_off > M2_MAX_OFFSET)
223 /* don't code a M3 match of len 3 if we have to
224 code a literal run. Code a literal instead. */
231 /* no current literal run: only try a lazy match,
232 if the literal could be coded into a r1 or m3 match */
233 if (c->r1_m_len == M2_MIN_LEN || op == c->m3)
234 lazy_match_min_gain = 0;
236 lazy_match_min_gain = -1;
241 /* try a lazy match */
243 lazy_match_min_gain = -1;
244 if (lazy_match_min_gain >= 0 && c->look > m_len)
248 r = find_match(c,swd,1,0);
252 if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET &&
253 c->m_off > M2_MAX_OFFSET)
254 lazy_match_min_gain += 1;
256 if (c->m_len >= m_len + lazy_match_min_gain)
262 assert(lzo_memcmp(c->ip - c->look, c->ip - c->look - m_off,
266 assert(ii + lit == c->ip - c->look);
272 assert(ii + lit + 1 == c->ip - c->look);
276 assert(ii + lit + ahead == c->ip - c->look);
283 r = find_match(c,swd,1,0);
291 /* code current literal run */
292 if (lit == 1 && c->r1_m_len == M2_MIN_LEN)
294 /* Code a context sensitive R1 match. */
295 assert((op[-2] >> M2O_BITS) == (M2_MARKER >> M2O_BITS));
297 assert((op[-2] >> M2O_BITS) == 0);
300 assert(ii + ahead == c->ip - c->look);
303 else if (lit < 4 && op == c->m3)
305 assert((c->m3[-2] >> M3O_BITS) == 0);
306 c->m3[-2] |= LZO_BYTE(lit << M3O_BITS);
307 MEMCPY_DS(op, ii, lit);
308 assert(ii + ahead == c->ip - c->look);
313 op = STORE_RUN(op,ii,lit);
325 op = code_match(c,op,m_len,m_off);
326 r = find_match(c,swd,m_len,1+ahead);
330 c->codesize = pd(op, out);
334 /* store final run */
336 op = STORE_RUN(op,ii,lit);
338 #if defined(LZO_EOF_CODE)
339 *op++ = M3_MARKER | 1;
344 c->codesize = pd(op, out);
345 assert(c->textsize == in_len);
347 *out_len = pd(op, out);
349 if (c->cb && c->cb->nprogress)
350 (*c->cb->nprogress)(c->cb, c->textsize, c->codesize, 0);
353 printf("%ld %ld -> %ld: %ld %ld %ld %ld %ld\n",
354 (long) c->textsize, (long)in_len, (long) c->codesize,
355 c->r1_r, c->m3_r, c->m2_m, c->m3_m, c->lazy);
362 /***********************************************************************
364 ************************************************************************/
367 lzo1c_999_compress ( const lzo_bytep in , lzo_uint in_len,
368 lzo_bytep out, lzo_uintp out_len,
371 return lzo1c_999_compress_callback(in,in_len,out,out_len,wrkmem,
372 (lzo_callback_p) 0, 0);