Coverage Report

Created: 2026-09-14 06:22

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/lzo-2.10/src/lzo1f_1.c
Line
Count
Source
1
/* lzo1f_1.c -- implementation of the LZO1F-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
#include "lzo_conf.h"
30
#include <lzo/lzo1f.h>
31
32
33
/***********************************************************************
34
//
35
************************************************************************/
36
37
13.7M
#define M2_MAX_OFFSET   0x0800
38
#define M3_MAX_OFFSET   0x3fff
39
4.53k
#define M3_MARKER       224
40
41
42
#ifndef LZO_HASH
43
#define LZO_HASH        LZO_HASH_LZO_INCREMENTAL_A
44
#endif
45
#define D_BITS          14
46
7.54M
#define D_INDEX1(d,p)   d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5)
47
2.96M
#define D_INDEX2(d,p)   d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f)
48
#include "lzo_dict.h"
49
50
51
/***********************************************************************
52
// compress a block of data.
53
************************************************************************/
54
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 )
59
459
{
60
459
    const lzo_bytep ip;
61
459
    lzo_bytep op;
62
459
    const lzo_bytep const in_end = in + in_len;
63
459
    const lzo_bytep const ip_end = in + in_len - 9;
64
459
    const lzo_bytep ii;
65
459
    lzo_dict_p const dict = (lzo_dict_p) wrkmem;
66
67
459
    op = out;
68
459
    ip = in;
69
459
    ii = ip;
70
71
459
    ip++;
72
459
    for (;;)
73
7.54M
    {
74
7.54M
        const lzo_bytep m_pos;
75
7.54M
        LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0);
76
7.54M
        lzo_uint m_len;
77
7.54M
        lzo_uint dindex;
78
7.54M
        lzo_uint lit;
79
80
7.54M
        DINDEX1(dindex,ip);
81
7.54M
        GINDEX(m_pos,m_off,dict,dindex,in);
82
7.54M
        if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M3_MAX_OFFSET))
83
3.60M
            goto literal;
84
3.94M
#if 1
85
3.94M
        if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
86
982k
            goto try_match;
87
2.96M
        DINDEX2(dindex,ip);
88
2.96M
#endif
89
2.96M
        GINDEX(m_pos,m_off,dict,dindex,in);
90
2.96M
        if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M3_MAX_OFFSET))
91
167k
            goto literal;
92
2.79M
        if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
93
1.30M
            goto try_match;
94
1.48M
        goto literal;
95
96
97
2.29M
try_match:
98
#if 0 && (LZO_OPT_UNALIGNED16)
99
        if (UA_GET_NE16(m_pos) != UA_GET_NE16(ip))
100
#else
101
2.29M
        if (m_pos[0] != ip[0] || m_pos[1] != ip[1])
102
1.99M
#endif
103
1.99M
        {
104
1.99M
        }
105
292k
        else
106
292k
        {
107
292k
            if (m_pos[2] == ip[2])
108
206k
            {
109
206k
                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 */
116
                {
117
                    assert(op - 2 > out); op[-2] |= LZO_BYTE(3);
118
                    *op++ = *ii++; *op++ = *ii++; *op++ = *ii++;
119
                    goto code_match;
120
                }
121
                if (*m_pos == ip[3])
122
#endif
123
206k
                    goto match;
124
206k
            }
125
292k
        }
126
127
128
    /* a literal */
129
7.33M
literal:
130
7.33M
        UPDATE_I(dict,0,dindex,ip,in);
131
7.33M
        if (++ip >= ip_end)
132
189
            break;
133
7.33M
        continue;
134
135
136
    /* a match */
137
7.33M
match:
138
206k
        UPDATE_I(dict,0,dindex,ip,in);
139
        /* store current literal run */
140
206k
        lit = pd(ip,ii);
141
206k
        if (lit > 0)
142
82.9k
        {
143
82.9k
            lzo_uint t = lit;
144
145
82.9k
            if (t < 4 && op > out)
146
54.8k
                op[-2] = LZO_BYTE(op[-2] | t);
147
28.0k
            else if (t <= 31)
148
24.3k
                *op++ = LZO_BYTE(t);
149
3.69k
            else
150
3.69k
            {
151
3.69k
                lzo_uint tt = t - 31;
152
153
3.69k
                *op++ = 0;
154
22.2k
                while (tt > 255)
155
18.6k
                {
156
18.6k
                    tt -= 255;
157
18.6k
                    UA_SET1(op, 0);
158
18.6k
                    op++;
159
18.6k
                }
160
3.69k
                assert(tt > 0);
161
3.69k
                *op++ = LZO_BYTE(tt);
162
3.69k
            }
163
5.42M
            do *op++ = *ii++; while (--t > 0);
164
82.9k
        }
165
206k
        assert(ii == ip);
166
167
168
        /* code the match */
169
206k
        ip += 3;
170
206k
        if (*m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++ ||
171
50.9k
            *m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++)
172
190k
        {
173
190k
            --ip;
174
190k
            m_len = pd(ip, ii);
175
190k
            assert(m_len >= 3); assert(m_len <= 8);
176
177
190k
            if (m_off <= M2_MAX_OFFSET)
178
149k
            {
179
149k
                m_off -= 1;
180
149k
                *op++ = LZO_BYTE(((m_len - 2) << 5) | ((m_off & 7) << 2));
181
149k
                *op++ = LZO_BYTE(m_off >> 3);
182
149k
            }
183
40.8k
            else if (m_len == 3 && m_off <= 2*M2_MAX_OFFSET && lit > 0)
184
0
            {
185
0
                m_off -= 1;
186
                /* m_off -= M2_MAX_OFFSET; */
187
0
                *op++ = LZO_BYTE(((m_off & 7) << 2));
188
0
                *op++ = LZO_BYTE(m_off >> 3);
189
0
            }
190
40.8k
            else
191
40.8k
            {
192
40.8k
                *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
193
40.8k
                *op++ = LZO_BYTE((m_off & 63) << 2);
194
40.8k
                *op++ = LZO_BYTE(m_off >> 6);
195
40.8k
            }
196
190k
        }
197
16.3k
        else
198
16.3k
        {
199
16.3k
            {
200
16.3k
                const lzo_bytep end;
201
16.3k
                end = in_end;
202
11.6M
                while (ip < end && *m_pos == *ip)
203
11.6M
                    { m_pos++; ip++; }
204
16.3k
                m_len = pd(ip, ii);
205
16.3k
            }
206
16.3k
            assert(m_len >= 3);
207
208
16.3k
            if (m_len <= 33)
209
12.2k
                *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
210
4.06k
            else
211
4.06k
            {
212
4.06k
                m_len -= 33;
213
4.06k
                *op++ = M3_MARKER | 0;
214
48.1k
                while (m_len > 255)
215
44.0k
                {
216
44.0k
                    m_len -= 255;
217
44.0k
                    UA_SET1(op, 0);
218
44.0k
                    op++;
219
44.0k
                }
220
4.06k
                assert(m_len > 0);
221
4.06k
                *op++ = LZO_BYTE(m_len);
222
4.06k
            }
223
16.3k
            *op++ = LZO_BYTE((m_off & 63) << 2);
224
16.3k
            *op++ = LZO_BYTE(m_off >> 6);
225
16.3k
        }
226
227
206k
        ii = ip;
228
206k
        if (ip >= ip_end)
229
270
            break;
230
206k
    }
231
232
233
    /* store final literal run */
234
459
    if (pd(in_end,ii) > 0)
235
407
    {
236
407
        lzo_uint t = pd(in_end,ii);
237
238
407
        if (t < 4 && op > out)
239
54
            op[-2] = LZO_BYTE(op[-2] | t);
240
353
        else if (t <= 31)
241
251
            *op++ = LZO_BYTE(t);
242
102
        else
243
102
        {
244
102
            lzo_uint tt = t - 31;
245
246
102
            *op++ = 0;
247
7.55k
            while (tt > 255)
248
7.45k
            {
249
7.45k
                tt -= 255;
250
7.45k
                UA_SET1(op, 0);
251
7.45k
                op++;
252
7.45k
            }
253
102
            assert(tt > 0);
254
102
            *op++ = LZO_BYTE(tt);
255
102
        }
256
407
        UA_COPYN(op, ii, t);
257
407
        op += t;
258
407
    }
259
260
459
    *out_len = pd(op, out);
261
459
    return LZO_E_OK;
262
459
}
263
264
265
/***********************************************************************
266
// public entry point
267
************************************************************************/
268
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 )
273
469
{
274
469
    lzo_bytep op = out;
275
469
    int r = LZO_E_OK;
276
277
469
    if (in_len == 0)
278
1
        *out_len = 0;
279
468
    else if (in_len <= 10)
280
9
    {
281
9
        *op++ = LZO_BYTE(in_len);
282
45
        do *op++ = *in++; while (--in_len > 0);
283
9
        *out_len = pd(op, out);
284
9
    }
285
459
    else
286
459
        r = do_compress(in,in_len,out,out_len,wrkmem);
287
288
469
    if (r == LZO_E_OK)
289
469
    {
290
469
        op = out + *out_len;
291
469
        op[0] = M3_MARKER | 1;
292
469
        op[1] = 0;
293
469
        op[2] = 0;
294
469
        *out_len += 3;
295
469
    }
296
297
469
    return r;
298
469
}
299
300
301
/* vim:set ts=4 sw=4 et: */