Coverage Report

Created: 2025-07-23 07:05

/src/lzo-2.10/src/lzo1f_1.c
Line
Count
Source (jump to first uncovered line)
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
3.82M
#define M2_MAX_OFFSET   0x0800
38
#define M3_MAX_OFFSET   0x3fff
39
11.7k
#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
2.49M
#define D_INDEX1(d,p)   d = DM(DMUL(0x21,DX3(p,5,5,6)) >> 5)
47
816k
#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
420
{
60
420
    const lzo_bytep ip;
61
420
    lzo_bytep op;
62
420
    const lzo_bytep const in_end = in + in_len;
63
420
    const lzo_bytep const ip_end = in + in_len - 9;
64
420
    const lzo_bytep ii;
65
420
    lzo_dict_p const dict = (lzo_dict_p) wrkmem;
66
67
420
    op = out;
68
420
    ip = in;
69
420
    ii = ip;
70
71
420
    ip++;
72
420
    for (;;)
73
2.49M
    {
74
2.49M
        const lzo_bytep m_pos;
75
2.49M
        LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0);
76
2.49M
        lzo_uint m_len;
77
2.49M
        lzo_uint dindex;
78
2.49M
        lzo_uint lit;
79
80
2.49M
        DINDEX1(dindex,ip);
81
2.49M
        GINDEX(m_pos,m_off,dict,dindex,in);
82
2.49M
        if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M3_MAX_OFFSET))
83
1.34M
            goto literal;
84
1.15M
#if 1
85
1.15M
        if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
86
334k
            goto try_match;
87
816k
        DINDEX2(dindex,ip);
88
816k
#endif
89
816k
        GINDEX(m_pos,m_off,dict,dindex,in);
90
816k
        if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M3_MAX_OFFSET))
91
84.5k
            goto literal;
92
731k
        if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
93
336k
            goto try_match;
94
394k
        goto literal;
95
96
97
670k
try_match:
98
#if 0 && (LZO_OPT_UNALIGNED16)
99
        if (UA_GET_NE16(m_pos) != UA_GET_NE16(ip))
100
#else
101
670k
        if (m_pos[0] != ip[0] || m_pos[1] != ip[1])
102
568k
#endif
103
568k
        {
104
568k
        }
105
102k
        else
106
102k
        {
107
102k
            if (m_pos[2] == ip[2])
108
85.3k
            {
109
85.3k
                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
85.3k
                    goto match;
124
85.3k
            }
125
102k
        }
126
127
128
    /* a literal */
129
2.40M
literal:
130
2.40M
        UPDATE_I(dict,0,dindex,ip,in);
131
2.40M
        if (++ip >= ip_end)
132
164
            break;
133
2.40M
        continue;
134
135
136
    /* a match */
137
2.40M
match:
138
85.3k
        UPDATE_I(dict,0,dindex,ip,in);
139
        /* store current literal run */
140
85.3k
        lit = pd(ip,ii);
141
85.3k
        if (lit > 0)
142
34.7k
        {
143
34.7k
            lzo_uint t = lit;
144
145
34.7k
            if (t < 4 && op > out)
146
19.8k
                op[-2] = LZO_BYTE(op[-2] | t);
147
14.8k
            else if (t <= 31)
148
12.3k
                *op++ = LZO_BYTE(t);
149
2.57k
            else
150
2.57k
            {
151
2.57k
                lzo_uint tt = t - 31;
152
153
2.57k
                *op++ = 0;
154
7.80k
                while (tt > 255)
155
5.23k
                {
156
5.23k
                    tt -= 255;
157
5.23k
                    UA_SET1(op, 0);
158
5.23k
                    op++;
159
5.23k
                }
160
2.57k
                assert(tt > 0);
161
2.57k
                *op++ = LZO_BYTE(tt);
162
2.57k
            }
163
1.73M
            do *op++ = *ii++; while (--t > 0);
164
34.7k
        }
165
85.3k
        assert(ii == ip);
166
167
168
        /* code the match */
169
85.3k
        ip += 3;
170
85.3k
        if (*m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++ ||
171
85.3k
            *m_pos++ != *ip++ || *m_pos++ != *ip++ || *m_pos++ != *ip++)
172
57.1k
        {
173
57.1k
            --ip;
174
57.1k
            m_len = pd(ip, ii);
175
57.1k
            assert(m_len >= 3); assert(m_len <= 8);
176
177
57.1k
            if (m_off <= M2_MAX_OFFSET)
178
49.1k
            {
179
49.1k
                m_off -= 1;
180
49.1k
                *op++ = LZO_BYTE(((m_len - 2) << 5) | ((m_off & 7) << 2));
181
49.1k
                *op++ = LZO_BYTE(m_off >> 3);
182
49.1k
            }
183
8.08k
            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
8.08k
            else
191
8.08k
            {
192
8.08k
                *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
193
8.08k
                *op++ = LZO_BYTE((m_off & 63) << 2);
194
8.08k
                *op++ = LZO_BYTE(m_off >> 6);
195
8.08k
            }
196
57.1k
        }
197
28.1k
        else
198
28.1k
        {
199
28.1k
            {
200
28.1k
                const lzo_bytep end;
201
28.1k
                end = in_end;
202
7.34M
                while (ip < end && *m_pos == *ip)
203
7.31M
                    { m_pos++; ip++; }
204
28.1k
                m_len = pd(ip, ii);
205
28.1k
            }
206
28.1k
            assert(m_len >= 3);
207
208
28.1k
            if (m_len <= 33)
209
16.8k
                *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
210
11.3k
            else
211
11.3k
            {
212
11.3k
                m_len -= 33;
213
11.3k
                *op++ = M3_MARKER | 0;
214
34.6k
                while (m_len > 255)
215
23.3k
                {
216
23.3k
                    m_len -= 255;
217
23.3k
                    UA_SET1(op, 0);
218
23.3k
                    op++;
219
23.3k
                }
220
11.3k
                assert(m_len > 0);
221
11.3k
                *op++ = LZO_BYTE(m_len);
222
11.3k
            }
223
28.1k
            *op++ = LZO_BYTE((m_off & 63) << 2);
224
28.1k
            *op++ = LZO_BYTE(m_off >> 6);
225
28.1k
        }
226
227
85.3k
        ii = ip;
228
85.3k
        if (ip >= ip_end)
229
256
            break;
230
85.3k
    }
231
232
233
    /* store final literal run */
234
420
    if (pd(in_end,ii) > 0)
235
375
    {
236
375
        lzo_uint t = pd(in_end,ii);
237
238
375
        if (t < 4 && op > out)
239
55
            op[-2] = LZO_BYTE(op[-2] | t);
240
320
        else if (t <= 31)
241
234
            *op++ = LZO_BYTE(t);
242
86
        else
243
86
        {
244
86
            lzo_uint tt = t - 31;
245
246
86
            *op++ = 0;
247
2.65k
            while (tt > 255)
248
2.57k
            {
249
2.57k
                tt -= 255;
250
2.57k
                UA_SET1(op, 0);
251
2.57k
                op++;
252
2.57k
            }
253
86
            assert(tt > 0);
254
86
            *op++ = LZO_BYTE(tt);
255
86
        }
256
375
        UA_COPYN(op, ii, t);
257
375
        op += t;
258
375
    }
259
260
420
    *out_len = pd(op, out);
261
420
    return LZO_E_OK;
262
420
}
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
429
{
274
429
    lzo_bytep op = out;
275
429
    int r = LZO_E_OK;
276
277
429
    if (in_len == 0)
278
1
        *out_len = 0;
279
428
    else if (in_len <= 10)
280
8
    {
281
8
        *op++ = LZO_BYTE(in_len);
282
39
        do *op++ = *in++; while (--in_len > 0);
283
8
        *out_len = pd(op, out);
284
8
    }
285
420
    else
286
420
        r = do_compress(in,in_len,out,out_len,wrkmem);
287
288
429
    if (r == LZO_E_OK)
289
429
    {
290
429
        op = out + *out_len;
291
429
        op[0] = M3_MARKER | 1;
292
429
        op[1] = 0;
293
429
        op[2] = 0;
294
429
        *out_len += 3;
295
429
    }
296
297
429
    return r;
298
429
}
299
300
301
/* vim:set ts=4 sw=4 et: */