Coverage Report

Created: 2026-01-09 06:15

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/lzo-2.10/src/lzo1x_c.ch
Line
Count
Source
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
2.15k
#  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
2.15k
{
45
2.15k
    const lzo_bytep ip;
46
2.15k
    lzo_bytep op;
47
2.15k
    const lzo_bytep const in_end = in + in_len;
48
2.15k
    const lzo_bytep const ip_end = in + in_len - 20;
49
2.15k
    const lzo_bytep ii;
50
2.15k
    lzo_dict_p const dict = (lzo_dict_p) wrkmem;
51
52
2.15k
    op = out;
53
2.15k
    ip = in;
54
2.15k
    ii = ip;
55
56
2.15k
    ip += ti < 4 ? 4 - ti : 0;
57
2.15k
    for (;;)
58
2.15k
    {
59
2.15k
        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
2.15k
        lzo_uint m_off;
100
2.15k
        lzo_uint m_len;
101
2.15k
        {
102
2.15k
        lzo_uint32_t dv;
103
2.15k
        lzo_uint dindex;
104
1.19M
literal:
105
1.19M
        ip += 1 + ((ip - ii) >> 5);
106
1.30M
next:
107
1.30M
        if __lzo_unlikely(ip >= ip_end)
108
2.15k
            break;
109
1.30M
        dv = UA_GET_LE32(ip);
110
1.30M
        dindex = DINDEX(dv,ip);
111
1.30M
        GINDEX(m_off,m_pos,in+dict,dindex,in);
112
1.30M
        UPDATE_I(dict,0,dindex,ip,in);
113
1.30M
        if __lzo_unlikely(dv != UA_GET_LE32(m_pos))
114
1.19M
            goto literal;
115
1.30M
        }
116
109k
#endif
117
118
    /* a match */
119
120
109k
        ii -= ti; ti = 0;
121
109k
        {
122
109k
        lzo_uint t = pd(ip,ii);
123
109k
        if (t != 0)
124
61.9k
        {
125
61.9k
            if (t <= 3)
126
28.1k
            {
127
28.1k
                op[-2] = LZO_BYTE(op[-2] | t);
128
28.1k
#if (LZO_OPT_UNALIGNED32)
129
28.1k
                UA_COPY4(op, ii);
130
28.1k
                op += t;
131
#else
132
                { do *op++ = *ii++; while (--t > 0); }
133
#endif
134
28.1k
            }
135
33.7k
#if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64)
136
33.7k
            else if (t <= 16)
137
20.3k
            {
138
20.3k
                *op++ = LZO_BYTE(t - 3);
139
20.3k
                UA_COPY8(op, ii);
140
20.3k
                UA_COPY8(op+8, ii+8);
141
20.3k
                op += t;
142
20.3k
            }
143
13.3k
#endif
144
13.3k
            else
145
13.3k
            {
146
13.3k
                if (t <= 18)
147
1.42k
                    *op++ = LZO_BYTE(t - 3);
148
11.9k
                else
149
11.9k
                {
150
11.9k
                    lzo_uint tt = t - 18;
151
11.9k
                    *op++ = 0;
152
130k
                    while __lzo_unlikely(tt > 255)
153
118k
                    {
154
118k
                        tt -= 255;
155
118k
                        UA_SET1(op, 0);
156
118k
                        op++;
157
118k
                    }
158
11.9k
                    assert(tt > 0);
159
11.9k
                    *op++ = LZO_BYTE(tt);
160
11.9k
                }
161
13.3k
#if (LZO_OPT_UNALIGNED32) || (LZO_OPT_UNALIGNED64)
162
1.93M
                do {
163
1.93M
                    UA_COPY8(op, ii);
164
1.93M
                    UA_COPY8(op+8, ii+8);
165
1.93M
                    op += 16; ii += 16; t -= 16;
166
1.93M
                } while (t >= 16); if (t > 0)
167
12.2k
#endif
168
82.0k
                { do *op++ = *ii++; while (--t > 0); }
169
13.3k
            }
170
61.9k
        }
171
109k
        }
172
109k
        m_len = 4;
173
109k
        {
174
109k
#if (LZO_OPT_UNALIGNED64)
175
109k
        lzo_uint64_t v;
176
109k
        v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len);
177
109k
        if __lzo_unlikely(v == 0) {
178
925k
            do {
179
925k
                m_len += 8;
180
925k
                v = UA_GET_NE64(ip + m_len) ^ UA_GET_NE64(m_pos + m_len);
181
925k
                if __lzo_unlikely(ip + m_len >= ip_end)
182
238
                    goto m_len_done;
183
925k
            } while (v == 0);
184
47.4k
        }
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
108k
        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
108k
        }
269
109k
m_len_done:
270
109k
        m_off = pd(ip,m_pos);
271
109k
        ip += m_len;
272
109k
        ii = ip;
273
109k
        if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
274
38.4k
        {
275
38.4k
            m_off -= 1;
276
38.4k
#if defined(LZO1X)
277
38.4k
            *op++ = LZO_BYTE(((m_len - 1) << 5) | ((m_off & 7) << 2));
278
38.4k
            *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
38.4k
        }
284
70.6k
        else if (m_off <= M3_MAX_OFFSET)
285
62.4k
        {
286
62.4k
            m_off -= 1;
287
62.4k
            if (m_len <= M3_MAX_LEN)
288
41.5k
                *op++ = LZO_BYTE(M3_MARKER | (m_len - 2));
289
20.9k
            else
290
20.9k
            {
291
20.9k
                m_len -= M3_MAX_LEN;
292
20.9k
                *op++ = M3_MARKER | 0;
293
34.5k
                while __lzo_unlikely(m_len > 255)
294
13.6k
                {
295
13.6k
                    m_len -= 255;
296
13.6k
                    UA_SET1(op, 0);
297
13.6k
                    op++;
298
13.6k
                }
299
20.9k
                *op++ = LZO_BYTE(m_len);
300
20.9k
            }
301
62.4k
            *op++ = LZO_BYTE(m_off << 2);
302
62.4k
            *op++ = LZO_BYTE(m_off >> 6);
303
62.4k
        }
304
8.20k
        else
305
8.20k
        {
306
8.20k
            m_off -= 0x4000;
307
8.20k
            if (m_len <= M4_MAX_LEN)
308
2.66k
                *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8) | (m_len - 2));
309
5.53k
            else
310
5.53k
            {
311
5.53k
                m_len -= M4_MAX_LEN;
312
5.53k
                *op++ = LZO_BYTE(M4_MARKER | ((m_off >> 11) & 8));
313
11.4k
                while __lzo_unlikely(m_len > 255)
314
5.86k
                {
315
5.86k
                    m_len -= 255;
316
5.86k
                    UA_SET1(op, 0);
317
5.86k
                    op++;
318
5.86k
                }
319
5.53k
                *op++ = LZO_BYTE(m_len);
320
5.53k
            }
321
8.20k
            *op++ = LZO_BYTE(m_off << 2);
322
8.20k
            *op++ = LZO_BYTE(m_off >> 6);
323
8.20k
        }
324
109k
        goto next;
325
108k
    }
326
327
2.15k
    *out_len = pd(op, out);
328
2.15k
    return pd(in_end,ii-ti);
329
2.15k
}
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
989
{
341
989
    const lzo_bytep ip = in;
342
989
    lzo_bytep op = out;
343
989
    lzo_uint l = in_len;
344
989
    lzo_uint t = 0;
345
346
3.14k
    while (l > 20)
347
2.16k
    {
348
2.16k
        lzo_uint ll = l;
349
2.16k
        lzo_uintptr_t ll_end;
350
2.16k
#if 0 || (LZO_DETERMINISTIC)
351
2.16k
        ll = LZO_MIN(ll, 49152);
352
2.16k
#endif
353
2.16k
        ll_end = (lzo_uintptr_t)ip + ll;
354
2.16k
        if ((ll_end + ((t + ll) >> 5)) <= ll_end || (const lzo_bytep)(ll_end + ((t + ll) >> 5)) <= ip + ll)
355
7
            break;
356
2.15k
#if (LZO_DETERMINISTIC)
357
2.15k
        lzo_memset(wrkmem, 0, ((lzo_uint)1 << D_BITS) * sizeof(lzo_dict_t));
358
2.15k
#endif
359
2.15k
        t = do_compress(ip,ll,op,out_len,t,wrkmem);
360
2.15k
        ip += ll;
361
2.15k
        op += *out_len;
362
2.15k
        l  -= ll;
363
2.15k
    }
364
989
    t += l;
365
366
989
    if (t > 0)
367
989
    {
368
989
        const lzo_bytep ii = in + in_len - t;
369
370
989
        if (op == out && t <= 238)
371
49
            *op++ = LZO_BYTE(17 + t);
372
940
        else if (t <= 3)
373
0
            op[-2] = LZO_BYTE(op[-2] | t);
374
940
        else if (t <= 18)
375
574
            *op++ = LZO_BYTE(t - 3);
376
366
        else
377
366
        {
378
366
            lzo_uint tt = t - 18;
379
380
366
            *op++ = 0;
381
103k
            while (tt > 255)
382
103k
            {
383
103k
                tt -= 255;
384
103k
                UA_SET1(op, 0);
385
103k
                op++;
386
103k
            }
387
366
            assert(tt > 0);
388
366
            *op++ = LZO_BYTE(tt);
389
366
        }
390
989
        UA_COPYN(op, ii, t);
391
989
        op += t;
392
989
    }
393
394
989
    *op++ = M4_MARKER | 1;
395
989
    *op++ = 0;
396
989
    *op++ = 0;
397
398
989
    *out_len = pd(op, out);
399
989
    return LZO_E_OK;
400
989
}
401
402
403
/* vim:set ts=4 sw=4 et: */