1 /* lzo1f_1.c -- implementation of the LZO1F-1 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/
42 #include "lzo/lzo1f.h"
45 /***********************************************************************
47 ************************************************************************/
49 #define M2_MAX_OFFSET 0x0800
50 #define M3_MAX_OFFSET 0x3fff
55 #define LZO_HASH LZO_HASH_LZO_INCREMENTAL_A
58 #define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5)
59 #define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f)
63 /***********************************************************************
64 // compress a block of data.
65 ************************************************************************/
68 int do_compress ( const lzo_bytep in , lzo_uint in_len,
69 lzo_bytep out, lzo_uintp out_len,
72 register const lzo_bytep ip;
74 const lzo_bytep const in_end = in + in_len;
75 const lzo_bytep const ip_end = in + in_len - 9;
77 lzo_dict_p const dict = (lzo_dict_p) wrkmem;
86 register const lzo_bytep m_pos;
93 GINDEX(m_pos,m_off,dict,dindex,in);
94 if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M3_MAX_OFFSET))
97 if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
101 GINDEX(m_pos,m_off,dict,dindex,in);
102 if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M3_MAX_OFFSET))
104 if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
110 #if 0 && defined(LZO_UNALIGNED_OK_2)
111 if (* (const lzo_ushortp) m_pos != * (const lzo_ushortp) ip)
113 if (m_pos[0] != ip[0] || m_pos[1] != ip[1])
119 if (m_pos[2] == ip[2])
123 if (m_off <= M2_MAX_OFFSET)
127 if (lit == 3) /* better compression, but slower */
129 assert(op - 2 > out); op[-2] |= LZO_BYTE(3);
130 *op++ = *ii++; *op++ = *ii++; *op++ = *ii++;
142 UPDATE_I(dict,0,dindex,ip,in);
150 UPDATE_I(dict,0,dindex,ip,in);
151 /* store current literal run */
155 register lzo_uint t = lit;
157 if (t < 4 && op > out)
158 op[-2] |= LZO_BYTE(t);
163 register lzo_uint tt = t - 31;
172 *op++ = LZO_BYTE(tt);
174 do *op++ = *ii++; while (--t > 0);
181 if (*m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++ ||
182 *m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++)
186 assert(m_len >= 3); assert(m_len <= 8);
188 if (m_off <= M2_MAX_OFFSET)
191 *op++ = LZO_BYTE(((m_len - 2) << 5) | ((m_off & 7) << 2));
192 *op++ = LZO_BYTE(m_off >> 3);
194 else if (m_len == 3 && m_off <= 2*M2_MAX_OFFSET && lit > 0)
197 /* m_off -= M2_MAX_OFFSET; */
198 *op++ = LZO_BYTE(((m_off & 7) << 2));
199 *op++ = LZO_BYTE(m_off >> 3);
203 *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
204 *op++ = LZO_BYTE((m_off & 63) << 2);
205 *op++ = LZO_BYTE(m_off >> 6);
213 while (ip < end && *m_pos == *ip)
220 *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
224 *op++ = M3_MARKER | 0;
231 *op++ = LZO_BYTE(m_len);
233 *op++ = LZO_BYTE((m_off & 63) << 2);
234 *op++ = LZO_BYTE(m_off >> 6);
243 /* store final literal run */
244 if (pd(in_end,ii) > 0)
246 register lzo_uint t = pd(in_end,ii);
248 if (t < 4 && op > out)
249 op[-2] |= LZO_BYTE(t);
254 register lzo_uint tt = t - 31;
263 *op++ = LZO_BYTE(tt);
265 do *op++ = *ii++; while (--t > 0);
268 *out_len = pd(op, out);
273 /***********************************************************************
274 // public entry point
275 ************************************************************************/
278 lzo1f_1_compress ( const lzo_bytep in , lzo_uint in_len,
279 lzo_bytep out, lzo_uintp out_len,
287 else if (in_len <= 10)
289 *op++ = LZO_BYTE(in_len);
290 do *op++ = *in++; while (--in_len > 0);
291 *out_len = pd(op, out);
294 r = do_compress(in,in_len,out,out_len,wrkmem);
299 *op++ = M3_MARKER | 1;