lzo: update to 2.09
[tomato.git] / release / src / router / lzo / src / lzo1f_1.c
blob44a138c8100b5afc11167e90cd0f2dd0e641deda
1 /* lzo1f_1.c -- implementation of the LZO1F-1 compression algorithm
3 This file is part of the LZO real-time data compression library.
5 Copyright (C) 1996-2015 Markus Franz Xaver Johannes Oberhumer
6 All Rights Reserved.
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.
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.
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.
23 Markus F.X.J. Oberhumer
24 <markus@oberhumer.com>
25 http://www.oberhumer.com/opensource/lzo/
29 #include "lzo_conf.h"
30 #include <lzo/lzo1f.h>
33 /***********************************************************************
35 ************************************************************************/
37 #define M2_MAX_OFFSET 0x0800
38 #define M3_MAX_OFFSET 0x3fff
39 #define M3_MARKER 224
42 #ifndef LZO_HASH
43 #define LZO_HASH LZO_HASH_LZO_INCREMENTAL_A
44 #endif
45 #define D_BITS 14
46 #define D_INDEX1(d,p) d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5)
47 #define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f)
48 #include "lzo_dict.h"
51 /***********************************************************************
52 // compress a block of data.
53 ************************************************************************/
55 static __lzo_noinline
56 int do_compress ( const lzo_bytep in , lzo_uint in_len,
57 lzo_bytep out, lzo_uintp out_len,
58 lzo_voidp wrkmem )
60 const lzo_bytep ip;
61 lzo_bytep op;
62 const lzo_bytep const in_end = in + in_len;
63 const lzo_bytep const ip_end = in + in_len - 9;
64 const lzo_bytep ii;
65 lzo_dict_p const dict = (lzo_dict_p) wrkmem;
67 op = out;
68 ip = in;
69 ii = ip;
71 ip++;
72 for (;;)
74 const lzo_bytep m_pos;
75 LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0);
76 lzo_uint m_len;
77 lzo_uint dindex;
78 lzo_uint lit;
80 DINDEX1(dindex,ip);
81 GINDEX(m_pos,m_off,dict,dindex,in);
82 if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M3_MAX_OFFSET))
83 goto literal;
84 #if 1
85 if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
86 goto try_match;
87 DINDEX2(dindex,ip);
88 #endif
89 GINDEX(m_pos,m_off,dict,dindex,in);
90 if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M3_MAX_OFFSET))
91 goto literal;
92 if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
93 goto try_match;
94 goto literal;
97 try_match:
98 #if 0 && (LZO_OPT_UNALIGNED16)
99 if (UA_GET_NE16(m_pos) != UA_GET_NE16(ip))
100 #else
101 if (m_pos[0] != ip[0] || m_pos[1] != ip[1])
102 #endif
105 else
107 if (m_pos[2] == ip[2])
109 m_pos += 3;
110 #if 0
111 if (m_off <= M2_MAX_OFFSET)
112 goto match;
113 if (lit <= 3)
114 goto match;
115 if (lit == 3) /* better compression, but slower */
117 assert(op - 2 > out); op[-2] |= LZO_BYTE(3);
118 *op++ = *ii++; *op++ = *ii++; *op++ = *ii++;
119 goto code_match;
121 if (*m_pos == ip[3])
122 #endif
123 goto match;
128 /* a literal */
129 literal:
130 UPDATE_I(dict,0,dindex,ip,in);
131 if (++ip >= ip_end)
132 break;
133 continue;
136 /* a match */
137 match:
138 UPDATE_I(dict,0,dindex,ip,in);
139 /* store current literal run */
140 lit = pd(ip,ii);
141 if (lit > 0)
143 lzo_uint t = lit;
145 if (t < 4 && op > out)
146 op[-2] = LZO_BYTE(op[-2] | t);
147 else if (t <= 31)
148 *op++ = LZO_BYTE(t);
149 else
151 lzo_uint tt = t - 31;
153 *op++ = 0;
154 while (tt > 255)
156 tt -= 255;
157 UA_SET1(op, 0);
158 op++;
160 assert(tt > 0);
161 *op++ = LZO_BYTE(tt);
163 do *op++ = *ii++; while (--t > 0);
165 assert(ii == ip);
168 /* code the match */
169 ip += 3;
170 if (*m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++ ||
171 *m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++)
173 --ip;
174 m_len = pd(ip, ii);
175 assert(m_len >= 3); assert(m_len <= 8);
177 if (m_off <= M2_MAX_OFFSET)
179 m_off -= 1;
180 *op++ = LZO_BYTE(((m_len - 2) << 5) | ((m_off & 7) << 2));
181 *op++ = LZO_BYTE(m_off >> 3);
183 else if (m_len == 3 && m_off <= 2*M2_MAX_OFFSET && lit > 0)
185 m_off -= 1;
186 /* m_off -= M2_MAX_OFFSET; */
187 *op++ = LZO_BYTE(((m_off & 7) << 2));
188 *op++ = LZO_BYTE(m_off >> 3);
190 else
192 *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
193 *op++ = LZO_BYTE((m_off & 63) << 2);
194 *op++ = LZO_BYTE(m_off >> 6);
197 else
200 const lzo_bytep end;
201 end = in_end;
202 while (ip < end && *m_pos == *ip)
203 m_pos++, ip++;
204 m_len = pd(ip, ii);
206 assert(m_len >= 3);
208 if (m_len <= 33)
209 *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
210 else
212 m_len -= 33;
213 *op++ = M3_MARKER | 0;
214 while (m_len > 255)
216 m_len -= 255;
217 UA_SET1(op, 0);
218 op++;
220 assert(m_len > 0);
221 *op++ = LZO_BYTE(m_len);
223 *op++ = LZO_BYTE((m_off & 63) << 2);
224 *op++ = LZO_BYTE(m_off >> 6);
227 ii = ip;
228 if (ip >= ip_end)
229 break;
233 /* store final literal run */
234 if (pd(in_end,ii) > 0)
236 lzo_uint t = pd(in_end,ii);
238 if (t < 4 && op > out)
239 op[-2] = LZO_BYTE(op[-2] | t);
240 else if (t <= 31)
241 *op++ = LZO_BYTE(t);
242 else
244 lzo_uint tt = t - 31;
246 *op++ = 0;
247 while (tt > 255)
249 tt -= 255;
250 UA_SET1(op, 0);
251 op++;
253 assert(tt > 0);
254 *op++ = LZO_BYTE(tt);
256 UA_COPYN(op, ii, t);
257 op += t;
260 *out_len = pd(op, out);
261 return LZO_E_OK;
265 /***********************************************************************
266 // public entry point
267 ************************************************************************/
269 LZO_PUBLIC(int)
270 lzo1f_1_compress ( const lzo_bytep in , lzo_uint in_len,
271 lzo_bytep out, lzo_uintp out_len,
272 lzo_voidp wrkmem )
274 lzo_bytep op = out;
275 int r = LZO_E_OK;
277 if (in_len == 0)
278 *out_len = 0;
279 else if (in_len <= 10)
281 *op++ = LZO_BYTE(in_len);
282 do *op++ = *in++; while (--in_len > 0);
283 *out_len = pd(op, out);
285 else
286 r = do_compress(in,in_len,out,out_len,wrkmem);
288 if (r == LZO_E_OK)
290 op = out + *out_len;
291 op[0] = M3_MARKER | 1;
292 op[1] = 0;
293 op[2] = 0;
294 *out_len += 3;
297 return r;
301 /* vim:set ts=4 sw=4 et: */