Coverage Report

Created: 2025-07-12 06:32

/src/lzo-2.10/src/lzo1x_c.ch
Line
Count
Source (jump to first uncovered line)
1
/* lzo1x_c.ch -- implementation of the LZO1[XY]-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
30
#if 1 && defined(DO_COMPRESS) && !defined(do_compress)
31
   /* choose a unique name to better help PGO optimizations */
32
1.98k
#  define do_compress       LZO_PP_ECONCAT2(DO_COMPRESS,_core)
33
#endif
34
35
36
/***********************************************************************
37
// compress a block of data.
38
************************************************************************/
39
40
static __lzo_noinline lzo_uint
41
do_compress ( const lzo_bytep in , lzo_uint  in_len,
42
                    lzo_bytep out, lzo_uintp out_len,
43
                    lzo_uint  ti,  lzo_voidp wrkmem)
44
1.98k
{
45
1.98k
    const lzo_bytep ip;
46
1.98k
    lzo_bytep op;
47
1.98k
    const lzo_bytep const in_end = in + in_len;
48
1.98k
    const lzo_bytep const ip_end = in + in_len - 20;
49
1.98k
    const lzo_bytep ii;
50
1.98k
    lzo_dict_p const dict = (lzo_dict_p) wrkmem;
51
52
1.98k
    op = out;
53
1.98k
    ip = in;
54
1.98k
    ii = ip;
55
56
1.98k
    ip += ti < 4 ? 4 - ti : 0;
57
1.98k
    for (;;)
58
1.98k
    {
59
1.98k
        const lzo_bytep m_pos;
60
#if !(LZO_DETERMINISTIC)
61
        LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0);
62
        lzo_uint m_len;
63
        lzo_uint dindex;
64
next:
65
        if __lzo_unlikely(ip >= ip_end)
66
            break;
67
        DINDEX1(dindex,ip);
68
        GINDEX(m_pos,m_off,dict,dindex,in);
69
        if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET))
70
            goto literal;
71
#if 1
72
        if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
73
            goto try_match;
74
        DINDEX2(dindex,ip);
75
#endif
76
        GINDEX(m_pos,m_off,dict,dindex,in);
77
        if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,M4_MAX_OFFSET))
78
            goto literal;
79
        if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
80
            goto try_match;
81
        goto literal;
82
83
try_match:
84
#if (LZO_OPT_UNALIGNED32)
85
        if (UA_GET_NE32(m_pos) != UA_GET_NE32(ip))
86
#else
87
        if (m_pos[0] != ip[0] || m_pos[1] != ip[1] || m_pos[2] != ip[2] || m_pos[3] != ip[3])
88
#endif
89
        {
90
            /* a literal */
91
literal:
92
            UPDATE_I(dict,0,dindex,ip,in);
93
            ip += 1 + ((ip - ii) >> 5);
94
            continue;
95
        }
96
/*match:*/
97
        UPDATE_I(dict,0,dindex,ip,in);
98
#else
99
1.98k
        lzo_uint m_off;
100
1.98k
        lzo_uint m_len;
101
1.98k
        {
102
1.98k
        lzo_uint32_t dv;
103
1.98k
        lzo_uint dindex;
104
1.42M
literal:
105
1.42M
        ip += 1 + ((ip - ii) >> 5);
106
1.59M
next:
107
1.59M
        if __lzo_unlikely(ip >= ip_end)
108
1.98k
            break;
109
1.59M
        dv = UA_GET_LE32(ip);
110
1.59M
        dindex = DINDEX(dv,ip);
111
1.59M
        GINDEX(m_off,m_pos,in+dict,dindex,in);
112
1.59M
        UPDATE_I(dict,0,dindex,ip,in);
113
1.59M
        if __lzo_unlikely(dv != UA_GET_LE32(m_pos))
114
1.42M
            goto literal;
115
1.59M
        }
116
176k
#endif
117
118
    /* a match */
119
120
176k
        ii -= ti; ti = 0;
121
176k
        {
122
176k
        lzo_uint t = pd(ip,ii);
123
176k
        if (t != 0)
124
95.5k
        {
125
95.5k
            if (t <= 3)
126
45.7k
            {
127
45.7k
                op[-2] = LZO_BYTE(op[-2] | t);
128
45.7k
#if (LZO_OPT_UNALIGNED32)
129
45.7k
                UA_COPY4(op, ii);
130
45.7k
                op += t;
131
#else
132
                { do *op++ = *ii++; while (--t > 0); }
133
#endif
134
45.7k
            }
135
49.8k
#if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64)
136
49.8k
            else if (t <= 16)
137
32.3k
            {
138
32.3k
                *op++ = LZO_BYTE(t - 3);
139
32.3k
                UA_COPY8(op, ii);
140
32.3k
                UA_COPY8(op+8, ii+8);
141
32.3k
                op += t;
142
32.3k
            }
143
17.5k
#endif
144
17.5k
            else
145
17.5k
            {
146
17.5k
                if (t <= 18)
147
2.06k
                    *op++ = LZO_BYTE(t - 3);
148
15.4k
                else
149
15.4k
                {
150
15.4k
                    lzo_uint tt = t - 18;
151
15.4k
                    *op++ = 0;
152
99.2k
                    while __lzo_unlikely(tt > 255)
153
83.7k
                    {
154
83.7k
                        tt -= 255;
155
83.7k
                        UA_SET1(op, 0);
156
83.7k
                        op++;
157
83.7k
                    }
158
15.4k
                    assert(tt > 0);
159
15.4k
                    *op++ = LZO_BYTE(tt);
160
15.4k
                }
161
17.5k
#if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64)
162
1.39M
                do {
163
1.39M
                    UA_COPY8(op, ii);
164
1.39M
                    UA_COPY8(op+8, ii+8);
165
1.39M
                    op += 16; ii += 16; t -= 16;
166
1.39M
                } while (t >= 16); if (t > 0)
167
15.9k
#endif
168
108k
                { do *op++ = *ii++; while (--t > 0); }
169
17.5k
            }
170
95.5k
        }
171
176k
        }
172
176k
        m_len = 4;
173
176k
        {
174
176k
#if (LZO_OPT_UNALIGNED64)
175
176k
        lzo_uint64_t v;
176
176k
        v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len);
177
176k
        if __lzo_unlikely(v == 0) {
178
1.21M
            do {
179
1.21M
                m_len += 8;
180
1.21M
                v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len);
181
1.21M
                if __lzo_unlikely(ip + m_len >= ip_end)
182
321
                    goto m_len_done;
183
1.21M
            } while (v == 0);
184
70.2k
        }
185
#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz64)
186
        m_len += lzo_bitops_ctlz64(v) / CHAR_BIT;
187
#elif (LZO_ABI_BIG_ENDIAN)
188
        if ((v >> (64 - CHAR_BIT)) == 0) do {
189
            v <<= CHAR_BIT;
190
            m_len += 1;
191
        } while ((v >> (64 - CHAR_BIT)) == 0);
192
#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz64)
193
176k
        m_len += lzo_bitops_cttz64(v) / CHAR_BIT;
194
#elif (LZO_ABI_LITTLE_ENDIAN)
195
        if ((v & UCHAR_MAX) == 0) do {
196
            v >>= CHAR_BIT;
197
            m_len += 1;
198
        } while ((v & UCHAR_MAX) == 0);
199
#else
200
        if (ip[m_len] == m_pos[m_len]) do {
201
            m_len += 1;
202
        } while (ip[m_len] == m_pos[m_len]);
203
#endif
204
#elif (LZO_OPT_UNALIGNED32)
205
        lzo_uint32_t v;
206
        v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len);
207
        if __lzo_unlikely(v == 0) {
208
            do {
209
                m_len += 4;
210
                v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len);
211
                if (v != 0)
212
                    break;
213
                m_len += 4;
214
                v = UA_GET_NE32(ip + m_len) ^ UA_GET_NE32(m_pos + m_len);
215
                if __lzo_unlikely(ip + m_len >= ip_end)
216
                    goto m_len_done;
217
            } while (v == 0);
218
        }
219
#if (LZO_ABI_BIG_ENDIAN) && defined(lzo_bitops_ctlz32)
220
        m_len += lzo_bitops_ctlz32(v) / CHAR_BIT;
221
#elif (LZO_ABI_BIG_ENDIAN)
222
        if ((v >> (32 - CHAR_BIT)) == 0) do {
223
            v <<= CHAR_BIT;
224
            m_len += 1;
225
        } while ((v >> (32 - CHAR_BIT)) == 0);
226
#elif (LZO_ABI_LITTLE_ENDIAN) && defined(lzo_bitops_cttz32)
227
        m_len += lzo_bitops_cttz32(v) / CHAR_BIT;
228
#elif (LZO_ABI_LITTLE_ENDIAN)
229
        if ((v & UCHAR_MAX) == 0) do {
230
            v >>= CHAR_BIT;
231
            m_len += 1;
232
        } while ((v & UCHAR_MAX) == 0);
233
#else
234
        if (ip[m_len] == m_pos[m_len]) do {
235
            m_len += 1;
236
        } while (ip[m_len] == m_pos[m_len]);
237
#endif
238
#else
239
        if __lzo_unlikely(ip[m_len] == m_pos[m_len]) {
240
            do {
241
                m_len += 1;
242
                if (ip[m_len] != m_pos[m_len])
243
                    break;
244
                m_len += 1;
245
                if (ip[m_len] != m_pos[m_len])
246
                    break;
247
                m_len += 1;
248
                if (ip[m_len] != m_pos[m_len])
249
                    break;
250
                m_len += 1;
251
                if (ip[m_len] != m_pos[m_len])
252
                    break;
253
                m_len += 1;
254
                if (ip[m_len] != m_pos[m_len])
255
                    break;
256
                m_len += 1;
257
                if (ip[m_len] != m_pos[m_len])
258
                    break;
259
                m_len += 1;
260
                if (ip[m_len] != m_pos[m_len])
261
                    break;
262
                m_len += 1;
263
                if __lzo_unlikely(ip + m_len >= ip_end)
264
                    goto m_len_done;
265
            } while (ip[m_len] == m_pos[m_len]);
266
        }
267
#endif
268
176k
        }
269
176k
m_len_done:
270
176k
        m_off = pd(ip,m_pos);
271
176k
        ip += m_len;
272
176k
        ii = ip;
273
176k
        if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
274
64.6k
        {
275
64.6k
            m_off -= 1;
276
64.6k
#if defined(LZO1X)
277
64.6k
            *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2));
278
64.6k
            *op++ = LZO_BYTE(m_off >> 3);
279
#elif defined(LZO1Y)
280
            *op++ = LZO_BYTE(((m_len + 1) << 4) | ((m_off & 3) << 2));
281
            *op++ = LZO_BYTE(m_off >> 2);
282
#endif
283
64.6k
        }
284
112k
        else if (m_off <= M3_MAX_OFFSET)
285
98.1k
        {
286
98.1k
            m_off -= 1;
287
98.1k
            if (m_len <= M3_MAX_LEN)
288
68.8k
                *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
289
29.3k
            else
290
29.3k
            {
291
29.3k
                m_len -= M3_MAX_LEN;
292
29.3k
                *op++ = M3_MARKER | 0;
293
47.6k
                while __lzo_unlikely(m_len > 255)
294
18.3k
                {
295
18.3k
                    m_len -= 255;
296
18.3k
                    UA_SET1(op, 0);
297
18.3k
                    op++;
298
18.3k
                }
299
29.3k
                *op++ = LZO_BYTE(m_len);
300
29.3k
            }
301
98.1k
            *op++ = LZO_BYTE(m_off << 2);
302
98.1k
            *op++ = LZO_BYTE(m_off >> 6);
303
98.1k
        }
304
14.1k
        else
305
14.1k
        {
306
14.1k
            m_off -= 0x4000;
307
14.1k
            if (m_len <= M4_MAX_LEN)
308
6.15k
                *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8) | (m_len - 2));
309
7.95k
            else
310
7.95k
            {
311
7.95k
                m_len -= M4_MAX_LEN;
312
7.95k
                *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8));
313
14.2k
                while __lzo_unlikely(m_len > 255)
314
6.28k
                {
315
6.28k
                    m_len -= 255;
316
6.28k
                    UA_SET1(op, 0);
317
6.28k
                    op++;
318
6.28k
                }
319
7.95k
                *op++ = LZO_BYTE(m_len);
320
7.95k
            }
321
14.1k
            *op++ = LZO_BYTE(m_off << 2);
322
14.1k
            *op++ = LZO_BYTE(m_off >> 6);
323
14.1k
        }
324
176k
        goto next;
325
176k
    }
326
327
1.98k
    *out_len = pd(op, out);
328
1.98k
    return pd(in_end,ii-ti);
329
1.98k
}
330
331
332
/***********************************************************************
333
// public entry point
334
************************************************************************/
335
336
LZO_PUBLIC(int)
337
DO_COMPRESS      ( const lzo_bytep in , lzo_uint  in_len,
338
                         lzo_bytep out, lzo_uintp out_len,
339
                         lzo_voidp wrkmem )
340
910
{
341
910
    const lzo_bytep ip = in;
342
910
    lzo_bytep op = out;
343
910
    lzo_uint l = in_len;
344
910
    lzo_uint t = 0;
345
346
2.89k
    while (l > 20)
347
1.98k
    {
348
1.98k
        lzo_uint ll = l;
349
1.98k
        lzo_uintptr_t ll_end;
350
1.98k
#if 0 || (LZO_DETERMINISTIC)
351
1.98k
        ll = LZO_MIN(ll, 49152);
352
1.98k
#endif
353
1.98k
        ll_end = (lzo_uintptr_t)ip + ll;
354
1.98k
        if ((ll_end + ((t + ll) >> 5)) <= ll_end || (const lzo_bytep)(ll_end + ((t + ll) >> 5)) <= ip + ll)
355
7
            break;
356
1.98k
#if (LZO_DETERMINISTIC)
357
1.98k
        lzo_memset(wrkmem, 0, ((lzo_uint)1 << D_BITS) * sizeof(lzo_dict_t));
358
1.98k
#endif
359
1.98k
        t = do_compress(ip,ll,op,out_len,t,wrkmem);
360
1.98k
        ip += ll;
361
1.98k
        op += *out_len;
362
1.98k
        l  -= ll;
363
1.98k
    }
364
910
    t += l;
365
366
910
    if (t > 0)
367
910
    {
368
910
        const lzo_bytep ii = in + in_len - t;
369
370
910
        if (op == out && t <= 238)
371
43
            *op++ = LZO_BYTE(17 + t);
372
867
        else if (t <= 3)
373
0
            op[-2] = LZO_BYTE(op[-2] | t);
374
867
        else if (t <= 18)
375
527
            *op++ = LZO_BYTE(t - 3);
376
340
        else
377
340
        {
378
340
            lzo_uint tt = t - 18;
379
380
340
            *op++ = 0;
381
105k
            while (tt > 255)
382
104k
            {
383
104k
                tt -= 255;
384
104k
                UA_SET1(op, 0);
385
104k
                op++;
386
104k
            }
387
340
            assert(tt > 0);
388
340
            *op++ = LZO_BYTE(tt);
389
340
        }
390
910
        UA_COPYN(op, ii, t);
391
910
        op += t;
392
910
    }
393
394
910
    *op++ = M4_MARKER | 1;
395
910
    *op++ = 0;
396
910
    *op++ = 0;
397
398
910
    *out_len = pd(op, out);
399
910
    return LZO_E_OK;
400
910
}
401
402
403
/* vim:set ts=4 sw=4 et: */