/src/lzo-2.10/src/lzo2a_9x.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* lzo2a_9x.c -- implementation of the LZO2A-999 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 | | #include "config2a.h" |
31 | | |
32 | | |
33 | | /*********************************************************************** |
34 | | // |
35 | | ************************************************************************/ |
36 | | |
37 | 4.51M | #define SWD_THRESHOLD 1 /* lower limit for match length */ |
38 | 821 | #define SWD_F 2048 /* upper limit for match length */ |
39 | | |
40 | | |
41 | | #define LZO2A 1 |
42 | 1.64k | #define LZO_COMPRESS_T lzo2a_999_t |
43 | 821 | #define lzo_swd_t lzo2a_999_swd_t |
44 | | #include "lzo_mchw.ch" |
45 | | |
46 | | |
47 | | #if (LZO_CC_BORLANDC && LZO_MM_FLAT) |
48 | | # if ((__BORLANDC__) >= 0x0450 && (__BORLANDC__) < 0x0460) |
49 | | /* avoid internal compiler error */ |
50 | | # pragma option -Od |
51 | | # endif |
52 | | #endif |
53 | | |
54 | | |
55 | | /*********************************************************************** |
56 | | // |
57 | | ************************************************************************/ |
58 | | |
59 | 4.19M | #define putbyte(x) *op++ = LZO_BYTE(x) |
60 | | |
61 | | #define putbits(j,x) \ |
62 | 4.87M | if (k == 0) bitp = op++; \ |
63 | 4.87M | SETBITS(j,x); \ |
64 | 4.87M | if (k >= 8) { *bitp = LZO_BYTE(MASKBITS(8)); DUMPBITS(8); \ |
65 | 654k | if (k > 0) bitp = op++; } |
66 | | |
67 | 4.51M | #define putbit(x) putbits(1,x) |
68 | | |
69 | | |
70 | | /*********************************************************************** |
71 | | // this is a public function, but there is no prototype in a header file |
72 | | ************************************************************************/ |
73 | | |
74 | | LZO_EXTERN(int) |
75 | | lzo2a_999_compress_callback ( const lzo_bytep in , lzo_uint in_len, |
76 | | lzo_bytep out, lzo_uintp out_len, |
77 | | lzo_voidp wrkmem, |
78 | | lzo_callback_p cb, |
79 | | lzo_uint max_chain ); |
80 | | |
81 | | LZO_PUBLIC(int) |
82 | | lzo2a_999_compress_callback ( const lzo_bytep in , lzo_uint in_len, |
83 | | lzo_bytep out, lzo_uintp out_len, |
84 | | lzo_voidp wrkmem, |
85 | | lzo_callback_p cb, |
86 | | lzo_uint max_chain ) |
87 | 821 | { |
88 | 821 | lzo_bytep op; |
89 | 821 | lzo_bytep bitp = 0; |
90 | 821 | lzo_uint m_len, m_off; |
91 | 821 | LZO_COMPRESS_T cc; |
92 | 821 | LZO_COMPRESS_T * const c = &cc; |
93 | 821 | lzo_swd_p const swd = (lzo_swd_p) wrkmem; |
94 | 821 | int r; |
95 | | |
96 | 821 | lzo_uint32_t b = 0; /* bit buffer */ |
97 | 821 | unsigned k = 0; /* bits in bit buffer */ |
98 | | |
99 | | /* sanity check */ |
100 | 821 | LZO_COMPILE_TIME_ASSERT(LZO2A_999_MEM_COMPRESS >= SIZEOF_LZO_SWD_T) |
101 | | |
102 | 821 | c->init = 0; |
103 | 821 | c->ip = c->in = in; |
104 | 821 | c->in_end = in + in_len; |
105 | 821 | c->cb = cb; |
106 | 821 | c->m1 = c->m2 = c->m3 = c->m4 = 0; |
107 | | |
108 | 821 | op = out; |
109 | | |
110 | 821 | r = init_match(c,swd,NULL,0,0); |
111 | 821 | if (r != 0) |
112 | 0 | return r; |
113 | 821 | if (max_chain > 0) |
114 | 0 | swd->max_chain = max_chain; |
115 | | |
116 | 821 | r = find_match(c,swd,0,0); |
117 | 821 | if (r != 0) |
118 | 0 | return r; |
119 | 4.08M | while (c->look > 0) |
120 | 4.08M | { |
121 | 4.08M | lzo_uint lazy_match_min_gain = 0; |
122 | | #if (SWD_N >= 8192) |
123 | | lzo_uint extra1 = 0; |
124 | | #endif |
125 | 4.08M | lzo_uint extra2 = 0; |
126 | 4.08M | lzo_uint ahead = 0; |
127 | | |
128 | 4.08M | m_len = c->m_len; |
129 | 4.08M | m_off = c->m_off; |
130 | | |
131 | | #if (SWD_N >= 8192) |
132 | | if (m_off >= 8192) |
133 | | { |
134 | | if (m_len < M3_MIN_LEN) |
135 | | m_len = 0; |
136 | | else |
137 | | lazy_match_min_gain = 1; |
138 | | } |
139 | | else |
140 | | #endif |
141 | 4.08M | if (m_len >= M1_MIN_LEN && m_len <= M1_MAX_LEN && m_off <= 256) |
142 | 369k | { |
143 | 369k | lazy_match_min_gain = 2; |
144 | | #if (SWD_N >= 8192) |
145 | | extra1 = 3; |
146 | | #endif |
147 | 369k | extra2 = 2; |
148 | 369k | } |
149 | 3.71M | else if (m_len >= 10) |
150 | 29.5k | lazy_match_min_gain = 1; |
151 | 3.68M | else if (m_len >= 3) |
152 | 47.8k | { |
153 | 47.8k | lazy_match_min_gain = 1; |
154 | | #if (SWD_N >= 8192) |
155 | | extra1 = 1; |
156 | | #endif |
157 | 47.8k | } |
158 | 3.63M | else |
159 | 3.63M | m_len = 0; |
160 | | |
161 | | |
162 | | /* try a lazy match */ |
163 | 4.08M | if (lazy_match_min_gain > 0 && c->look > m_len) |
164 | 446k | { |
165 | 446k | unsigned char lit = LZO_BYTE(swd->b_char); |
166 | | |
167 | 446k | r = find_match(c,swd,1,0); |
168 | 446k | assert(r == 0); LZO_UNUSED(r); |
169 | 446k | assert(c->look > 0); |
170 | | |
171 | | #if (SWD_N >= 8192) |
172 | | if (m_off < 8192 && c->m_off >= 8192) |
173 | | lazy_match_min_gain += extra1; |
174 | | else |
175 | | #endif |
176 | 446k | if (m_len >= M1_MIN_LEN && m_len <= M1_MAX_LEN && m_off <= 256) |
177 | 369k | { |
178 | 369k | if (!(c->m_len >= M1_MIN_LEN && |
179 | 369k | c->m_len <= M1_MAX_LEN && c->m_off <= 256)) |
180 | 326k | lazy_match_min_gain += extra2; |
181 | 369k | } |
182 | 446k | if (c->m_len >= M1_MIN_LEN && |
183 | 446k | c->m_len <= M1_MAX_LEN && c->m_off <= 256) |
184 | 52.4k | { |
185 | 52.4k | lazy_match_min_gain -= 1; |
186 | 52.4k | } |
187 | | |
188 | 446k | if ((lzo_int) lazy_match_min_gain < 1) |
189 | 9.62k | lazy_match_min_gain = 1; |
190 | | |
191 | 446k | if (c->m_len >= m_len + lazy_match_min_gain) |
192 | 19.4k | { |
193 | 19.4k | c->lazy++; |
194 | | #if !defined(NDEBUG) |
195 | | m_len = c->m_len; |
196 | | m_off = c->m_off; |
197 | | assert(lzo_memcmp(c->ip - c->look, c->ip - c->look - m_off, |
198 | | m_len) == 0); |
199 | | assert(m_len >= 3 || (m_len >= 2 && m_off <= 256)); |
200 | | #endif |
201 | | /* code literal */ |
202 | 19.4k | putbit(0); |
203 | 19.4k | putbyte(lit); |
204 | 19.4k | c->lit_bytes++; |
205 | 19.4k | continue; |
206 | 19.4k | } |
207 | 427k | else |
208 | 427k | ahead = 1; |
209 | 427k | assert(m_len > 0); |
210 | 427k | } |
211 | | |
212 | | |
213 | 4.06M | if (m_len == 0) |
214 | 3.63M | { |
215 | | /* a literal */ |
216 | 3.63M | putbit(0); |
217 | 3.63M | putbyte(swd->b_char); |
218 | 3.63M | c->lit_bytes++; |
219 | 3.63M | r = find_match(c,swd,1,0); |
220 | 3.63M | assert(r == 0); LZO_UNUSED(r); |
221 | 3.63M | } |
222 | 427k | else |
223 | 427k | { |
224 | 427k | assert(m_len >= M1_MIN_LEN); |
225 | 427k | assert(m_off > 0); |
226 | 427k | assert(m_off <= SWD_N); |
227 | | |
228 | | /* 2 - code match */ |
229 | 427k | if (m_len >= M1_MIN_LEN && m_len <= M1_MAX_LEN && m_off <= 256) |
230 | 362k | { |
231 | 362k | putbit(1); |
232 | 362k | putbit(0); |
233 | 362k | putbits(2,m_len - M1_MIN_LEN); |
234 | 362k | putbyte(m_off - 1); |
235 | 362k | c->m1++; |
236 | 362k | } |
237 | | #if (SWD_N >= 8192) |
238 | | else if (m_off >= 8192) |
239 | | { |
240 | | unsigned len = m_len; |
241 | | assert(m_len >= M3_MIN_LEN); |
242 | | putbit(1); |
243 | | putbit(1); |
244 | | putbyte(m_off & 31); |
245 | | putbyte(m_off >> 5); |
246 | | putbit(1); |
247 | | len -= M3_MIN_LEN - 1; |
248 | | while (len > 255) |
249 | | { |
250 | | len -= 255; |
251 | | putbyte(0); |
252 | | } |
253 | | putbyte(len); |
254 | | c->m4++; |
255 | | } |
256 | | #endif |
257 | 64.6k | else |
258 | 64.6k | { |
259 | 64.6k | assert(m_len >= 3); |
260 | | |
261 | 64.6k | putbit(1); |
262 | 64.6k | putbit(1); |
263 | 64.6k | if (m_len <= 9) |
264 | 38.2k | { |
265 | 38.2k | putbyte(((m_len - 2) << 5) | (m_off & 31)); |
266 | 38.2k | putbyte(m_off >> 5); |
267 | 38.2k | c->m2++; |
268 | 38.2k | } |
269 | 26.4k | else |
270 | 26.4k | { |
271 | 26.4k | lzo_uint len = m_len; |
272 | 26.4k | putbyte(m_off & 31); |
273 | 26.4k | putbyte(m_off >> 5); |
274 | | #if (SWD_N >= 8192) |
275 | | putbit(0); |
276 | | #endif |
277 | 26.4k | len -= 10 - 1; |
278 | 47.3k | while (len > 255) |
279 | 20.8k | { |
280 | 20.8k | len -= 255; |
281 | 20.8k | putbyte(0); |
282 | 20.8k | } |
283 | 26.4k | putbyte(len); |
284 | 26.4k | c->m3++; |
285 | 26.4k | } |
286 | 64.6k | } |
287 | 427k | r = find_match(c,swd,m_len,1+ahead); |
288 | 427k | assert(r == 0); LZO_UNUSED(r); |
289 | 427k | } |
290 | | |
291 | 4.06M | c->codesize = pd(op, out); |
292 | 4.06M | } |
293 | | |
294 | 821 | #if defined(LZO_EOF_CODE) |
295 | | /* code EOF code */ |
296 | 821 | putbit(1); |
297 | 821 | putbit(1); |
298 | 821 | putbyte(1 << 5); |
299 | 821 | putbyte(0); |
300 | 821 | #endif |
301 | | |
302 | | /* flush remaining bits */ |
303 | 821 | assert(k < CHAR_BIT); |
304 | 821 | if (k > 0) |
305 | 718 | { |
306 | 718 | assert(b == MASKBITS(k)); |
307 | 718 | assert(op - bitp > 1); |
308 | 718 | *bitp = LZO_BYTE(MASKBITS(k)); |
309 | 718 | DUMPBITS(k); |
310 | 718 | assert(b == 0); |
311 | 718 | assert(k == 0); |
312 | 718 | } |
313 | | |
314 | 821 | assert(c->textsize == in_len); |
315 | 821 | c->codesize = pd(op, out); |
316 | | |
317 | 821 | *out_len = pd(op, out); |
318 | | |
319 | 821 | if (c->cb && c->cb->nprogress) |
320 | 0 | (*c->cb->nprogress)(c->cb, c->textsize, c->codesize, 0); |
321 | | |
322 | | #if 0 |
323 | | printf("%ld -> %ld: %ld %ld %ld %ld %ld %ld\n", |
324 | | (long) c->textsize, (long) c->codesize, |
325 | | c->lit_bytes, c->m1, c->m2, c->m3, c->m4, c->lazy); |
326 | | #endif |
327 | 821 | return LZO_E_OK; |
328 | 821 | } |
329 | | |
330 | | |
331 | | |
332 | | /*********************************************************************** |
333 | | // |
334 | | ************************************************************************/ |
335 | | |
336 | | LZO_PUBLIC(int) |
337 | | lzo2a_999_compress ( const lzo_bytep in , lzo_uint in_len, |
338 | | lzo_bytep out, lzo_uintp out_len, |
339 | | lzo_voidp wrkmem ) |
340 | 821 | { |
341 | 821 | return lzo2a_999_compress_callback(in,in_len,out,out_len,wrkmem, |
342 | 821 | (lzo_callback_p) 0, 0); |
343 | 821 | } |
344 | | |
345 | | |
346 | | /* vim:set ts=4 sw=4 et: */ |