Coverage Report

Created: 2025-10-28 06:47

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
9.34M
#define M2_MAX_OFFSET   0x0800
38
#define M3_MAX_OFFSET   0x3fff
39
10.2k
#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
5.04M
#define D_INDEX1(d,p)   d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5)
47
1.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
380
{
60
380
    const lzo_bytep ip;
61
380
    lzo_bytep op;
62
380
    const lzo_bytep const in_end = in + in_len;
63
380
    const lzo_bytep const ip_end = in + in_len - 9;
64
380
    const lzo_bytep ii;
65
380
    lzo_dict_p const dict = (lzo_dict_p) wrkmem;
66
67
380
    op = out;
68
380
    ip = in;
69
380
    ii = ip;
70
71
380
    ip++;
72
380
    for (;;)
73
5.04M
    {
74
5.04M
        const lzo_bytep m_pos;
75
5.04M
        LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0);
76
5.04M
        lzo_uint m_len;
77
5.04M
        lzo_uint dindex;
78
5.04M
        lzo_uint lit;
79
80
5.04M
        DINDEX1(dindex,ip);
81
5.04M
        GINDEX(m_pos,m_off,dict,dindex,in);
82
5.04M
        if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M3_MAX_OFFSET))
83
2.33M
            goto literal;
84
2.71M
#if 1
85
2.71M
        if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
86
746k
            goto try_match;
87
1.96M
        DINDEX2(dindex,ip);
88
1.96M
#endif
89
1.96M
        GINDEX(m_pos,m_off,dict,dindex,in);
90
1.96M
        if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M3_MAX_OFFSET))
91
119k
            goto literal;
92
1.84M
        if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
93
868k
            goto try_match;
94
975k
        goto literal;
95
96
97
1.61M
try_match:
98
#if 0 && (LZO_OPT_UNALIGNED16)
99
        if (UA_GET_NE16(m_pos) != UA_GET_NE16(ip))
100
#else
101
1.61M
        if (m_pos[0] != ip[0] || m_pos[1] != ip[1])
102
1.41M
#endif
103
1.41M
        {
104
1.41M
        }
105
204k
        else
106
204k
        {
107
204k
            if (m_pos[2] == ip[2])
108
188k
            {
109
188k
                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
188k
                    goto match;
124
188k
            }
125
204k
        }
126
127
128
    /* a literal */
129
4.85M
literal:
130
4.85M
        UPDATE_I(dict,0,dindex,ip,in);
131
4.85M
        if (++ip >= ip_end)
132
143
            break;
133
4.85M
        continue;
134
135
136
    /* a match */
137
4.85M
match:
138
188k
        UPDATE_I(dict,0,dindex,ip,in);
139
        /* store current literal run */
140
188k
        lit = pd(ip,ii);
141
188k
        if (lit > 0)
142
112k
        {
143
112k
            lzo_uint t = lit;
144
145
112k
            if (t < 4 && op > out)
146
36.3k
                op[-2] = LZO_BYTE(op[-2] | t);
147
76.0k
            else if (t <= 31)
148
65.7k
                *op++ = LZO_BYTE(t);
149
10.3k
            else
150
10.3k
            {
151
10.3k
                lzo_uint tt = t - 31;
152
153
10.3k
                *op++ = 0;
154
20.8k
                while (tt > 255)
155
10.5k
                {
156
10.5k
                    tt -= 255;
157
10.5k
                    UA_SET1(op, 0);
158
10.5k
                    op++;
159
10.5k
                }
160
10.3k
                assert(tt > 0);
161
10.3k
                *op++ = LZO_BYTE(tt);
162
10.3k
            }
163
4.24M
            do *op++ = *ii++; while (--t > 0);
164
112k
        }
165
188k
        assert(ii == ip);
166
167
168
        /* code the match */
169
188k
        ip += 3;
170
188k
        if (*m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++ ||
171
40.0k
            *m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++)
172
163k
        {
173
163k
            --ip;
174
163k
            m_len = pd(ip, ii);
175
163k
            assert(m_len >= 3); assert(m_len <= 8);
176
177
163k
            if (m_off <= M2_MAX_OFFSET)
178
93.8k
            {
179
93.8k
                m_off -= 1;
180
93.8k
                *op++ = LZO_BYTE(((m_len - 2) << 5) | ((m_off & 7) << 2));
181
93.8k
                *op++ = LZO_BYTE(m_off >> 3);
182
93.8k
            }
183
69.5k
            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
69.5k
            else
191
69.5k
            {
192
69.5k
                *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
193
69.5k
                *op++ = LZO_BYTE((m_off & 63) << 2);
194
69.5k
                *op++ = LZO_BYTE(m_off >> 6);
195
69.5k
            }
196
163k
        }
197
25.5k
        else
198
25.5k
        {
199
25.5k
            {
200
25.5k
                const lzo_bytep end;
201
25.5k
                end = in_end;
202
8.02M
                while (ip < end && *m_pos == *ip)
203
8.00M
                    { m_pos++; ip++; }
204
25.5k
                m_len = pd(ip, ii);
205
25.5k
            }
206
25.5k
            assert(m_len >= 3);
207
208
25.5k
            if (m_len <= 33)
209
15.6k
                *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
210
9.89k
            else
211
9.89k
            {
212
9.89k
                m_len -= 33;
213
9.89k
                *op++ = M3_MARKER | 0;
214
36.5k
                while (m_len > 255)
215
26.6k
                {
216
26.6k
                    m_len -= 255;
217
26.6k
                    UA_SET1(op, 0);
218
26.6k
                    op++;
219
26.6k
                }
220
9.89k
                assert(m_len > 0);
221
9.89k
                *op++ = LZO_BYTE(m_len);
222
9.89k
            }
223
25.5k
            *op++ = LZO_BYTE((m_off & 63) << 2);
224
25.5k
            *op++ = LZO_BYTE(m_off >> 6);
225
25.5k
        }
226
227
188k
        ii = ip;
228
188k
        if (ip >= ip_end)
229
237
            break;
230
188k
    }
231
232
233
    /* store final literal run */
234
380
    if (pd(in_end,ii) > 0)
235
336
    {
236
336
        lzo_uint t = pd(in_end,ii);
237
238
336
        if (t < 4 && op > out)
239
50
            op[-2] = LZO_BYTE(op[-2] | t);
240
286
        else if (t <= 31)
241
215
            *op++ = LZO_BYTE(t);
242
71
        else
243
71
        {
244
71
            lzo_uint tt = t - 31;
245
246
71
            *op++ = 0;
247
2.42k
            while (tt > 255)
248
2.35k
            {
249
2.35k
                tt -= 255;
250
2.35k
                UA_SET1(op, 0);
251
2.35k
                op++;
252
2.35k
            }
253
71
            assert(tt > 0);
254
71
            *op++ = LZO_BYTE(tt);
255
71
        }
256
336
        UA_COPYN(op, ii, t);
257
336
        op += t;
258
336
    }
259
260
380
    *out_len = pd(op, out);
261
380
    return LZO_E_OK;
262
380
}
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
388
{
274
388
    lzo_bytep op = out;
275
388
    int r = LZO_E_OK;
276
277
388
    if (in_len == 0)
278
1
        *out_len = 0;
279
387
    else if (in_len <= 10)
280
7
    {
281
7
        *op++ = LZO_BYTE(in_len);
282
31
        do *op++ = *in++; while (--in_len > 0);
283
7
        *out_len = pd(op, out);
284
7
    }
285
380
    else
286
380
        r = do_compress(in,in_len,out,out_len,wrkmem);
287
288
388
    if (r == LZO_E_OK)
289
388
    {
290
388
        op = out + *out_len;
291
388
        op[0] = M3_MARKER | 1;
292
388
        op[1] = 0;
293
388
        op[2] = 0;
294
388
        *out_len += 3;
295
388
    }
296
297
388
    return r;
298
388
}
299
300
301
/* vim:set ts=4 sw=4 et: */