1 /* lzo1x_oo.ch -- LZO1X compressed data optimizer
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 #define TEST_IP (ip < ip_end)
42 #define TEST_OP (op <= op_end)
44 #define NO_LIT LZO_UINT_MAX
47 /***********************************************************************
49 ************************************************************************/
51 static void copy2(lzo_bytep ip, const lzo_bytep m_pos, lzo_uint off)
62 static void copy3(lzo_bytep ip, const lzo_bytep m_pos, lzo_uint off)
68 ip[2] = ip[1] = m_pos[0];
83 /***********************************************************************
84 // optimize a block of data.
85 ************************************************************************/
88 DO_OPTIMIZE ( lzo_bytep in , lzo_uint in_len,
89 lzo_bytep out, lzo_uintp out_len,
96 lzo_bytep const ip_end = in + in_len;
97 lzo_bytep const op_end = out + *out_len;
98 lzo_bytep litp = NULL;
100 lzo_uint next_lit = NO_LIT;
102 unsigned long o_m1_a = 0, o_m1_b = 0, o_m2 = 0, o_m3_a = 0, o_m3_b = 0;
117 goto first_literal_run;
119 assert(*ip < 16 || (*ip == 17 && in_len == 3));
121 while (TEST_IP && TEST_OP)
138 *op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
140 do *op++ = *ip++; while (--t > 0);
148 m_pos = op - 1 - 0x800;
150 m_pos = op - 1 - 0x400;
154 *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos++;
161 if (t < 16) /* a M1 match */
170 /* assert that there was a match just before */
171 assert(lit >= 1 && lit <= 3);
172 assert(litp == ip - 2 - lit - 2);
173 assert((lzo_uint)(*litp & 3) == lit);
175 /* test if a match follows */
176 if (nl == 0 && lit == 1 && ip[0] >= 16)
179 /* adjust length of previous short run */
181 *litp = LZO_BYTE((*litp & ~3) | lit);
182 /* copy over the 2 literals that replace the match */
183 copy2(ip-2,m_pos,pd(op,m_pos));
186 /* test if a literal run follows */
187 else if (nl == 0 && ip[0] < 16 && ip[0] != 0 &&
188 (lit + 2 + ip[0] < 16))
191 /* remove short run */
193 /* copy over the 2 literals that replace the match */
194 copy2(ip-3+1,m_pos,pd(op,m_pos));
195 /* move literals 1 byte ahead */
198 lzo_memmove(litp+1,litp,lit);
199 /* insert new length of long literal run */
200 lit += 2 + t + 3; assert(lit <= 18);
201 *litp = LZO_BYTE(lit - 3);
204 *op++ = *m_pos++; *op++ = *m_pos++;
205 goto copy_literal_run;
208 *op++ = *m_pos++; *op++ = *m_pos++;
213 if (t >= 64) /* a M2 match */
217 m_pos -= (t >> 2) & 7;
221 m_pos -= (t >> 2) & 3;
229 /* test if in beetween two long literal runs */
230 if (t == 1 && lit > 3 && nl == 0 &&
231 ip[0] < 16 && ip[0] != 0 && (lit + 3 + ip[0] < 16))
233 assert(*litp == lit - 3);
235 /* copy over the 3 literals that replace the match */
236 copy3(ip-1-2,m_pos,pd(op,m_pos));
237 /* set new length of previous literal run */
238 lit += 3 + t + 3; assert(lit <= 18);
239 *litp = LZO_BYTE(lit - 3);
241 *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos++;
242 goto copy_literal_run;
247 if (t >= 32) /* a M3 match */
261 else /* a M4 match */
264 m_pos -= (t & 8) << 11;
283 /* test if in beetween two matches */
284 if (t == 1 && lit == 0 && nl == 0 && ip[0] >= 16)
286 assert(litp == ip - 3 - lit - 2);
287 assert((lzo_uint)(*litp & 3) == lit);
289 /* make a previous short run */
291 *litp = LZO_BYTE((*litp & ~3) | lit);
292 /* copy over the 3 literals that replace the match */
293 copy3(ip-3,m_pos,pd(op,m_pos));
296 /* test if a literal run follows */
297 else if (t == 1 && lit <= 3 && nl == 0 &&
298 ip[0] < 16 && ip[0] != 0 && (lit + 3 + ip[0] < 16))
300 assert(litp == ip - 3 - lit - 2);
301 assert((lzo_uint)(*litp & 3) == lit);
303 /* remove short run */
305 /* copy over the 3 literals that replace the match */
306 copy3(ip-4+1,m_pos,pd(op,m_pos));
307 /* move literals 1 byte ahead */
310 lzo_memmove(litp+1,litp,lit);
311 /* insert new length of long literal run */
312 lit += 3 + t + 3; assert(lit <= 18);
313 *litp = LZO_BYTE(lit - 3);
316 *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos++;
317 goto copy_literal_run;
321 *op++ = *m_pos++; *op++ = *m_pos++;
322 do *op++ = *m_pos++; while (--t > 0);
326 if (next_lit == NO_LIT)
340 do *op++ = *ip++; while (--t > 0);
342 } while (TEST_IP && TEST_OP);
345 /* no EOF code was found */
346 *out_len = pd(op, out);
347 return LZO_E_EOF_NOT_FOUND;
352 printf("optimize: %5lu %5lu %5lu %5lu %5lu\n",
353 o_m1_a, o_m1_b, o_m2, o_m3_a, o_m3_b);
355 LZO_UNUSED(o_m1_a); LZO_UNUSED(o_m1_b); LZO_UNUSED(o_m2);
356 LZO_UNUSED(o_m3_a); LZO_UNUSED(o_m3_b);
357 *out_len = pd(op, out);
358 return (ip == ip_end ? LZO_E_OK :
359 (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));