Coverage Report

Created: 2025-10-10 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/lzo-2.10/src/lzo1b_d.ch
Line
Count
Source
1
/* lzo1b_d.ch -- implementation of the LZO1B decompression 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 "lzo1_d.ch"
30
31
32
/***********************************************************************
33
// decompress a block of data.
34
************************************************************************/
35
36
LZO_PUBLIC(int)
37
DO_DECOMPRESS    ( const lzo_bytep in , lzo_uint  in_len,
38
                         lzo_bytep out, lzo_uintp out_len,
39
                         lzo_voidp wrkmem )
40
973
{
41
973
    lzo_bytep op;
42
973
    const lzo_bytep ip;
43
973
    lzo_uint t;
44
973
    const lzo_bytep m_pos;
45
46
973
    const lzo_bytep const ip_end = in + in_len;
47
973
#if defined(HAVE_ANY_OP)
48
973
    lzo_bytep const op_end = out + *out_len;
49
973
#endif
50
51
973
    LZO_UNUSED(wrkmem);
52
53
973
    op = out;
54
973
    ip = in;
55
56
973
    while (TEST_IP_AND_TEST_OP)
57
154k
    {
58
154k
        t = *ip++;      /* get marker */
59
60
154k
        if (t < R0MIN)      /* a literal run */
61
39.3k
        {
62
39.3k
            if (t == 0)             /* a R0 literal run */
63
14.5k
            {
64
14.5k
                NEED_IP(1);
65
14.5k
                t = *ip++;
66
14.5k
                if (t >= R0FAST - R0MIN)            /* a long R0 run */
67
2.06k
                {
68
2.06k
                    t -= R0FAST - R0MIN;
69
2.06k
                    if (t == 0)
70
1.10k
                        t = R0FAST;
71
957
                    else
72
957
                    {
73
#if 0
74
                        t = 256u << ((unsigned) t);
75
#else
76
                        /* help the optimizer */
77
957
                        lzo_uint tt = 256;
78
1.73k
                        do tt <<= 1; while (--t > 0);
79
957
                        t = tt;
80
957
#endif
81
957
                    }
82
83
2.06k
                    NEED_IP(t); NEED_OP(t);
84
1.96k
#if 1 && (LZO_OPT_UNALIGNED32)
85
234k
                    do {
86
234k
                        UA_COPY4(op+0, ip+0);
87
234k
                        UA_COPY4(op+4, ip+4);
88
234k
                        op += 8; ip += 8;
89
234k
                        t -= 8;
90
234k
                    } while (t > 0);
91
#else
92
                    MEMCPY8_DS(op,ip,t);
93
#endif
94
1.96k
                    continue;
95
1.96k
                }
96
12.5k
                t += R0MIN;                         /* a short R0 run */
97
12.5k
            }
98
99
37.2k
            NEED_IP(t); NEED_OP(t);
100
            /* copy literal run */
101
37.1k
#if 1 && (LZO_OPT_UNALIGNED32)
102
37.1k
            if (t >= 4)
103
23.0k
            {
104
143k
                do {
105
143k
                    UA_COPY4(op, ip);
106
143k
                    op += 4; ip += 4; t -= 4;
107
143k
                } while (t >= 4);
108
23.0k
                if (t > 0) do *op++ = *ip++; while (--t > 0);
109
23.0k
            }
110
14.0k
            else
111
14.0k
#endif
112
14.0k
            {
113
#if (M3O_BITS < 7)
114
17.7k
literal1:
115
17.7k
#endif
116
41.1k
                do *op++ = *ip++; while (--t > 0);
117
17.7k
            }
118
119
#if (M3O_BITS == 7)
120
literal2:
121
#endif
122
123
            /* after a literal a match must follow */
124
37.1k
            while (TEST_IP_AND_TEST_OP)
125
515k
            {
126
515k
                t = *ip++;          /* get R1 marker */
127
515k
                if (t >= R0MIN)
128
47.7k
                    goto match;
129
130
467k
                NEED_IP(2); NEED_OP(M2_MIN_LEN + 1);
131
132
            /* R1 match - a M2_MIN_LEN match + 1 byte literal */
133
467k
                assert((t & M2O_MASK) == t);
134
467k
                m_pos = op - M2_MIN_OFFSET;
135
467k
                m_pos -= t | (((lzo_uint) *ip++) << M2O_BITS);
136
467k
                assert(m_pos >= out); assert(m_pos < op);
137
467k
                TEST_LB(m_pos);
138
467k
                COPY_M2;
139
467k
                *op++ = *ip++;
140
467k
            }
141
142
53
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
143
53
            break;
144
35.8k
#endif
145
35.8k
        }
146
147
163k
match:
148
149
163k
        if (t >= M2_MARKER)             /* a M2 match */
150
126k
        {
151
            /* get match offset */
152
126k
            NEED_IP(1);
153
126k
            m_pos = op - M2_MIN_OFFSET;
154
126k
            m_pos -= (t & M2O_MASK) | (((lzo_uint) *ip++) << M2O_BITS);
155
126k
            assert(m_pos >= out); assert(m_pos < op);
156
126k
            TEST_LB(m_pos);
157
158
            /* get match len */
159
126k
            t = (t >> M2O_BITS) - 1;
160
126k
            NEED_OP(t + M2_MIN_LEN - 1);
161
126k
            COPY_M2X;
162
126k
            MEMCPY_DS(op,m_pos,t);
163
126k
        }
164
36.2k
        else                            /* a M3 or M4 match */
165
36.2k
        {
166
            /* get match len */
167
36.2k
            t &= M3L_MASK;
168
36.2k
            if (t == 0)         /* a M4 match */
169
2.50k
            {
170
2.50k
                NEED_IP(1);
171
2.44M
                while (*ip == 0)
172
2.43M
                {
173
2.43M
                    t += 255;
174
2.43M
                    ip++;
175
2.43M
                    TEST_OV(t);
176
2.43M
                    NEED_IP(1);
177
2.43M
                }
178
2.46k
                t += (M4_MIN_LEN - M3_MIN_LEN) + *ip++;
179
2.46k
            }
180
181
            /* get match offset */
182
36.2k
            NEED_IP(2);
183
36.1k
            m_pos = op - (M3_MIN_OFFSET - M3_EOF_OFFSET);
184
36.1k
            m_pos -= *ip++ & M3O_MASK;
185
36.1k
            m_pos -= (lzo_uint)(*ip++) << M3O_BITS;
186
36.1k
#if defined(LZO_EOF_CODE)
187
36.1k
            if (m_pos == op)
188
64
                goto eof_found;
189
36.1k
#endif
190
191
            /* copy match */
192
36.1k
            assert(m_pos >= out); assert(m_pos < op);
193
36.1k
            TEST_LB(m_pos); NEED_OP(t + M3_MIN_LEN - 1);
194
35.9k
#if (LZO_OPT_UNALIGNED32)
195
35.9k
            if (t >= 2 * 4 - (M3_MIN_LEN - 1) && (op - m_pos) >= 4)
196
31.7k
            {
197
31.7k
                UA_COPY4(op, m_pos);
198
31.7k
                op += 4; m_pos += 4; t -= 4 - (M3_MIN_LEN - 1);
199
4.27M
                do {
200
4.27M
                    UA_COPY4(op, m_pos);
201
4.27M
                    op += 4; m_pos += 4; t -= 4;
202
4.27M
                } while (t >= 4);
203
40.6k
                if (t > 0) do *op++ = *m_pos++; while (--t > 0);
204
31.7k
            }
205
4.25k
            else
206
4.25k
#endif
207
4.25k
            {
208
4.25k
            COPY_M3X;
209
4.25k
            MEMCPY_DS(op,m_pos,t);
210
4.25k
            }
211
212
213
#if (M3O_BITS < 7)
214
26.9k
            t = ip[-2] >> M3O_BITS;
215
26.9k
            if (t)
216
10.8k
            {
217
10.8k
                NEED_IP(t); NEED_OP(t);
218
10.8k
                goto literal1;
219
10.8k
            }
220
#elif (M3O_BITS == 7)
221
            /* optimized version */
222
            if (ip[-2] & (1 << M3O_BITS))
223
            {
224
                NEED_IP(1); NEED_OP(1);
225
                *op++ = *ip++;
226
                goto literal2;
227
            }
228
#endif
229
35.9k
        }
230
163k
    }
231
232
233
131
#if defined(LZO_EOF_CODE)
234
131
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
235
    /* no EOF code was found */
236
131
    *out_len = pd(op, out);
237
131
    return LZO_E_EOF_NOT_FOUND;
238
0
#endif
239
240
64
eof_found:
241
64
    assert(t == 1);
242
64
#endif
243
64
    *out_len = pd(op, out);
244
64
    return (ip == ip_end ? LZO_E_OK :
245
64
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
246
247
248
0
#if defined(HAVE_NEED_IP)
249
439
input_overrun:
250
439
    *out_len = pd(op, out);
251
439
    return LZO_E_INPUT_OVERRUN;
252
0
#endif
253
254
0
#if defined(HAVE_NEED_OP)
255
57
output_overrun:
256
57
    *out_len = pd(op, out);
257
57
    return LZO_E_OUTPUT_OVERRUN;
258
0
#endif
259
260
0
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
261
282
lookbehind_overrun:
262
282
    *out_len = pd(op, out);
263
282
    return LZO_E_LOOKBEHIND_OVERRUN;
264
973
#endif
265
973
}
lzo1b_decompress_safe
Line
Count
Source
40
467
{
41
467
    lzo_bytep op;
42
467
    const lzo_bytep ip;
43
467
    lzo_uint t;
44
467
    const lzo_bytep m_pos;
45
46
467
    const lzo_bytep const ip_end = in + in_len;
47
467
#if defined(HAVE_ANY_OP)
48
467
    lzo_bytep const op_end = out + *out_len;
49
467
#endif
50
51
467
    LZO_UNUSED(wrkmem);
52
53
467
    op = out;
54
467
    ip = in;
55
56
467
    while (TEST_IP_AND_TEST_OP)
57
56.6k
    {
58
56.6k
        t = *ip++;      /* get marker */
59
60
56.6k
        if (t < R0MIN)      /* a literal run */
61
13.1k
        {
62
13.1k
            if (t == 0)             /* a R0 literal run */
63
1.97k
            {
64
1.97k
                NEED_IP(1);
65
1.96k
                t = *ip++;
66
1.96k
                if (t >= R0FAST - R0MIN)            /* a long R0 run */
67
926
                {
68
926
                    t -= R0FAST - R0MIN;
69
926
                    if (t == 0)
70
506
                        t = R0FAST;
71
420
                    else
72
420
                    {
73
#if 0
74
                        t = 256u << ((unsigned) t);
75
#else
76
                        /* help the optimizer */
77
420
                        lzo_uint tt = 256;
78
709
                        do tt <<= 1; while (--t > 0);
79
420
                        t = tt;
80
420
#endif
81
420
                    }
82
83
926
                    NEED_IP(t); NEED_OP(t);
84
879
#if 1 && (LZO_OPT_UNALIGNED32)
85
74.4k
                    do {
86
74.4k
                        UA_COPY4(op+0, ip+0);
87
74.4k
                        UA_COPY4(op+4, ip+4);
88
74.4k
                        op += 8; ip += 8;
89
74.4k
                        t -= 8;
90
74.4k
                    } while (t > 0);
91
#else
92
                    MEMCPY8_DS(op,ip,t);
93
#endif
94
879
                    continue;
95
882
                }
96
1.04k
                t += R0MIN;                         /* a short R0 run */
97
1.04k
            }
98
99
12.1k
            NEED_IP(t); NEED_OP(t);
100
            /* copy literal run */
101
12.1k
#if 1 && (LZO_OPT_UNALIGNED32)
102
12.1k
            if (t >= 4)
103
4.95k
            {
104
21.2k
                do {
105
21.2k
                    UA_COPY4(op, ip);
106
21.2k
                    op += 4; ip += 4; t -= 4;
107
21.2k
                } while (t >= 4);
108
4.95k
                if (t > 0) do *op++ = *ip++; while (--t > 0);
109
4.95k
            }
110
7.16k
            else
111
7.16k
#endif
112
7.16k
            {
113
#if (M3O_BITS < 7)
114
literal1:
115
#endif
116
12.7k
                do *op++ = *ip++; while (--t > 0);
117
7.16k
            }
118
119
#if (M3O_BITS == 7)
120
literal2:
121
#endif
122
123
            /* after a literal a match must follow */
124
12.1k
            while (TEST_IP_AND_TEST_OP)
125
141k
            {
126
141k
                t = *ip++;          /* get R1 marker */
127
141k
                if (t >= R0MIN)
128
12.0k
                    goto match;
129
130
129k
                NEED_IP(2); NEED_OP(M2_MIN_LEN + 1);
131
132
            /* R1 match - a M2_MIN_LEN match + 1 byte literal */
133
129k
                assert((t & M2O_MASK) == t);
134
129k
                m_pos = op - M2_MIN_OFFSET;
135
129k
                m_pos -= t | (((lzo_uint) *ip++) << M2O_BITS);
136
129k
                assert(m_pos >= out); assert(m_pos < op);
137
129k
                TEST_LB(m_pos);
138
129k
                COPY_M2;
139
129k
                *op++ = *ip++;
140
129k
            }
141
142
19
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
143
19
            break;
144
12.1k
#endif
145
12.1k
        }
146
147
55.5k
match:
148
149
55.5k
        if (t >= M2_MARKER)             /* a M2 match */
150
46.3k
        {
151
            /* get match offset */
152
46.3k
            NEED_IP(1);
153
46.3k
            m_pos = op - M2_MIN_OFFSET;
154
46.3k
            m_pos -= (t & M2O_MASK) | (((lzo_uint) *ip++) << M2O_BITS);
155
46.3k
            assert(m_pos >= out); assert(m_pos < op);
156
46.3k
            TEST_LB(m_pos);
157
158
            /* get match len */
159
46.3k
            t = (t >> M2O_BITS) - 1;
160
46.3k
            NEED_OP(t + M2_MIN_LEN - 1);
161
46.3k
            COPY_M2X;
162
46.3k
            MEMCPY_DS(op,m_pos,t);
163
46.3k
        }
164
9.21k
        else                            /* a M3 or M4 match */
165
9.21k
        {
166
            /* get match len */
167
9.21k
            t &= M3L_MASK;
168
9.21k
            if (t == 0)         /* a M4 match */
169
717
            {
170
717
                NEED_IP(1);
171
1.05M
                while (*ip == 0)
172
1.05M
                {
173
1.05M
                    t += 255;
174
1.05M
                    ip++;
175
1.05M
                    TEST_OV(t);
176
1.05M
                    NEED_IP(1);
177
1.05M
                }
178
697
                t += (M4_MIN_LEN - M3_MIN_LEN) + *ip++;
179
697
            }
180
181
            /* get match offset */
182
9.19k
            NEED_IP(2);
183
9.17k
            m_pos = op - (M3_MIN_OFFSET - M3_EOF_OFFSET);
184
9.17k
            m_pos -= *ip++ & M3O_MASK;
185
9.17k
            m_pos -= (lzo_uint)(*ip++) << M3O_BITS;
186
9.17k
#if defined(LZO_EOF_CODE)
187
9.17k
            if (m_pos == op)
188
36
                goto eof_found;
189
9.13k
#endif
190
191
            /* copy match */
192
9.17k
            assert(m_pos >= out); assert(m_pos < op);
193
9.13k
            TEST_LB(m_pos); NEED_OP(t + M3_MIN_LEN - 1);
194
9.06k
#if (LZO_OPT_UNALIGNED32)
195
9.06k
            if (t >= 2 * 4 - (M3_MIN_LEN - 1) && (op - m_pos) >= 4)
196
8.09k
            {
197
8.09k
                UA_COPY4(op, m_pos);
198
8.09k
                op += 4; m_pos += 4; t -= 4 - (M3_MIN_LEN - 1);
199
1.95M
                do {
200
1.95M
                    UA_COPY4(op, m_pos);
201
1.95M
                    op += 4; m_pos += 4; t -= 4;
202
1.95M
                } while (t >= 4);
203
10.9k
                if (t > 0) do *op++ = *m_pos++; while (--t > 0);
204
8.09k
            }
205
964
            else
206
964
#endif
207
964
            {
208
964
            COPY_M3X;
209
964
            MEMCPY_DS(op,m_pos,t);
210
964
            }
211
212
213
#if (M3O_BITS < 7)
214
            t = ip[-2] >> M3O_BITS;
215
            if (t)
216
            {
217
                NEED_IP(t); NEED_OP(t);
218
                goto literal1;
219
            }
220
#elif (M3O_BITS == 7)
221
            /* optimized version */
222
            if (ip[-2] & (1 << M3O_BITS))
223
            {
224
                NEED_IP(1); NEED_OP(1);
225
                *op++ = *ip++;
226
                goto literal2;
227
            }
228
#endif
229
9.06k
        }
230
55.5k
    }
231
232
233
61
#if defined(LZO_EOF_CODE)
234
61
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
235
    /* no EOF code was found */
236
61
    *out_len = pd(op, out);
237
61
    return LZO_E_EOF_NOT_FOUND;
238
0
#endif
239
240
36
eof_found:
241
36
    assert(t == 1);
242
36
#endif
243
36
    *out_len = pd(op, out);
244
36
    return (ip == ip_end ? LZO_E_OK :
245
36
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
246
247
248
0
#if defined(HAVE_NEED_IP)
249
202
input_overrun:
250
202
    *out_len = pd(op, out);
251
202
    return LZO_E_INPUT_OVERRUN;
252
0
#endif
253
254
0
#if defined(HAVE_NEED_OP)
255
24
output_overrun:
256
24
    *out_len = pd(op, out);
257
24
    return LZO_E_OUTPUT_OVERRUN;
258
0
#endif
259
260
0
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
261
144
lookbehind_overrun:
262
144
    *out_len = pd(op, out);
263
144
    return LZO_E_LOOKBEHIND_OVERRUN;
264
467
#endif
265
467
}
lzo1c_decompress_safe
Line
Count
Source
40
506
{
41
506
    lzo_bytep op;
42
506
    const lzo_bytep ip;
43
506
    lzo_uint t;
44
506
    const lzo_bytep m_pos;
45
46
506
    const lzo_bytep const ip_end = in + in_len;
47
506
#if defined(HAVE_ANY_OP)
48
506
    lzo_bytep const op_end = out + *out_len;
49
506
#endif
50
51
506
    LZO_UNUSED(wrkmem);
52
53
506
    op = out;
54
506
    ip = in;
55
56
506
    while (TEST_IP_AND_TEST_OP)
57
97.9k
    {
58
97.9k
        t = *ip++;      /* get marker */
59
60
97.9k
        if (t < R0MIN)      /* a literal run */
61
26.2k
        {
62
26.2k
            if (t == 0)             /* a R0 literal run */
63
12.6k
            {
64
12.6k
                NEED_IP(1);
65
12.6k
                t = *ip++;
66
12.6k
                if (t >= R0FAST - R0MIN)            /* a long R0 run */
67
1.13k
                {
68
1.13k
                    t -= R0FAST - R0MIN;
69
1.13k
                    if (t == 0)
70
597
                        t = R0FAST;
71
537
                    else
72
537
                    {
73
#if 0
74
                        t = 256u << ((unsigned) t);
75
#else
76
                        /* help the optimizer */
77
537
                        lzo_uint tt = 256;
78
1.02k
                        do tt <<= 1; while (--t > 0);
79
537
                        t = tt;
80
537
#endif
81
537
                    }
82
83
1.13k
                    NEED_IP(t); NEED_OP(t);
84
1.08k
#if 1 && (LZO_OPT_UNALIGNED32)
85
159k
                    do {
86
159k
                        UA_COPY4(op+0, ip+0);
87
159k
                        UA_COPY4(op+4, ip+4);
88
159k
                        op += 8; ip += 8;
89
159k
                        t -= 8;
90
159k
                    } while (t > 0);
91
#else
92
                    MEMCPY8_DS(op,ip,t);
93
#endif
94
1.08k
                    continue;
95
1.08k
                }
96
11.4k
                t += R0MIN;                         /* a short R0 run */
97
11.4k
            }
98
99
25.0k
            NEED_IP(t); NEED_OP(t);
100
            /* copy literal run */
101
24.9k
#if 1 && (LZO_OPT_UNALIGNED32)
102
24.9k
            if (t >= 4)
103
18.0k
            {
104
121k
                do {
105
121k
                    UA_COPY4(op, ip);
106
121k
                    op += 4; ip += 4; t -= 4;
107
121k
                } while (t >= 4);
108
18.0k
                if (t > 0) do *op++ = *ip++; while (--t > 0);
109
18.0k
            }
110
6.92k
            else
111
6.92k
#endif
112
6.92k
            {
113
6.92k
#if (M3O_BITS < 7)
114
17.7k
literal1:
115
17.7k
#endif
116
28.4k
                do *op++ = *ip++; while (--t > 0);
117
17.7k
            }
118
119
#if (M3O_BITS == 7)
120
literal2:
121
#endif
122
123
            /* after a literal a match must follow */
124
35.8k
            while (TEST_IP_AND_TEST_OP)
125
373k
            {
126
373k
                t = *ip++;          /* get R1 marker */
127
373k
                if (t >= R0MIN)
128
35.7k
                    goto match;
129
130
337k
                NEED_IP(2); NEED_OP(M2_MIN_LEN + 1);
131
132
            /* R1 match - a M2_MIN_LEN match + 1 byte literal */
133
337k
                assert((t & M2O_MASK) == t);
134
337k
                m_pos = op - M2_MIN_OFFSET;
135
337k
                m_pos -= t | (((lzo_uint) *ip++) << M2O_BITS);
136
337k
                assert(m_pos >= out); assert(m_pos < op);
137
337k
                TEST_LB(m_pos);
138
337k
                COPY_M2;
139
337k
                *op++ = *ip++;
140
337k
            }
141
142
34
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
143
34
            break;
144
35.8k
#endif
145
35.8k
        }
146
147
107k
match:
148
149
107k
        if (t >= M2_MARKER)             /* a M2 match */
150
80.4k
        {
151
            /* get match offset */
152
80.4k
            NEED_IP(1);
153
80.4k
            m_pos = op - M2_MIN_OFFSET;
154
80.4k
            m_pos -= (t & M2O_MASK) | (((lzo_uint) *ip++) << M2O_BITS);
155
80.4k
            assert(m_pos >= out); assert(m_pos < op);
156
80.4k
            TEST_LB(m_pos);
157
158
            /* get match len */
159
80.3k
            t = (t >> M2O_BITS) - 1;
160
80.3k
            NEED_OP(t + M2_MIN_LEN - 1);
161
80.3k
            COPY_M2X;
162
80.3k
            MEMCPY_DS(op,m_pos,t);
163
80.3k
        }
164
27.0k
        else                            /* a M3 or M4 match */
165
27.0k
        {
166
            /* get match len */
167
27.0k
            t &= M3L_MASK;
168
27.0k
            if (t == 0)         /* a M4 match */
169
1.78k
            {
170
1.78k
                NEED_IP(1);
171
1.38M
                while (*ip == 0)
172
1.38M
                {
173
1.38M
                    t += 255;
174
1.38M
                    ip++;
175
1.38M
                    TEST_OV(t);
176
1.38M
                    NEED_IP(1);
177
1.38M
                }
178
1.76k
                t += (M4_MIN_LEN - M3_MIN_LEN) + *ip++;
179
1.76k
            }
180
181
            /* get match offset */
182
27.0k
            NEED_IP(2);
183
27.0k
            m_pos = op - (M3_MIN_OFFSET - M3_EOF_OFFSET);
184
27.0k
            m_pos -= *ip++ & M3O_MASK;
185
27.0k
            m_pos -= (lzo_uint)(*ip++) << M3O_BITS;
186
27.0k
#if defined(LZO_EOF_CODE)
187
27.0k
            if (m_pos == op)
188
28
                goto eof_found;
189
26.9k
#endif
190
191
            /* copy match */
192
27.0k
            assert(m_pos >= out); assert(m_pos < op);
193
26.9k
            TEST_LB(m_pos); NEED_OP(t + M3_MIN_LEN - 1);
194
26.9k
#if (LZO_OPT_UNALIGNED32)
195
26.9k
            if (t >= 2 * 4 - (M3_MIN_LEN - 1) && (op - m_pos) >= 4)
196
23.6k
            {
197
23.6k
                UA_COPY4(op, m_pos);
198
23.6k
                op += 4; m_pos += 4; t -= 4 - (M3_MIN_LEN - 1);
199
2.31M
                do {
200
2.31M
                    UA_COPY4(op, m_pos);
201
2.31M
                    op += 4; m_pos += 4; t -= 4;
202
2.31M
                } while (t >= 4);
203
29.7k
                if (t > 0) do *op++ = *m_pos++; while (--t > 0);
204
23.6k
            }
205
3.28k
            else
206
3.28k
#endif
207
3.28k
            {
208
3.28k
            COPY_M3X;
209
3.28k
            MEMCPY_DS(op,m_pos,t);
210
3.28k
            }
211
212
213
26.9k
#if (M3O_BITS < 7)
214
26.9k
            t = ip[-2] >> M3O_BITS;
215
26.9k
            if (t)
216
10.8k
            {
217
10.8k
                NEED_IP(t); NEED_OP(t);
218
10.8k
                goto literal1;
219
10.8k
            }
220
#elif (M3O_BITS == 7)
221
            /* optimized version */
222
            if (ip[-2] & (1 << M3O_BITS))
223
            {
224
                NEED_IP(1); NEED_OP(1);
225
                *op++ = *ip++;
226
                goto literal2;
227
            }
228
#endif
229
26.9k
        }
230
107k
    }
231
232
233
70
#if defined(LZO_EOF_CODE)
234
70
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
235
    /* no EOF code was found */
236
70
    *out_len = pd(op, out);
237
70
    return LZO_E_EOF_NOT_FOUND;
238
0
#endif
239
240
28
eof_found:
241
28
    assert(t == 1);
242
28
#endif
243
28
    *out_len = pd(op, out);
244
28
    return (ip == ip_end ? LZO_E_OK :
245
28
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
246
247
248
0
#if defined(HAVE_NEED_IP)
249
237
input_overrun:
250
237
    *out_len = pd(op, out);
251
237
    return LZO_E_INPUT_OVERRUN;
252
0
#endif
253
254
0
#if defined(HAVE_NEED_OP)
255
33
output_overrun:
256
33
    *out_len = pd(op, out);
257
33
    return LZO_E_OUTPUT_OVERRUN;
258
0
#endif
259
260
0
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
261
138
lookbehind_overrun:
262
138
    *out_len = pd(op, out);
263
138
    return LZO_E_LOOKBEHIND_OVERRUN;
264
506
#endif
265
506
}
266
267
268
/* vim:set ts=4 sw=4 et: */