1 /* lzo1x_c.ch -- implementation of the LZO1[XY]-1 compression algorithm
3 This file is part of the LZO real-time data compression library.
5 Copyright (C) 2011 Markus Franz Xaver Johannes Oberhumer
6 Copyright (C) 2010 Markus Franz Xaver Johannes Oberhumer
7 Copyright (C) 2009 Markus Franz Xaver Johannes Oberhumer
8 Copyright (C) 2008 Markus Franz Xaver Johannes Oberhumer
9 Copyright (C) 2007 Markus Franz Xaver Johannes Oberhumer
10 Copyright (C) 2006 Markus Franz Xaver Johannes Oberhumer
11 Copyright (C) 2005 Markus Franz Xaver Johannes Oberhumer
12 Copyright (C) 2004 Markus Franz Xaver Johannes Oberhumer
13 Copyright (C) 2003 Markus Franz Xaver Johannes Oberhumer
14 Copyright (C) 2002 Markus Franz Xaver Johannes Oberhumer
15 Copyright (C) 2001 Markus Franz Xaver Johannes Oberhumer
16 Copyright (C) 2000 Markus Franz Xaver Johannes Oberhumer
17 Copyright (C) 1999 Markus Franz Xaver Johannes Oberhumer
18 Copyright (C) 1998 Markus Franz Xaver Johannes Oberhumer
19 Copyright (C) 1997 Markus Franz Xaver Johannes Oberhumer
20 Copyright (C) 1996 Markus Franz Xaver Johannes Oberhumer
23 The LZO library is free software; you can redistribute it and/or
24 modify it under the terms of the GNU General Public License as
25 published by the Free Software Foundation; either version 2 of
26 the License, or (at your option) any later version.
28 The LZO library is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU General Public License for more details.
33 You should have received a copy of the GNU General Public License
34 along with the LZO library; see the file COPYING.
35 If not, write to the Free Software Foundation, Inc.,
36 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
38 Markus F.X.J. Oberhumer
39 <markus@oberhumer.com>
40 http://www.oberhumer.com/opensource/lzo/
45 #if 1 && defined(DO_COMPRESS) && !defined(do_compress)
46 /* choose a unique name to better help PGO optimizations */
47 # define do_compress LZO_CPP_ECONCAT2(DO_COMPRESS,_core)
50 #if defined(UA_GET64) && (LZO_ABI_BIG_ENDIAN)
51 # define WANT_lzo_bitops_clz64 1
52 #elif defined(UA_GET64) && (LZO_ABI_LITTLE_ENDIAN)
53 # define WANT_lzo_bitops_ctz64 1
54 #elif defined(UA_GET32) && (LZO_ABI_BIG_ENDIAN)
55 # define WANT_lzo_bitops_clz32 1
56 #elif defined(UA_GET32) && (LZO_ABI_LITTLE_ENDIAN)
57 # define WANT_lzo_bitops_ctz32 1
59 #include "lzo_func.ch"
62 /***********************************************************************
63 // compress a block of data.
64 ************************************************************************/
66 static __lzo_noinline lzo_uint
67 do_compress ( const lzo_bytep in , lzo_uint in_len,
68 lzo_bytep out, lzo_uintp out_len,
69 lzo_uint ti, lzo_voidp wrkmem)
71 register const lzo_bytep ip;
73 const lzo_bytep const in_end = in + in_len;
74 const lzo_bytep const ip_end = in + in_len - 20;
76 lzo_dict_p const dict = (lzo_dict_p) wrkmem;
82 ip += ti < 4 ? 4 - ti : 0;
85 const lzo_bytep m_pos;
86 #if !(LZO_DETERMINISTIC)
87 LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0);
91 if __lzo_unlikely(ip >= ip_end)
94 GINDEX(m_pos,m_off,dict,dindex,in);
95 if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET))
98 if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
102 GINDEX(m_pos,m_off,dict,dindex,in);
103 if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET))
105 if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
110 #if defined(UA_GET32)
111 if (UA_GET32(m_pos) != UA_GET32(ip))
113 if (m_pos[0] != ip[0] || m_pos[1] != ip[1] || m_pos[2] != ip[2] || m_pos[3] != ip[3])
118 UPDATE_I(dict,0,dindex,ip,in);
119 ip += 1 + ((ip - ii) >> 5);
123 UPDATE_I(dict,0,dindex,ip,in);
131 ip += 1 + ((ip - ii) >> 5);
133 if __lzo_unlikely(ip >= ip_end)
136 dindex = DINDEX(dv,ip);
137 GINDEX(m_off,m_pos,in+dict,dindex,in);
138 UPDATE_I(dict,0,dindex,ip,in);
139 if __lzo_unlikely(dv != UA_GET32(m_pos))
148 register lzo_uint t = pd(ip,ii);
153 op[-2] |= LZO_BYTE(t);
154 #if defined(UA_COPY32)
158 { do *op++ = *ii++; while (--t > 0); }
161 #if defined(UA_COPY32) || defined(UA_COPY64)
164 *op++ = LZO_BYTE(t - 3);
165 #if defined(UA_COPY64)
167 UA_COPY64(op+8, ii+8);
170 UA_COPY32(op+4, ii+4);
171 UA_COPY32(op+8, ii+8);
172 UA_COPY32(op+12, ii+12);
180 *op++ = LZO_BYTE(t - 3);
183 register lzo_uint tt = t - 18;
185 while __lzo_unlikely(tt > 255)
188 #if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400))
189 * (volatile unsigned char *) op++ = 0;
195 *op++ = LZO_BYTE(tt);
197 #if defined(UA_COPY32) || defined(UA_COPY64)
199 #if defined(UA_COPY64)
201 UA_COPY64(op+8, ii+8);
204 UA_COPY32(op+4, ii+4);
205 UA_COPY32(op+8, ii+8);
206 UA_COPY32(op+12, ii+12);
208 op += 16; ii += 16; t -= 16;
209 } while (t >= 16); if (t > 0)
211 { do *op++ = *ii++; while (--t > 0); }
217 #if defined(UA_GET64)
219 v = UA_GET64(ip + m_len) ^ UA_GET64(m_pos + m_len);
220 if __lzo_unlikely(v == 0) {
223 v = UA_GET64(ip + m_len) ^ UA_GET64(m_pos + m_len);
224 if __lzo_unlikely(ip + m_len >= ip_end)
228 #if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_clz64)
229 m_len += lzo_bitops_clz64(v) / CHAR_BIT;
230 #elif (LZO_ABI_BIG_ENDIAN)
231 if ((v >> (64 - CHAR_BIT)) == 0) do {
234 } while ((v >> (64 - CHAR_BIT)) == 0);
235 #elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_ctz64)
236 m_len += lzo_bitops_ctz64(v) / CHAR_BIT;
237 #elif (LZO_ABI_LITTLE_ENDIAN)
238 if ((v & UCHAR_MAX) == 0) do {
241 } while ((v & UCHAR_MAX) == 0);
243 if (ip[m_len] == m_pos[m_len]) do {
245 } while (ip[m_len] == m_pos[m_len]);
247 #elif defined(UA_GET32)
249 v = UA_GET32(ip + m_len) ^ UA_GET32(m_pos + m_len);
250 if __lzo_unlikely(v == 0) {
253 v = UA_GET32(ip + m_len) ^ UA_GET32(m_pos + m_len);
254 if __lzo_unlikely(ip + m_len >= ip_end)
258 #if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_clz32)
259 m_len += lzo_bitops_clz32(v) / CHAR_BIT;
260 #elif (LZO_ABI_BIG_ENDIAN)
261 if ((v >> (32 - CHAR_BIT)) == 0) do {
264 } while ((v >> (32 - CHAR_BIT)) == 0);
265 #elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_ctz32)
266 m_len += lzo_bitops_ctz32(v) / CHAR_BIT;
267 #elif (LZO_ABI_LITTLE_ENDIAN)
268 if ((v & UCHAR_MAX) == 0) do {
271 } while ((v & UCHAR_MAX) == 0);
273 if (ip[m_len] == m_pos[m_len]) do {
275 } while (ip[m_len] == m_pos[m_len]);
278 if __lzo_unlikely(ip[m_len] == m_pos[m_len]) {
281 if __lzo_unlikely(ip + m_len >= ip_end)
283 } while (ip[m_len] == m_pos[m_len]);
288 m_off = pd(ip,m_pos);
291 if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
295 *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2));
296 *op++ = LZO_BYTE(m_off >> 3);
298 *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2));
299 *op++ = LZO_BYTE(m_off >> 2);
302 else if (m_off <= M3_MAX_OFFSET)
305 if (m_len <= M3_MAX_LEN)
306 *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
310 *op++ = M3_MARKER | 0;
311 while __lzo_unlikely(m_len > 255)
314 #if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400))
315 * (volatile unsigned char *) op++ = 0;
320 *op++ = LZO_BYTE(m_len);
322 *op++ = LZO_BYTE(m_off << 2);
323 *op++ = LZO_BYTE(m_off >> 6);
328 if (m_len <= M4_MAX_LEN)
329 *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8) | (m_len - 2));
333 *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8));
334 while __lzo_unlikely(m_len > 255)
337 #if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400))
338 * (volatile unsigned char *) op++ = 0;
343 *op++ = LZO_BYTE(m_len);
345 *op++ = LZO_BYTE(m_off << 2);
346 *op++ = LZO_BYTE(m_off >> 6);
351 *out_len = pd(op, out);
352 return pd(in_end,ii-ti);
356 /***********************************************************************
357 // public entry point
358 ************************************************************************/
361 DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len,
362 lzo_bytep out, lzo_uintp out_len,
365 const lzo_bytep ip = in;
373 lzo_uintptr_t ll_end;
374 #if 0 || (LZO_DETERMINISTIC)
375 ll = LZO_MIN(ll, 49152);
377 ll_end = (lzo_uintptr_t)ip + ll;
378 if ((ll_end + ((t + ll) >> 5)) <= ll_end || (const lzo_bytep)(ll_end + ((t + ll) >> 5)) <= ip + ll)
380 #if (LZO_DETERMINISTIC)
381 lzo_memset(wrkmem, 0, ((lzo_uint)1 << D_BITS) * sizeof(lzo_dict_t));
383 t = do_compress(ip,ll,op,out_len,t,wrkmem);
392 const lzo_bytep ii = in + in_len - t;
394 if (op == out && t <= 238)
395 *op++ = LZO_BYTE(17 + t);
397 op[-2] |= LZO_BYTE(t);
399 *op++ = LZO_BYTE(t - 3);
402 lzo_uint tt = t - 18;
408 #if 1 && (LZO_CC_MSC && (_MSC_VER >= 1400))
409 /* prevent the compiler from transforming this loop
410 * into a memset() call */
411 * (volatile unsigned char *) op++ = 0;
417 *op++ = LZO_BYTE(tt);
419 do *op++ = *ii++; while (--t > 0);
422 *op++ = M4_MARKER | 1;
426 *out_len = pd(op, out);