Coverage Report

Created: 2024-07-27 06:11

/src/lzo-2.10/src/lzo1a.c
Line
Count
Source (jump to first uncovered line)
1
/* lzo1a.c -- implementation of the LZO1A 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/lzo1a.h>
31
32
33
/***********************************************************************
34
// The next two defines can be changed to customize LZO1A.
35
// The default version is LZO1A-5/1.
36
************************************************************************/
37
38
/* run bits (3 - 5) - the compressor and the decompressor
39
 * must use the same value. */
40
#if !defined(RBITS)
41
2.37M
#  define RBITS     5
42
#endif
43
44
/* compression level (1 - 9) - this only affects the compressor.
45
 * 1 is fastest, 9 is best compression ratio
46
 */
47
#if !defined(CLEVEL)
48
0
#  define CLEVEL    1           /* fastest by default */
49
#endif
50
51
52
/* Collect statistics */
53
#if 0 && !defined(LZO_COLLECT_STATS)
54
#  define LZO_COLLECT_STATS 1
55
#endif
56
57
58
/***********************************************************************
59
// You should not have to change anything below this line.
60
************************************************************************/
61
62
/* check configuration */
63
#if (RBITS < 3 || RBITS > 5)
64
#  error "invalid RBITS"
65
#endif
66
#if (CLEVEL < 1 || CLEVEL > 9)
67
#  error "invalid CLEVEL"
68
#endif
69
70
71
/***********************************************************************
72
// internal configuration
73
// all of these affect compression only
74
************************************************************************/
75
76
/* choose the hashing strategy */
77
#ifndef LZO_HASH
78
#define LZO_HASH    LZO_HASH_LZO_INCREMENTAL_A
79
#endif
80
14.8M
#define D_INDEX1(d,p)       d = DM(DMUL(0x21,DX2(p,5,5)) >> 5)
81
9.61M
#define D_INDEX2(d,p)       d = d ^ D_MASK
82
83
#include "lzo1a_de.h"
84
#include "stats1a.h"
85
86
87
/* check other constants */
88
#if (LBITS < 5 || LBITS > 8)
89
#  error "invalid LBITS"
90
#endif
91
92
93
#if (LZO_COLLECT_STATS)
94
   static lzo1a_stats_t lzo_statistics;
95
   lzo1a_stats_t *lzo1a_stats = &lzo_statistics;
96
#  define lzo_stats lzo1a_stats
97
#endif
98
99
100
/***********************************************************************
101
// get algorithm info, return memory required for compression
102
************************************************************************/
103
104
LZO_EXTERN(lzo_uint) lzo1a_info ( int *rbits, int *clevel );
105
106
LZO_PUBLIC(lzo_uint)
107
lzo1a_info ( int *rbits, int *clevel )
108
0
{
109
0
    if (rbits)
110
0
        *rbits = RBITS;
111
0
    if (clevel)
112
0
        *clevel = CLEVEL;
113
0
    return D_SIZE * lzo_sizeof(lzo_bytep);
114
0
}
115
116
117
/***********************************************************************
118
// LZO1A decompress a block of data.
119
//
120
// Could be easily translated into assembly code.
121
************************************************************************/
122
123
LZO_PUBLIC(int)
124
lzo1a_decompress ( const lzo_bytep in , lzo_uint  in_len,
125
                         lzo_bytep out, lzo_uintp out_len,
126
                         lzo_voidp wrkmem )
127
985
{
128
985
    lzo_bytep op;
129
985
    const lzo_bytep ip;
130
985
    lzo_uint t;
131
985
    const lzo_bytep m_pos;
132
985
    const lzo_bytep const ip_end = in + in_len;
133
134
985
    LZO_UNUSED(wrkmem);
135
136
985
    op = out;
137
985
    ip = in;
138
291k
    while (ip < ip_end)
139
290k
    {
140
290k
        t = *ip++;      /* get marker */
141
290k
        LZO_STATS(lzo_stats->marker[t]++);
142
143
290k
        if (t == 0)             /* a R0 literal run */
144
23.2k
        {
145
23.2k
            t = *ip++;
146
23.2k
            if (t >= R0FAST - R0MIN)            /* a long R0 run */
147
10.1k
            {
148
10.1k
                t -= R0FAST - R0MIN;
149
10.1k
                if (t == 0)
150
3.39k
                    t = R0FAST;
151
6.74k
                else
152
6.74k
                {
153
#if 0
154
                    t = 256u << ((unsigned) t);
155
#else
156
                    /* help the optimizer */
157
6.74k
                    lzo_uint tt = 256;
158
13.0k
                    do tt <<= 1; while (--t > 0);
159
6.74k
                    t = tt;
160
6.74k
#endif
161
6.74k
                }
162
10.1k
                MEMCPY8_DS(op,ip,t);
163
10.1k
                continue;
164
10.1k
            }
165
13.1k
            t += R0MIN;
166
13.1k
            goto literal;
167
23.2k
        }
168
267k
        else if (t < R0MIN)     /* a short literal run */
169
111k
        {
170
124k
literal:
171
124k
            MEMCPY_DS(op,ip,t);
172
173
        /* after a literal a match must follow */
174
134k
            while (ip < ip_end)
175
133k
            {
176
133k
                t = *ip++;          /* get R1 marker */
177
133k
                if (t >= R0MIN)
178
123k
                    goto match;
179
180
            /* R1 match - a context sensitive 3 byte match + 1 byte literal */
181
10.2k
                assert((t & OMASK) == t);
182
10.2k
                m_pos = op - MIN_OFFSET;
183
10.2k
                m_pos -= t | (((lzo_uint) *ip++) << OBITS);
184
10.2k
                assert(m_pos >= out); assert(m_pos < op);
185
10.2k
                *op++ = m_pos[0];
186
10.2k
                *op++ = m_pos[1];
187
10.2k
                *op++ = m_pos[2];
188
10.2k
                *op++ = *ip++;
189
10.2k
            }
190
124k
        }
191
156k
        else                    /* a match */
192
156k
        {
193
279k
match:
194
            /* get match offset */
195
279k
            m_pos = op - MIN_OFFSET;
196
279k
            m_pos -= (t & OMASK) | (((lzo_uint) *ip++) << OBITS);
197
279k
            assert(m_pos >= out); assert(m_pos < op);
198
199
            /* get match len */
200
279k
            if (t < ((MSIZE - 1) << OBITS))         /* a short match */
201
166k
            {
202
166k
                t >>= OBITS;
203
166k
                *op++ = *m_pos++;
204
166k
                *op++ = *m_pos++;
205
166k
                MEMCPY_DS(op,m_pos,t);
206
166k
            }
207
112k
            else                                     /* a long match */
208
112k
            {
209
#if (LBITS < 8)
210
                t = (MIN_MATCH_LONG - THRESHOLD) + ((lzo_uint)(*ip++) & LMASK);
211
#else
212
112k
                t = (MIN_MATCH_LONG - THRESHOLD) + (lzo_uint)(*ip++);
213
112k
#endif
214
112k
                *op++ = *m_pos++;
215
112k
                *op++ = *m_pos++;
216
112k
                MEMCPY_DS(op,m_pos,t);
217
#if (LBITS < 8)
218
                /* a very short literal following a long match */
219
                t = ip[-1] >> LBITS;
220
                if (t) do
221
                    *op++ = *ip++;
222
                while (--t);
223
#endif
224
112k
            }
225
279k
        }
226
290k
    }
227
228
985
    *out_len = pd(op, out);
229
230
    /* the next line is the only check in the decompressor */
231
985
    return (ip == ip_end ? LZO_E_OK :
232
985
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
233
985
}
234
235
236
237
/***********************************************************************
238
// LZO1A compress a block of data.
239
//
240
// I apologize for the spaghetti code, but it really helps the optimizer.
241
************************************************************************/
242
243
#include "lzo1a_cr.ch"
244
245
static int
246
do_compress    ( const lzo_bytep in , lzo_uint  in_len,
247
                       lzo_bytep out, lzo_uintp out_len,
248
                       lzo_voidp wrkmem )
249
541
{
250
541
    const lzo_bytep ip;
251
541
#if defined(__LZO_HASH_INCREMENTAL)
252
541
    lzo_xint dv;
253
541
#endif
254
541
    const lzo_bytep m_pos;
255
541
    lzo_bytep op;
256
541
    const lzo_bytep const ip_end = in+in_len - DVAL_LEN - MIN_MATCH_LONG;
257
541
    const lzo_bytep const in_end = in+in_len - DVAL_LEN;
258
541
    const lzo_bytep ii;
259
541
    lzo_dict_p const dict = (lzo_dict_p) wrkmem;
260
541
    const lzo_bytep r1 = ip_end;    /* pointer for R1 match (none yet) */
261
#if (LBITS < 8)
262
    const lzo_bytep im = ip_end;    /* pointer to last match start */
263
#endif
264
265
#if !defined(NDEBUG)
266
    const lzo_bytep m_pos_sav;
267
#endif
268
269
541
    op = out;
270
541
    ip = in;
271
541
    ii = ip;            /* point to start of current literal run */
272
273
    /* init dictionary */
274
541
#if (LZO_DETERMINISTIC)
275
541
    BZERO8_PTR(wrkmem,sizeof(lzo_dict_t),D_SIZE);
276
541
#endif
277
278
541
    DVAL_FIRST(dv,ip); UPDATE_D(dict,0,dv,ip,in); ip++;
279
541
    DVAL_NEXT(dv,ip);
280
281
14.8M
    do {
282
14.8M
        LZO_DEFINE_UNINITIALIZED_VAR(lzo_uint, m_off, 0);
283
14.8M
        lzo_uint dindex;
284
285
14.8M
        DINDEX1(dindex,ip);
286
14.8M
        GINDEX(m_pos,m_off,dict,dindex,in);
287
14.8M
        if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,MAX_OFFSET))
288
5.23M
            goto literal;
289
9.61M
        if (m_pos[0] == ip[0] && m_pos[1] == ip[1] && m_pos[2] == ip[2])
290
185k
            goto match;
291
9.43M
        DINDEX2(dindex,ip);
292
9.43M
        GINDEX(m_pos,m_off,dict,dindex,in);
293
9.43M
        if (LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,MAX_OFFSET))
294
2.61M
            goto literal;
295
6.81M
        if (m_pos[0] == ip[0] && m_pos[1] == ip[1] && m_pos[2] == ip[2])
296
46.7k
            goto match;
297
6.76M
        goto literal;
298
299
14.6M
literal:
300
14.6M
        UPDATE_I(dict,0,dindex,ip,in);
301
14.6M
        if (++ip >= ip_end)
302
255
            break;
303
14.6M
        continue;
304
305
14.6M
match:
306
232k
        UPDATE_I(dict,0,dindex,ip,in);
307
#if !defined(NDEBUG) && (LZO_DICT_USE_PTR)
308
        assert(m_pos == NULL || m_pos >= in);
309
        m_pos_sav = m_pos;
310
#endif
311
232k
        m_pos += 3;
312
232k
        {
313
    /* we have found a match (of at least length 3) */
314
315
#if !defined(NDEBUG) && !(LZO_DICT_USE_PTR)
316
            assert((m_pos_sav = ip - m_off) == (m_pos - 3));
317
#endif
318
319
232k
            assert(m_pos >= in);
320
232k
            assert(ip < ip_end);
321
322
            /* 1) store the current literal run */
323
232k
            if (pd(ip,ii) > 0)
324
111k
            {
325
111k
                lzo_uint t = pd(ip,ii);
326
327
111k
                if (ip - r1 == MIN_MATCH + 1)
328
7.84k
                {
329
                /* Code a context sensitive R1 match.
330
                 * This is tricky and somewhat difficult to explain:
331
                 * multiplex a literal run of length 1 into the previous
332
                 * short match of length MIN_MATCH.
333
                 * The key idea is:
334
                 *  - after a short run a match MUST follow
335
                 *  - therefore the value m = 000 in the mmmooooo marker is free
336
                 *  - use 000ooooo to indicate a MIN_MATCH match (this
337
                 *    is already coded) plus a 1 byte literal
338
                 */
339
7.84k
                    assert(t == 1);
340
                    /* modify marker byte */
341
7.84k
                    assert((op[-2] >> OBITS) == (MIN_MATCH - THRESHOLD));
342
7.84k
                    op[-2] &= OMASK;
343
7.84k
                    assert((op[-2] >> OBITS) == 0);
344
                    /* copy 1 literal */
345
7.84k
                    *op++ = *ii;
346
7.84k
                    LZO_STATS(lzo_stats->r1_matches++);
347
7.84k
                    r1 = ip;                /* set new R1 pointer */
348
7.84k
                }
349
103k
                else if (t < R0MIN)
350
92.4k
                {
351
                    /* inline the copying of a short run */
352
#if (LBITS < 8)
353
                    if (t < (1 << (8-LBITS)) && ii - im >= MIN_MATCH_LONG)
354
                    {
355
                    /* Code a very short literal run into the
356
                     * previous long match length byte.
357
                     */
358
                        LZO_STATS(lzo_stats->lit_runs_after_long_match++);
359
                        LZO_STATS(lzo_stats->lit_run_after_long_match[t]++);
360
                        assert(ii - im <= MAX_MATCH_LONG);
361
                        assert((op[-1] >> LBITS) == 0);
362
                        op[-1] = LZO_BYTE(op[-1] | (t << LBITS));
363
                        MEMCPY_DS(op, ii, t);
364
                    }
365
                    else
366
#endif
367
92.4k
                    {
368
92.4k
                        LZO_STATS(lzo_stats->lit_runs++);
369
92.4k
                        LZO_STATS(lzo_stats->lit_run[t]++);
370
92.4k
                        *op++ = LZO_BYTE(t);
371
92.4k
                        MEMCPY_DS(op, ii, t);
372
92.4k
                        r1 = ip;                /* set new R1 pointer */
373
92.4k
                    }
374
92.4k
                }
375
11.1k
                else if (t < R0FAST)
376
5.99k
                {
377
                    /* inline the copying of a short R0 run */
378
5.99k
                    LZO_STATS(lzo_stats->r0short_runs++);
379
5.99k
                    *op++ = 0; *op++ = LZO_BYTE(t - R0MIN);
380
5.99k
                    MEMCPY_DS(op, ii, t);
381
5.99k
                    r1 = ip;                /* set new R1 pointer */
382
5.99k
                }
383
5.13k
                else
384
5.13k
                    op = store_run(op,ii,t);
385
111k
            }
386
#if (LBITS < 8)
387
            im = ip;
388
#endif
389
390
391
            /* 2) compute match len */
392
232k
            ii = ip;        /* point to start of current match */
393
394
            /* we already matched MIN_MATCH bytes,
395
             * m_pos also already advanced MIN_MATCH bytes */
396
232k
            ip += MIN_MATCH;
397
232k
            assert(m_pos < ip);
398
399
            /* try to match another MIN_MATCH_LONG - MIN_MATCH bytes
400
             * to see if we get a long match */
401
402
1.91M
#define PS  *m_pos++ != *ip++
403
404
#if (MIN_MATCH_LONG - MIN_MATCH == 2)                   /* MBITS == 2 */
405
            if (PS || PS)
406
#elif (MIN_MATCH_LONG - MIN_MATCH == 6)                 /* MBITS == 3 */
407
232k
            if (PS || PS || PS || PS || PS || PS)
408
#elif (MIN_MATCH_LONG - MIN_MATCH == 14)                /* MBITS == 4 */
409
            if (PS || PS || PS || PS || PS || PS || PS ||
410
                PS || PS || PS || PS || PS || PS || PS)
411
#elif (MIN_MATCH_LONG - MIN_MATCH == 30)                /* MBITS == 5 */
412
            if (PS || PS || PS || PS || PS || PS || PS || PS ||
413
                PS || PS || PS || PS || PS || PS || PS || PS ||
414
                PS || PS || PS || PS || PS || PS || PS || PS ||
415
                PS || PS || PS || PS || PS || PS)
416
#else
417
#  error "MBITS not yet implemented"
418
#endif
419
147k
            {
420
            /* we've found a short match */
421
147k
                lzo_uint m_len;
422
423
            /* 2a) compute match parameters */
424
147k
                    assert(ip-m_pos == (int)m_off);
425
147k
                --ip;   /* ran one too far, point back to non-match */
426
147k
                m_len = pd(ip, ii);
427
147k
                    assert(m_len >= MIN_MATCH_SHORT);
428
147k
                    assert(m_len <= MAX_MATCH_SHORT);
429
147k
                    assert(m_off >= MIN_OFFSET);
430
147k
                    assert(m_off <= MAX_OFFSET);
431
147k
                    assert(ii-m_off == m_pos_sav);
432
147k
                    assert(lzo_memcmp(m_pos_sav,ii,m_len) == 0);
433
147k
                m_off -= MIN_OFFSET;
434
435
            /* 2b) code a short match */
436
                /* code short match len + low offset bits */
437
147k
                *op++ = LZO_BYTE(((m_len - THRESHOLD) << OBITS) |
438
147k
                                 (m_off & OMASK));
439
                /* code high offset bits */
440
147k
                *op++ = LZO_BYTE(m_off >> OBITS);
441
442
443
#if (LZO_COLLECT_STATS)
444
                lzo_stats->short_matches++;
445
                lzo_stats->short_match[m_len]++;
446
                if (m_off < OSIZE)
447
                    lzo_stats->short_match_offset_osize[m_len]++;
448
                if (m_off < 256)
449
                    lzo_stats->short_match_offset_256[m_len]++;
450
                if (m_off < 1024)
451
                    lzo_stats->short_match_offset_1024[m_len]++;
452
#endif
453
454
455
            /* 2c) Insert phrases (beginning with ii+1) into the dictionary. */
456
457
147k
#define SI      /* nothing */
458
147k
#define DI      ++ii; DVAL_NEXT(dv,ii); UPDATE_D(dict,0,dv,ii,in);
459
232k
#define XI      assert(ii < ip); ii = ip; DVAL_FIRST(dv,(ip));
460
461
#if (CLEVEL == 9) || (CLEVEL >= 7 && MBITS <= 4) || (CLEVEL >= 5 && MBITS <= 3)
462
            /* Insert the whole match (ii+1)..(ip-1) into dictionary.  */
463
                ++ii;
464
                do {
465
                    DVAL_NEXT(dv,ii);
466
                    UPDATE_D(dict,0,dv,ii,in);
467
                } while (++ii < ip);
468
                DVAL_NEXT(dv,ii);
469
                assert(ii == ip);
470
                DVAL_ASSERT(dv,ip);
471
#elif (CLEVEL >= 3)
472
                SI   DI DI   XI
473
#elif (CLEVEL >= 2)
474
                SI   DI      XI
475
#else
476
147k
                             XI
477
147k
#endif
478
479
147k
            }
480
84.6k
            else
481
84.6k
            {
482
            /* we've found a long match - see how far we can still go */
483
84.6k
                const lzo_bytep end;
484
84.6k
                lzo_uint m_len;
485
486
84.6k
                assert(ip <= in_end);
487
84.6k
                assert(ii == ip - MIN_MATCH_LONG);
488
489
84.6k
                if (pd(in_end,ip) <= (MAX_MATCH_LONG - MIN_MATCH_LONG))
490
449
                    end = in_end;
491
84.1k
                else
492
84.1k
                {
493
84.1k
                    end = ip + (MAX_MATCH_LONG - MIN_MATCH_LONG);
494
84.1k
                    assert(end < in_end);
495
84.1k
                }
496
497
7.75M
                while (ip < end && *m_pos == *ip)
498
7.66M
                    { m_pos++; ip++; }
499
84.6k
                assert(ip <= in_end);
500
501
            /* 2a) compute match parameters */
502
84.6k
                m_len = pd(ip, ii);
503
84.6k
                    assert(m_len >= MIN_MATCH_LONG);
504
84.6k
                    assert(m_len <= MAX_MATCH_LONG);
505
84.6k
                    assert(m_off >= MIN_OFFSET);
506
84.6k
                    assert(m_off <= MAX_OFFSET);
507
84.6k
                    assert(ii-m_off == m_pos_sav);
508
84.6k
                    assert(lzo_memcmp(m_pos_sav,ii,m_len) == 0);
509
84.6k
                    assert(pd(ip,m_pos) == m_off);
510
84.6k
                m_off -= MIN_OFFSET;
511
512
            /* 2b) code the long match */
513
                /* code long match flag + low offset bits */
514
84.6k
                *op++ = LZO_BYTE(((MSIZE - 1) << OBITS) | (m_off & OMASK));
515
                /* code high offset bits */
516
84.6k
                *op++ = LZO_BYTE(m_off >> OBITS);
517
                /* code match len */
518
84.6k
                *op++ = LZO_BYTE(m_len - MIN_MATCH_LONG);
519
520
521
#if (LZO_COLLECT_STATS)
522
                lzo_stats->long_matches++;
523
                lzo_stats->long_match[m_len]++;
524
#endif
525
526
527
            /* 2c) Insert phrases (beginning with ii+1) into the dictionary. */
528
#if (CLEVEL == 9)
529
            /* Insert the whole match (ii+1)..(ip-1) into dictionary.  */
530
            /* This is not recommended because it is slow. */
531
                ++ii;
532
                do {
533
                    DVAL_NEXT(dv,ii);
534
                    UPDATE_D(dict,0,dv,ii,in);
535
                } while (++ii < ip);
536
                DVAL_NEXT(dv,ii);
537
                assert(ii == ip);
538
                DVAL_ASSERT(dv,ip);
539
#elif (CLEVEL >= 8)
540
                SI   DI DI DI DI DI DI DI DI   XI
541
#elif (CLEVEL >= 7)
542
                SI   DI DI DI DI DI DI DI      XI
543
#elif (CLEVEL >= 6)
544
                SI   DI DI DI DI DI DI         XI
545
#elif (CLEVEL >= 5)
546
                SI   DI DI DI DI               XI
547
#elif (CLEVEL >= 4)
548
                SI   DI DI DI                  XI
549
#elif (CLEVEL >= 3)
550
                SI   DI DI                     XI
551
#elif (CLEVEL >= 2)
552
                SI   DI                        XI
553
#else
554
84.6k
                                               XI
555
84.6k
#endif
556
84.6k
            }
557
558
            /* ii now points to the start of the next literal run */
559
232k
            assert(ii == ip);
560
232k
        }
561
562
14.8M
    } while (ip < ip_end);
563
564
541
    assert(ip <= in_end);
565
566
567
#if defined(LZO_RETURN_IF_NOT_COMPRESSIBLE)
568
    /* return -1 if op == out to indicate that we
569
     * couldn't compress and didn't copy anything.
570
     */
571
    if (op == out)
572
    {
573
        *out_len = 0;
574
        return LZO_E_NOT_COMPRESSIBLE;
575
    }
576
#endif
577
578
    /* store the final literal run */
579
541
    if (pd(in_end+DVAL_LEN,ii) > 0)
580
541
        op = store_run(op,ii,pd(in_end+DVAL_LEN,ii));
581
582
541
    *out_len = pd(op, out);
583
541
    return 0;               /* compression went ok */
584
541
}
585
586
587
/***********************************************************************
588
// LZO1A compress public entry point.
589
************************************************************************/
590
591
LZO_PUBLIC(int)
592
lzo1a_compress ( const lzo_bytep in , lzo_uint  in_len,
593
                       lzo_bytep out, lzo_uintp out_len,
594
                       lzo_voidp wrkmem )
595
549
{
596
549
    int r = LZO_E_OK;
597
598
599
#if (LZO_COLLECT_STATS)
600
    lzo_memset(lzo_stats,0,sizeof(*lzo_stats));
601
    lzo_stats->rbits  = RBITS;
602
    lzo_stats->clevel = CLEVEL;
603
    lzo_stats->dbits  = DBITS;
604
    lzo_stats->lbits  = LBITS;
605
    lzo_stats->min_match_short = MIN_MATCH_SHORT;
606
    lzo_stats->max_match_short = MAX_MATCH_SHORT;
607
    lzo_stats->min_match_long  = MIN_MATCH_LONG;
608
    lzo_stats->max_match_long  = MAX_MATCH_LONG;
609
    lzo_stats->min_offset      = MIN_OFFSET;
610
    lzo_stats->max_offset      = MAX_OFFSET;
611
    lzo_stats->r0min  = R0MIN;
612
    lzo_stats->r0fast = R0FAST;
613
    lzo_stats->r0max  = R0MAX;
614
    lzo_stats->in_len = in_len;
615
#endif
616
617
618
    /* don't try to compress a block that's too short */
619
549
    if (in_len == 0)
620
1
        *out_len = 0;
621
548
    else if (in_len <= MIN_MATCH_LONG + DVAL_LEN + 1)
622
7
    {
623
#if defined(LZO_RETURN_IF_NOT_COMPRESSIBLE)
624
        r = LZO_E_NOT_COMPRESSIBLE;
625
#else
626
7
        *out_len = pd(store_run(out,in,in_len), out);
627
7
#endif
628
7
    }
629
541
    else
630
541
        r = do_compress(in,in_len,out,out_len,wrkmem);
631
632
633
#if (LZO_COLLECT_STATS)
634
    lzo_stats->short_matches -= lzo_stats->r1_matches;
635
    lzo_stats->short_match[MIN_MATCH] -= lzo_stats->r1_matches;
636
    lzo_stats->out_len = *out_len;
637
#endif
638
639
549
    return r;
640
549
}
641
642
643
/* vim:set ts=4 sw=4 et: */