/src/lzo-2.10/src/lzo1x_c.ch
Line | Count | Source (jump to first uncovered line) |
1 | | /* lzo1x_c.ch -- implementation of the LZO1[XY]-1 compression algorithm |
2 | | |
3 | | This file is part of the LZO real-time data compression library. |
4 | | |
5 | | Copyright (C) 1996-2017 Markus Franz Xaver Johannes Oberhumer |
6 | | All Rights Reserved. |
7 | | |
8 | | The LZO library is free software; you can redistribute it and/or |
9 | | modify it under the terms of the GNU General Public License as |
10 | | published by the Free Software Foundation; either version 2 of |
11 | | the License, or (at your option) any later version. |
12 | | |
13 | | The LZO library is distributed in the hope that it will be useful, |
14 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | | GNU General Public License for more details. |
17 | | |
18 | | You should have received a copy of the GNU General Public License |
19 | | along with the LZO library; see the file COPYING. |
20 | | If not, write to the Free Software Foundation, Inc., |
21 | | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
22 | | |
23 | | Markus F.X.J. Oberhumer |
24 | | <markus@oberhumer.com> |
25 | | http://www.oberhumer.com/opensource/lzo/ |
26 | | */ |
27 | | |
28 | | |
29 | | |
30 | | #if 1 && defined(DO_COMPRESS) && !defined(do_compress) |
31 | | /* choose a unique name to better help PGO optimizations */ |
32 | 1.98k | # define do_compress LZO_PP_ECONCAT2(DO_COMPRESS,_core) |
33 | | #endif |
34 | | |
35 | | |
36 | | /*********************************************************************** |
37 | | // compress a block of data. |
38 | | ************************************************************************/ |
39 | | |
40 | | static __lzo_noinline lzo_uint |
41 | | do_compress ( const lzo_bytep in , lzo_uint in_len, |
42 | | lzo_bytep out, lzo_uintp out_len, |
43 | | lzo_uint ti, lzo_voidp wrkmem) |
44 | 1.98k | { |
45 | 1.98k | const lzo_bytep ip; |
46 | 1.98k | lzo_bytep op; |
47 | 1.98k | const lzo_bytep const in_end = in + in_len; |
48 | 1.98k | const lzo_bytep const ip_end = in + in_len - 20; |
49 | 1.98k | const lzo_bytep ii; |
50 | 1.98k | lzo_dict_p const dict = (lzo_dict_p) wrkmem; |
51 | | |
52 | 1.98k | op = out; |
53 | 1.98k | ip = in; |
54 | 1.98k | ii = ip; |
55 | | |
56 | 1.98k | ip += ti < 4 ? 4 - ti : 0; |
57 | 1.98k | for (;;) |
58 | 1.98k | { |
59 | 1.98k | const lzo_bytep m_pos; |
60 | | #if !(LZO_DETERMINISTIC) |
61 | | LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0); |
62 | | lzo_uint m_len; |
63 | | lzo_uint dindex; |
64 | | next: |
65 | | if __lzo_unlikely(ip >= ip_end) |
66 | | break; |
67 | | DINDEX1(dindex,ip); |
68 | | GINDEX(m_pos,m_off,dict,dindex,in); |
69 | | if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) |
70 | | goto literal; |
71 | | #if 1 |
72 | | if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) |
73 | | goto try_match; |
74 | | DINDEX2(dindex,ip); |
75 | | #endif |
76 | | GINDEX(m_pos,m_off,dict,dindex,in); |
77 | | if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET)) |
78 | | goto literal; |
79 | | if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3]) |
80 | | goto try_match; |
81 | | goto literal; |
82 | | |
83 | | try_match: |
84 | | #if (LZO_OPT_UNALIGNED32) |
85 | | if (UA_GET_NE32(m_pos) != UA_GET_NE32(ip)) |
86 | | #else |
87 | | if (m_pos[0] != ip[0] || m_pos[1] != ip[1] || m_pos[2] != ip[2] || m_pos[3] != ip[3]) |
88 | | #endif |
89 | | { |
90 | | /* a literal */ |
91 | | literal: |
92 | | UPDATE_I(dict,0,dindex,ip,in); |
93 | | ip += 1 + ((ip - ii) >> 5); |
94 | | continue; |
95 | | } |
96 | | /*match:*/ |
97 | | UPDATE_I(dict,0,dindex,ip,in); |
98 | | #else |
99 | 1.98k | lzo_uint m_off; |
100 | 1.98k | lzo_uint m_len; |
101 | 1.98k | { |
102 | 1.98k | lzo_uint32_t dv; |
103 | 1.98k | lzo_uint dindex; |
104 | 1.42M | literal: |
105 | 1.42M | ip += 1 + ((ip - ii) >> 5); |
106 | 1.59M | next: |
107 | 1.59M | if __lzo_unlikely(ip >= ip_end) |
108 | 1.98k | break; |
109 | 1.59M | dv = UA_GET_LE32(ip); |
110 | 1.59M | dindex = DINDEX(dv,ip); |
111 | 1.59M | GINDEX(m_off,m_pos,in+dict,dindex,in); |
112 | 1.59M | UPDATE_I(dict,0,dindex,ip,in); |
113 | 1.59M | if __lzo_unlikely(dv != UA_GET_LE32(m_pos)) |
114 | 1.42M | goto literal; |
115 | 1.59M | } |
116 | 176k | #endif |
117 | | |
118 | | /* a match */ |
119 | | |
120 | 176k | ii -= ti; ti = 0; |
121 | 176k | { |
122 | 176k | lzo_uint t = pd(ip,ii); |
123 | 176k | if (t != 0) |
124 | 95.5k | { |
125 | 95.5k | if (t <= 3) |
126 | 45.7k | { |
127 | 45.7k | op[-2] = LZO_BYTE(op[-2] | t); |
128 | 45.7k | #if (LZO_OPT_UNALIGNED32) |
129 | 45.7k | UA_COPY4(op, ii); |
130 | 45.7k | op += t; |
131 | | #else |
132 | | { do *op++ = *ii++; while (--t > 0); } |
133 | | #endif |
134 | 45.7k | } |
135 | 49.8k | #if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64) |
136 | 49.8k | else if (t <= 16) |
137 | 32.3k | { |
138 | 32.3k | *op++ = LZO_BYTE(t - 3); |
139 | 32.3k | UA_COPY8(op, ii); |
140 | 32.3k | UA_COPY8(op+8, ii+8); |
141 | 32.3k | op += t; |
142 | 32.3k | } |
143 | 17.5k | #endif |
144 | 17.5k | else |
145 | 17.5k | { |
146 | 17.5k | if (t <= 18) |
147 | 2.06k | *op++ = LZO_BYTE(t - 3); |
148 | 15.4k | else |
149 | 15.4k | { |
150 | 15.4k | lzo_uint tt = t - 18; |
151 | 15.4k | *op++ = 0; |
152 | 99.2k | while __lzo_unlikely(tt > 255) |
153 | 83.7k | { |
154 | 83.7k | tt -= 255; |
155 | 83.7k | UA_SET1(op, 0); |
156 | 83.7k | op++; |
157 | 83.7k | } |
158 | 15.4k | assert(tt > 0); |
159 | 15.4k | *op++ = LZO_BYTE(tt); |
160 | 15.4k | } |
161 | 17.5k | #if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64) |
162 | 1.39M | do { |
163 | 1.39M | UA_COPY8(op, ii); |
164 | 1.39M | UA_COPY8(op+8, ii+8); |
165 | 1.39M | op += 16; ii += 16; t -= 16; |
166 | 1.39M | } while (t >= 16); if (t > 0) |
167 | 15.9k | #endif |
168 | 108k | { do *op++ = *ii++; while (--t > 0); } |
169 | 17.5k | } |
170 | 95.5k | } |
171 | 176k | } |
172 | 176k | m_len = 4; |
173 | 176k | { |
174 | 176k | #if (LZO_OPT_UNALIGNED64) |
175 | 176k | lzo_uint64_t v; |
176 | 176k | v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len); |
177 | 176k | if __lzo_unlikely(v == 0) { |
178 | 1.21M | do { |
179 | 1.21M | m_len += 8; |
180 | 1.21M | v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len); |
181 | 1.21M | if __lzo_unlikely(ip + m_len >= ip_end) |
182 | 321 | goto m_len_done; |
183 | 1.21M | } while (v == 0); |
184 | 70.2k | } |
185 | | #if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz64) |
186 | | m_len += lzo_bitops_ctlz64(v) / CHAR_BIT; |
187 | | #elif (LZO_ABI_BIG_ENDIAN) |
188 | | if ((v >> (64 - CHAR_BIT)) == 0) do { |
189 | | v <<= CHAR_BIT; |
190 | | m_len += 1; |
191 | | } while ((v >> (64 - CHAR_BIT)) == 0); |
192 | | #elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz64) |
193 | 176k | m_len += lzo_bitops_cttz64(v) / CHAR_BIT; |
194 | | #elif (LZO_ABI_LITTLE_ENDIAN) |
195 | | if ((v & UCHAR_MAX) == 0) do { |
196 | | v >>= CHAR_BIT; |
197 | | m_len += 1; |
198 | | } while ((v & UCHAR_MAX) == 0); |
199 | | #else |
200 | | if (ip[m_len] == m_pos[m_len]) do { |
201 | | m_len += 1; |
202 | | } while (ip[m_len] == m_pos[m_len]); |
203 | | #endif |
204 | | #elif (LZO_OPT_UNALIGNED32) |
205 | | lzo_uint32_t v; |
206 | | v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); |
207 | | if __lzo_unlikely(v == 0) { |
208 | | do { |
209 | | m_len += 4; |
210 | | v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); |
211 | | if (v != 0) |
212 | | break; |
213 | | m_len += 4; |
214 | | v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len); |
215 | | if __lzo_unlikely(ip + m_len >= ip_end) |
216 | | goto m_len_done; |
217 | | } while (v == 0); |
218 | | } |
219 | | #if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz32) |
220 | | m_len += lzo_bitops_ctlz32(v) / CHAR_BIT; |
221 | | #elif (LZO_ABI_BIG_ENDIAN) |
222 | | if ((v >> (32 - CHAR_BIT)) == 0) do { |
223 | | v <<= CHAR_BIT; |
224 | | m_len += 1; |
225 | | } while ((v >> (32 - CHAR_BIT)) == 0); |
226 | | #elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz32) |
227 | | m_len += lzo_bitops_cttz32(v) / CHAR_BIT; |
228 | | #elif (LZO_ABI_LITTLE_ENDIAN) |
229 | | if ((v & UCHAR_MAX) == 0) do { |
230 | | v >>= CHAR_BIT; |
231 | | m_len += 1; |
232 | | } while ((v & UCHAR_MAX) == 0); |
233 | | #else |
234 | | if (ip[m_len] == m_pos[m_len]) do { |
235 | | m_len += 1; |
236 | | } while (ip[m_len] == m_pos[m_len]); |
237 | | #endif |
238 | | #else |
239 | | if __lzo_unlikely(ip[m_len] == m_pos[m_len]) { |
240 | | do { |
241 | | m_len += 1; |
242 | | if (ip[m_len] != m_pos[m_len]) |
243 | | break; |
244 | | m_len += 1; |
245 | | if (ip[m_len] != m_pos[m_len]) |
246 | | break; |
247 | | m_len += 1; |
248 | | if (ip[m_len] != m_pos[m_len]) |
249 | | break; |
250 | | m_len += 1; |
251 | | if (ip[m_len] != m_pos[m_len]) |
252 | | break; |
253 | | m_len += 1; |
254 | | if (ip[m_len] != m_pos[m_len]) |
255 | | break; |
256 | | m_len += 1; |
257 | | if (ip[m_len] != m_pos[m_len]) |
258 | | break; |
259 | | m_len += 1; |
260 | | if (ip[m_len] != m_pos[m_len]) |
261 | | break; |
262 | | m_len += 1; |
263 | | if __lzo_unlikely(ip + m_len >= ip_end) |
264 | | goto m_len_done; |
265 | | } while (ip[m_len] == m_pos[m_len]); |
266 | | } |
267 | | #endif |
268 | 176k | } |
269 | 176k | m_len_done: |
270 | 176k | m_off = pd(ip,m_pos); |
271 | 176k | ip += m_len; |
272 | 176k | ii = ip; |
273 | 176k | if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) |
274 | 64.6k | { |
275 | 64.6k | m_off -= 1; |
276 | 64.6k | #if defined(LZO1X) |
277 | 64.6k | *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2)); |
278 | 64.6k | *op++ = LZO_BYTE(m_off >> 3); |
279 | | #elif defined(LZO1Y) |
280 | | *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2)); |
281 | | *op++ = LZO_BYTE(m_off >> 2); |
282 | | #endif |
283 | 64.6k | } |
284 | 112k | else if (m_off <= M3_MAX_OFFSET) |
285 | 98.1k | { |
286 | 98.1k | m_off -= 1; |
287 | 98.1k | if (m_len <= M3_MAX_LEN) |
288 | 68.8k | *op++ = LZO_BYTE(M3_MARKER | (m_len - 2)); |
289 | 29.3k | else |
290 | 29.3k | { |
291 | 29.3k | m_len -= M3_MAX_LEN; |
292 | 29.3k | *op++ = M3_MARKER | 0; |
293 | 47.6k | while __lzo_unlikely(m_len > 255) |
294 | 18.3k | { |
295 | 18.3k | m_len -= 255; |
296 | 18.3k | UA_SET1(op, 0); |
297 | 18.3k | op++; |
298 | 18.3k | } |
299 | 29.3k | *op++ = LZO_BYTE(m_len); |
300 | 29.3k | } |
301 | 98.1k | *op++ = LZO_BYTE(m_off << 2); |
302 | 98.1k | *op++ = LZO_BYTE(m_off >> 6); |
303 | 98.1k | } |
304 | 14.1k | else |
305 | 14.1k | { |
306 | 14.1k | m_off -= 0x4000; |
307 | 14.1k | if (m_len <= M4_MAX_LEN) |
308 | 6.15k | *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8) | (m_len - 2)); |
309 | 7.95k | else |
310 | 7.95k | { |
311 | 7.95k | m_len -= M4_MAX_LEN; |
312 | 7.95k | *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8)); |
313 | 14.2k | while __lzo_unlikely(m_len > 255) |
314 | 6.28k | { |
315 | 6.28k | m_len -= 255; |
316 | 6.28k | UA_SET1(op, 0); |
317 | 6.28k | op++; |
318 | 6.28k | } |
319 | 7.95k | *op++ = LZO_BYTE(m_len); |
320 | 7.95k | } |
321 | 14.1k | *op++ = LZO_BYTE(m_off << 2); |
322 | 14.1k | *op++ = LZO_BYTE(m_off >> 6); |
323 | 14.1k | } |
324 | 176k | goto next; |
325 | 176k | } |
326 | | |
327 | 1.98k | *out_len = pd(op, out); |
328 | 1.98k | return pd(in_end,ii-ti); |
329 | 1.98k | } |
330 | | |
331 | | |
332 | | /*********************************************************************** |
333 | | // public entry point |
334 | | ************************************************************************/ |
335 | | |
336 | | LZO_PUBLIC(int) |
337 | | DO_COMPRESS ( const lzo_bytep in , lzo_uint in_len, |
338 | | lzo_bytep out, lzo_uintp out_len, |
339 | | lzo_voidp wrkmem ) |
340 | 910 | { |
341 | 910 | const lzo_bytep ip = in; |
342 | 910 | lzo_bytep op = out; |
343 | 910 | lzo_uint l = in_len; |
344 | 910 | lzo_uint t = 0; |
345 | | |
346 | 2.89k | while (l > 20) |
347 | 1.98k | { |
348 | 1.98k | lzo_uint ll = l; |
349 | 1.98k | lzo_uintptr_t ll_end; |
350 | 1.98k | #if 0 || (LZO_DETERMINISTIC) |
351 | 1.98k | ll = LZO_MIN(ll, 49152); |
352 | 1.98k | #endif |
353 | 1.98k | ll_end = (lzo_uintptr_t)ip + ll; |
354 | 1.98k | if ((ll_end + ((t + ll) >> 5)) <= ll_end || (const lzo_bytep)(ll_end + ((t + ll) >> 5)) <= ip + ll) |
355 | 7 | break; |
356 | 1.98k | #if (LZO_DETERMINISTIC) |
357 | 1.98k | lzo_memset(wrkmem, 0, ((lzo_uint)1 << D_BITS) * sizeof(lzo_dict_t)); |
358 | 1.98k | #endif |
359 | 1.98k | t = do_compress(ip,ll,op,out_len,t,wrkmem); |
360 | 1.98k | ip += ll; |
361 | 1.98k | op += *out_len; |
362 | 1.98k | l -= ll; |
363 | 1.98k | } |
364 | 910 | t += l; |
365 | | |
366 | 910 | if (t > 0) |
367 | 910 | { |
368 | 910 | const lzo_bytep ii = in + in_len - t; |
369 | | |
370 | 910 | if (op == out && t <= 238) |
371 | 43 | *op++ = LZO_BYTE(17 + t); |
372 | 867 | else if (t <= 3) |
373 | 0 | op[-2] = LZO_BYTE(op[-2] | t); |
374 | 867 | else if (t <= 18) |
375 | 527 | *op++ = LZO_BYTE(t - 3); |
376 | 340 | else |
377 | 340 | { |
378 | 340 | lzo_uint tt = t - 18; |
379 | | |
380 | 340 | *op++ = 0; |
381 | 105k | while (tt > 255) |
382 | 104k | { |
383 | 104k | tt -= 255; |
384 | 104k | UA_SET1(op, 0); |
385 | 104k | op++; |
386 | 104k | } |
387 | 340 | assert(tt > 0); |
388 | 340 | *op++ = LZO_BYTE(tt); |
389 | 340 | } |
390 | 910 | UA_COPYN(op, ii, t); |
391 | 910 | op += t; |
392 | 910 | } |
393 | | |
394 | 910 | *op++ = M4_MARKER | 1; |
395 | 910 | *op++ = 0; |
396 | 910 | *op++ = 0; |
397 | | |
398 | 910 | *out_len = pd(op, out); |
399 | 910 | return LZO_E_OK; |
400 | 910 | } |
401 | | |
402 | | |
403 | | /* vim:set ts=4 sw=4 et: */ |