1 /* lzo1x_d.ch -- implementation of the LZO1X decompression 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/
45 #define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src)
48 #if defined(LZO_UNALIGNED_OK_4)
49 # define COPY4(dst,src) __COPY4(dst,src)
50 #elif defined(LZO_ALIGNED_OK_4)
51 # define COPY4(dst,src) __COPY4((lzo_uintptr_t)(dst),(lzo_uintptr_t)(src))
55 /***********************************************************************
56 // decompress a block of data.
57 ************************************************************************/
59 #if defined(DO_DECOMPRESS)
61 DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len,
62 lzo_bytep out, lzo_uintp out_len,
66 register lzo_bytep op;
67 register const lzo_bytep ip;
69 #if defined(COPY_DICT)
71 const lzo_bytep dict_end;
73 register const lzo_bytep m_pos;
76 const lzo_bytep const ip_end = in + in_len;
77 #if defined(HAVE_ANY_OP)
78 lzo_bytep const op_end = out + *out_len;
81 lzo_uint last_m_off = 0;
86 #if defined(COPY_DICT)
89 if (dict_len > M4_MAX_OFFSET)
91 dict += dict_len - M4_MAX_OFFSET;
92 dict_len = M4_MAX_OFFSET;
94 dict_end = dict + dict_len;
101 #endif /* COPY_DICT */
113 assert(t > 0); NEED_OP(t); NEED_IP(t+1);
114 do *op++ = *ip++; while (--t > 0);
115 goto first_literal_run;
118 while (TEST_IP && TEST_OP)
136 assert(t > 0); NEED_OP(t+3); NEED_IP(t+4);
137 #if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
138 #if !defined(LZO_UNALIGNED_OK_4)
139 if (PTR_ALIGNED2_4(op,ip))
150 op += 4; ip += 4; t -= 4;
152 if (t > 0) do *op++ = *ip++; while (--t > 0);
155 do *op++ = *ip++; while (--t > 0);
157 #if !defined(LZO_UNALIGNED_OK_4)
162 #if !defined(LZO_UNALIGNED_OK_4)
164 *op++ = *ip++; *op++ = *ip++; *op++ = *ip++;
165 do *op++ = *ip++; while (--t > 0);
176 #if defined(COPY_DICT)
178 m_off = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
181 m_off = (1 + M2_MAX_OFFSET) + (t >> 2) + (*ip++ << 2);
184 t = 3; COPY_DICT(t,m_off)
185 #else /* !COPY_DICT */
187 t = (1 + M2_MAX_OFFSET) + (t << 6) + (*ip++ >> 2);
191 m_pos = op - (1 + M2_MAX_OFFSET);
195 TEST_LB(m_pos); NEED_OP(3);
196 *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos;
197 #endif /* COPY_DICT */
204 if (t >= 64) /* a M2 match */
206 #if defined(COPY_DICT)
208 m_off = 1 + ((t >> 2) & 7) + (*ip++ << 3);
211 m_off = 1 + ((t >> 2) & 3) + (*ip++ << 2);
219 m_off = 1 + (m_off << 6) + (*ip++ >> 2);
224 #else /* !COPY_DICT */
227 m_pos -= (t >> 2) & 7;
232 m_pos -= (t >> 2) & 3;
237 lzo_uint off = t & 0x1f;
241 assert(last_m_off > 0);
246 off = 1 + (off << 6) + (*ip++ >> 2);
253 TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
255 #endif /* COPY_DICT */
257 else if (t >= 32) /* a M3 match */
271 #if defined(COPY_DICT)
273 m_off = 1 + (ip[0] << 6) + (ip[1] >> 2);
276 m_off = 1 + (ip[0] >> 2) + (ip[1] << 6);
278 #else /* !COPY_DICT */
281 lzo_uint off = 1 + (ip[0] << 6) + (ip[1] >> 2);
285 #elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
287 m_pos -= (* (const lzo_ushortp) ip) >> 2;
290 m_pos -= (ip[0] >> 2) + (ip[1] << 6);
292 #endif /* COPY_DICT */
295 else if (t >= 16) /* a M4 match */
297 #if defined(COPY_DICT)
298 m_off = (t & 8) << 11;
299 #else /* !COPY_DICT */
301 m_pos -= (t & 8) << 11;
302 #endif /* COPY_DICT */
315 #if defined(COPY_DICT)
317 m_off += (ip[0] << 6) + (ip[1] >> 2);
319 m_off += (ip[0] >> 2) + (ip[1] << 6);
328 #else /* !COPY_DICT */
330 m_pos -= (ip[0] << 6) + (ip[1] >> 2);
331 #elif defined(LZO_UNALIGNED_OK_2) && defined(LZO_ABI_LITTLE_ENDIAN)
332 m_pos -= (* (const lzo_ushortp) ip) >> 2;
334 m_pos -= (ip[0] >> 2) + (ip[1] << 6);
341 last_m_off = pd((const lzo_bytep)op, m_pos);
343 #endif /* COPY_DICT */
345 else /* a M1 match */
347 #if defined(COPY_DICT)
349 m_off = 1 + (t << 6) + (*ip++ >> 2);
352 m_off = 1 + (t >> 2) + (*ip++ << 2);
355 t = 2; COPY_DICT(t,m_off)
356 #else /* !COPY_DICT */
358 t = 1 + (t << 6) + (*ip++ >> 2);
366 TEST_LB(m_pos); NEED_OP(2);
367 *op++ = *m_pos++; *op++ = *m_pos;
368 #endif /* COPY_DICT */
373 #if defined(COPY_DICT)
376 t += 3-1; COPY_DICT(t,m_off)
378 #else /* !COPY_DICT */
380 TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
381 #if defined(LZO_UNALIGNED_OK_4) || defined(LZO_ALIGNED_OK_4)
382 #if !defined(LZO_UNALIGNED_OK_4)
383 if (t >= 2 * 4 - (3 - 1) && PTR_ALIGNED2_4(op,m_pos))
385 assert((op - m_pos) >= 4); /* both pointers are aligned */
387 if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
391 op += 4; m_pos += 4; t -= 4 - (3 - 1);
394 op += 4; m_pos += 4; t -= 4;
396 if (t > 0) do *op++ = *m_pos++; while (--t > 0);
402 *op++ = *m_pos++; *op++ = *m_pos++;
403 do *op++ = *m_pos++; while (--t > 0);
406 #endif /* COPY_DICT */
419 assert(t > 0); assert(t < 4); NEED_OP(t); NEED_IP(t+1);
421 do *op++ = *ip++; while (--t > 0);
424 if (t > 1) { *op++ = *ip++; if (t > 2) { *op++ = *ip++; } }
427 } while (TEST_IP && TEST_OP);
430 #if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
431 /* no EOF code was found */
432 *out_len = pd(op, out);
433 return LZO_E_EOF_NOT_FOUND;
438 *out_len = pd(op, out);
439 return (ip == ip_end ? LZO_E_OK :
440 (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
443 #if defined(HAVE_NEED_IP)
445 *out_len = pd(op, out);
446 return LZO_E_INPUT_OVERRUN;
449 #if defined(HAVE_NEED_OP)
451 *out_len = pd(op, out);
452 return LZO_E_OUTPUT_OVERRUN;
455 #if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
457 *out_len = pd(op, out);
458 return LZO_E_LOOKBEHIND_OVERRUN;