Coverage Report

Created: 2025-11-24 06:26

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
918
{
41
918
    lzo_bytep op;
42
918
    const lzo_bytep ip;
43
918
    lzo_uint t;
44
918
    const lzo_bytep m_pos;
45
46
918
    const lzo_bytep const ip_end = in + in_len;
47
918
#if defined(HAVE_ANY_OP)
48
918
    lzo_bytep const op_end = out + *out_len;
49
918
#endif
50
51
918
    LZO_UNUSED(wrkmem);
52
53
918
    op = out;
54
918
    ip = in;
55
56
918
    while (TEST_IP_AND_TEST_OP)
57
224k
    {
58
224k
        t = *ip++;      /* get marker */
59
60
224k
        if (t < R0MIN)      /* a literal run */
61
56.4k
        {
62
56.4k
            if (t == 0)             /* a R0 literal run */
63
9.84k
            {
64
9.84k
                NEED_IP(1);
65
9.83k
                t = *ip++;
66
9.83k
                if (t >= R0FAST - R0MIN)            /* a long R0 run */
67
2.96k
                {
68
2.96k
                    t -= R0FAST - R0MIN;
69
2.96k
                    if (t == 0)
70
1.70k
                        t = R0FAST;
71
1.26k
                    else
72
1.26k
                    {
73
#if 0
74
                        t = 256u << ((unsigned) t);
75
#else
76
                        /* help the optimizer */
77
1.26k
                        lzo_uint tt = 256;
78
2.15k
                        do tt <<= 1; while (--t > 0);
79
1.26k
                        t = tt;
80
1.26k
#endif
81
1.26k
                    }
82
83
2.96k
                    NEED_IP(t); NEED_OP(t);
84
2.85k
#if 1 && (LZO_OPT_UNALIGNED32)
85
334k
                    do {
86
334k
                        UA_COPY4(op+0, ip+0);
87
334k
                        UA_COPY4(op+4, ip+4);
88
334k
                        op += 8; ip += 8;
89
334k
                        t -= 8;
90
334k
                    } while (t > 0);
91
#else
92
                    MEMCPY8_DS(op,ip,t);
93
#endif
94
2.85k
                    continue;
95
2.86k
                }
96
6.86k
                t += R0MIN;                         /* a short R0 run */
97
6.86k
            }
98
99
53.4k
            NEED_IP(t); NEED_OP(t);
100
            /* copy literal run */
101
53.3k
#if 1 && (LZO_OPT_UNALIGNED32)
102
53.3k
            if (t >= 4)
103
35.6k
            {
104
149k
                do {
105
149k
                    UA_COPY4(op, ip);
106
149k
                    op += 4; ip += 4; t -= 4;
107
149k
                } while (t >= 4);
108
36.9k
                if (t > 0) do *op++ = *ip++; while (--t > 0);
109
35.6k
            }
110
17.6k
            else
111
17.6k
#endif
112
17.6k
            {
113
#if (M3O_BITS < 7)
114
31.4k
literal1:
115
31.4k
#endif
116
72.5k
                do *op++ = *ip++; while (--t > 0);
117
31.4k
            }
118
119
#if (M3O_BITS == 7)
120
literal2:
121
#endif
122
123
            /* after a literal a match must follow */
124
54.9k
            while (TEST_IP_AND_TEST_OP)
125
604k
            {
126
604k
                t = *ip++;          /* get R1 marker */
127
604k
                if (t >= R0MIN)
128
79.3k
                    goto match;
129
130
525k
                NEED_IP(2); NEED_OP(M2_MIN_LEN + 1);
131
132
            /* R1 match - a M2_MIN_LEN match + 1 byte literal */
133
525k
                assert((t & M2O_MASK) == t);
134
525k
                m_pos = op - M2_MIN_OFFSET;
135
525k
                m_pos -= t | (((lzo_uint) *ip++) << M2O_BITS);
136
525k
                assert(m_pos >= out); assert(m_pos < op);
137
525k
                TEST_LB(m_pos);
138
525k
                COPY_M2;
139
525k
                *op++ = *ip++;
140
525k
            }
141
142
53
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
143
53
            break;
144
54.9k
#endif
145
54.9k
        }
146
147
247k
match:
148
149
247k
        if (t >= M2_MARKER)             /* a M2 match */
150
173k
        {
151
            /* get match offset */
152
173k
            NEED_IP(1);
153
173k
            m_pos = op - M2_MIN_OFFSET;
154
173k
            m_pos -= (t & M2O_MASK) | (((lzo_uint) *ip++) << M2O_BITS);
155
173k
            assert(m_pos >= out); assert(m_pos < op);
156
173k
            TEST_LB(m_pos);
157
158
            /* get match len */
159
173k
            t = (t >> M2O_BITS) - 1;
160
173k
            NEED_OP(t + M2_MIN_LEN - 1);
161
173k
            COPY_M2X;
162
173k
            MEMCPY_DS(op,m_pos,t);
163
173k
        }
164
73.3k
        else                            /* a M3 or M4 match */
165
73.3k
        {
166
            /* get match len */
167
73.3k
            t &= M3L_MASK;
168
73.3k
            if (t == 0)         /* a M4 match */
169
21.0k
            {
170
21.0k
                NEED_IP(1);
171
2.56M
                while (*ip == 0)
172
2.54M
                {
173
2.54M
                    t += 255;
174
2.54M
                    ip++;
175
2.54M
                    TEST_OV(t);
176
2.54M
                    NEED_IP(1);
177
2.54M
                }
178
20.9k
                t += (M4_MIN_LEN - M3_MIN_LEN) + *ip++;
179
20.9k
            }
180
181
            /* get match offset */
182
73.3k
            NEED_IP(2);
183
73.2k
            m_pos = op - (M3_MIN_OFFSET - M3_EOF_OFFSET);
184
73.2k
            m_pos -= *ip++ & M3O_MASK;
185
73.2k
            m_pos -= (lzo_uint)(*ip++) << M3O_BITS;
186
73.2k
#if defined(LZO_EOF_CODE)
187
73.2k
            if (m_pos == op)
188
51
                goto eof_found;
189
73.2k
#endif
190
191
            /* copy match */
192
73.2k
            assert(m_pos >= out); assert(m_pos < op);
193
73.2k
            TEST_LB(m_pos); NEED_OP(t + M3_MIN_LEN - 1);
194
73.0k
#if (LZO_OPT_UNALIGNED32)
195
73.0k
            if (t >= 2 * 4 - (M3_MIN_LEN - 1) && (op - m_pos) >= 4)
196
63.6k
            {
197
63.6k
                UA_COPY4(op, m_pos);
198
63.6k
                op += 4; m_pos += 4; t -= 4 - (M3_MIN_LEN - 1);
199
3.59M
                do {
200
3.59M
                    UA_COPY4(op, m_pos);
201
3.59M
                    op += 4; m_pos += 4; t -= 4;
202
3.59M
                } while (t >= 4);
203
86.9k
                if (t > 0) do *op++ = *m_pos++; while (--t > 0);
204
63.6k
            }
205
9.41k
            else
206
9.41k
#endif
207
9.41k
            {
208
9.41k
            COPY_M3X;
209
9.41k
            MEMCPY_DS(op,m_pos,t);
210
9.41k
            }
211
212
213
#if (M3O_BITS < 7)
214
52.9k
            t = ip[-2] >> M3O_BITS;
215
52.9k
            if (t)
216
26.1k
            {
217
26.1k
                NEED_IP(t); NEED_OP(t);
218
26.1k
                goto literal1;
219
26.1k
            }
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
73.0k
        }
230
247k
    }
231
232
233
128
#if defined(LZO_EOF_CODE)
234
128
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
235
    /* no EOF code was found */
236
128
    *out_len = pd(op, out);
237
128
    return LZO_E_EOF_NOT_FOUND;
238
0
#endif
239
240
51
eof_found:
241
51
    assert(t == 1);
242
51
#endif
243
51
    *out_len = pd(op, out);
244
51
    return (ip == ip_end ? LZO_E_OK :
245
51
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
246
247
248
0
#if defined(HAVE_NEED_IP)
249
413
input_overrun:
250
413
    *out_len = pd(op, out);
251
413
    return LZO_E_INPUT_OVERRUN;
252
0
#endif
253
254
0
#if defined(HAVE_NEED_OP)
255
69
output_overrun:
256
69
    *out_len = pd(op, out);
257
69
    return LZO_E_OUTPUT_OVERRUN;
258
0
#endif
259
260
0
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
261
257
lookbehind_overrun:
262
257
    *out_len = pd(op, out);
263
257
    return LZO_E_LOOKBEHIND_OVERRUN;
264
918
#endif
265
918
}
lzo1b_decompress_safe
Line
Count
Source
40
434
{
41
434
    lzo_bytep op;
42
434
    const lzo_bytep ip;
43
434
    lzo_uint t;
44
434
    const lzo_bytep m_pos;
45
46
434
    const lzo_bytep const ip_end = in + in_len;
47
434
#if defined(HAVE_ANY_OP)
48
434
    lzo_bytep const op_end = out + *out_len;
49
434
#endif
50
51
434
    LZO_UNUSED(wrkmem);
52
53
434
    op = out;
54
434
    ip = in;
55
56
434
    while (TEST_IP_AND_TEST_OP)
57
97.0k
    {
58
97.0k
        t = *ip++;      /* get marker */
59
60
97.0k
        if (t < R0MIN)      /* a literal run */
61
26.1k
        {
62
26.1k
            if (t == 0)             /* a R0 literal run */
63
4.10k
            {
64
4.10k
                NEED_IP(1);
65
4.09k
                t = *ip++;
66
4.09k
                if (t >= R0FAST - R0MIN)            /* a long R0 run */
67
1.50k
                {
68
1.50k
                    t -= R0FAST - R0MIN;
69
1.50k
                    if (t == 0)
70
1.04k
                        t = R0FAST;
71
463
                    else
72
463
                    {
73
#if 0
74
                        t = 256u << ((unsigned) t);
75
#else
76
                        /* help the optimizer */
77
463
                        lzo_uint tt = 256;
78
877
                        do tt <<= 1; while (--t > 0);
79
463
                        t = tt;
80
463
#endif
81
463
                    }
82
83
1.50k
                    NEED_IP(t); NEED_OP(t);
84
1.45k
#if 1 && (LZO_OPT_UNALIGNED32)
85
145k
                    do {
86
145k
                        UA_COPY4(op+0, ip+0);
87
145k
                        UA_COPY4(op+4, ip+4);
88
145k
                        op += 8; ip += 8;
89
145k
                        t -= 8;
90
145k
                    } while (t > 0);
91
#else
92
                    MEMCPY8_DS(op,ip,t);
93
#endif
94
1.45k
                    continue;
95
1.45k
                }
96
2.58k
                t += R0MIN;                         /* a short R0 run */
97
2.58k
            }
98
99
24.6k
            NEED_IP(t); NEED_OP(t);
100
            /* copy literal run */
101
24.5k
#if 1 && (LZO_OPT_UNALIGNED32)
102
24.5k
            if (t >= 4)
103
12.2k
            {
104
46.0k
                do {
105
46.0k
                    UA_COPY4(op, ip);
106
46.0k
                    op += 4; ip += 4; t -= 4;
107
46.0k
                } while (t >= 4);
108
12.2k
                if (t > 0) do *op++ = *ip++; while (--t > 0);
109
12.2k
            }
110
12.3k
            else
111
12.3k
#endif
112
12.3k
            {
113
#if (M3O_BITS < 7)
114
literal1:
115
#endif
116
22.8k
                do *op++ = *ip++; while (--t > 0);
117
12.3k
            }
118
119
#if (M3O_BITS == 7)
120
literal2:
121
#endif
122
123
            /* after a literal a match must follow */
124
24.5k
            while (TEST_IP_AND_TEST_OP)
125
215k
            {
126
215k
                t = *ip++;          /* get R1 marker */
127
215k
                if (t >= R0MIN)
128
24.4k
                    goto match;
129
130
191k
                NEED_IP(2); NEED_OP(M2_MIN_LEN + 1);
131
132
            /* R1 match - a M2_MIN_LEN match + 1 byte literal */
133
191k
                assert((t & M2O_MASK) == t);
134
191k
                m_pos = op - M2_MIN_OFFSET;
135
191k
                m_pos -= t | (((lzo_uint) *ip++) << M2O_BITS);
136
191k
                assert(m_pos >= out); assert(m_pos < op);
137
191k
                TEST_LB(m_pos);
138
191k
                COPY_M2;
139
191k
                *op++ = *ip++;
140
191k
            }
141
142
23
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
143
23
            break;
144
24.5k
#endif
145
24.5k
        }
146
147
95.4k
match:
148
149
95.4k
        if (t >= M2_MARKER)             /* a M2 match */
150
75.1k
        {
151
            /* get match offset */
152
75.1k
            NEED_IP(1);
153
75.0k
            m_pos = op - M2_MIN_OFFSET;
154
75.0k
            m_pos -= (t & M2O_MASK) | (((lzo_uint) *ip++) << M2O_BITS);
155
75.0k
            assert(m_pos >= out); assert(m_pos < op);
156
75.0k
            TEST_LB(m_pos);
157
158
            /* get match len */
159
75.0k
            t = (t >> M2O_BITS) - 1;
160
75.0k
            NEED_OP(t + M2_MIN_LEN - 1);
161
75.0k
            COPY_M2X;
162
75.0k
            MEMCPY_DS(op,m_pos,t);
163
75.0k
        }
164
20.3k
        else                            /* a M3 or M4 match */
165
20.3k
        {
166
            /* get match len */
167
20.3k
            t &= M3L_MASK;
168
20.3k
            if (t == 0)         /* a M4 match */
169
3.24k
            {
170
3.24k
                NEED_IP(1);
171
1.29M
                while (*ip == 0)
172
1.29M
                {
173
1.29M
                    t += 255;
174
1.29M
                    ip++;
175
1.29M
                    TEST_OV(t);
176
1.29M
                    NEED_IP(1);
177
1.29M
                }
178
3.22k
                t += (M4_MIN_LEN - M3_MIN_LEN) + *ip++;
179
3.22k
            }
180
181
            /* get match offset */
182
20.2k
            NEED_IP(2);
183
20.2k
            m_pos = op - (M3_MIN_OFFSET - M3_EOF_OFFSET);
184
20.2k
            m_pos -= *ip++ & M3O_MASK;
185
20.2k
            m_pos -= (lzo_uint)(*ip++) << M3O_BITS;
186
20.2k
#if defined(LZO_EOF_CODE)
187
20.2k
            if (m_pos == op)
188
24
                goto eof_found;
189
20.2k
#endif
190
191
            /* copy match */
192
20.2k
            assert(m_pos >= out); assert(m_pos < op);
193
20.2k
            TEST_LB(m_pos); NEED_OP(t + M3_MIN_LEN - 1);
194
20.1k
#if (LZO_OPT_UNALIGNED32)
195
20.1k
            if (t >= 2 * 4 - (M3_MIN_LEN - 1) && (op - m_pos) >= 4)
196
18.6k
            {
197
18.6k
                UA_COPY4(op, m_pos);
198
18.6k
                op += 4; m_pos += 4; t -= 4 - (M3_MIN_LEN - 1);
199
1.63M
                do {
200
1.63M
                    UA_COPY4(op, m_pos);
201
1.63M
                    op += 4; m_pos += 4; t -= 4;
202
1.63M
                } while (t >= 4);
203
24.1k
                if (t > 0) do *op++ = *m_pos++; while (--t > 0);
204
18.6k
            }
205
1.50k
            else
206
1.50k
#endif
207
1.50k
            {
208
1.50k
            COPY_M3X;
209
1.50k
            MEMCPY_DS(op,m_pos,t);
210
1.50k
            }
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
20.1k
        }
230
95.4k
    }
231
232
233
55
#if defined(LZO_EOF_CODE)
234
55
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
235
    /* no EOF code was found */
236
55
    *out_len = pd(op, out);
237
55
    return LZO_E_EOF_NOT_FOUND;
238
0
#endif
239
240
24
eof_found:
241
24
    assert(t == 1);
242
24
#endif
243
24
    *out_len = pd(op, out);
244
24
    return (ip == ip_end ? LZO_E_OK :
245
24
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
246
247
248
0
#if defined(HAVE_NEED_IP)
249
190
input_overrun:
250
190
    *out_len = pd(op, out);
251
190
    return LZO_E_INPUT_OVERRUN;
252
0
#endif
253
254
0
#if defined(HAVE_NEED_OP)
255
31
output_overrun:
256
31
    *out_len = pd(op, out);
257
31
    return LZO_E_OUTPUT_OVERRUN;
258
0
#endif
259
260
0
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
261
134
lookbehind_overrun:
262
134
    *out_len = pd(op, out);
263
134
    return LZO_E_LOOKBEHIND_OVERRUN;
264
434
#endif
265
434
}
lzo1c_decompress_safe
Line
Count
Source
40
484
{
41
484
    lzo_bytep op;
42
484
    const lzo_bytep ip;
43
484
    lzo_uint t;
44
484
    const lzo_bytep m_pos;
45
46
484
    const lzo_bytep const ip_end = in + in_len;
47
484
#if defined(HAVE_ANY_OP)
48
484
    lzo_bytep const op_end = out + *out_len;
49
484
#endif
50
51
484
    LZO_UNUSED(wrkmem);
52
53
484
    op = out;
54
484
    ip = in;
55
56
484
    while (TEST_IP_AND_TEST_OP)
57
127k
    {
58
127k
        t = *ip++;      /* get marker */
59
60
127k
        if (t < R0MIN)      /* a literal run */
61
30.3k
        {
62
30.3k
            if (t == 0)             /* a R0 literal run */
63
5.74k
            {
64
5.74k
                NEED_IP(1);
65
5.73k
                t = *ip++;
66
5.73k
                if (t >= R0FAST - R0MIN)            /* a long R0 run */
67
1.46k
                {
68
1.46k
                    t -= R0FAST - R0MIN;
69
1.46k
                    if (t == 0)
70
662
                        t = R0FAST;
71
798
                    else
72
798
                    {
73
#if 0
74
                        t = 256u << ((unsigned) t);
75
#else
76
                        /* help the optimizer */
77
798
                        lzo_uint tt = 256;
78
1.28k
                        do tt <<= 1; while (--t > 0);
79
798
                        t = tt;
80
798
#endif
81
798
                    }
82
83
1.46k
                    NEED_IP(t); NEED_OP(t);
84
1.40k
#if 1 && (LZO_OPT_UNALIGNED32)
85
188k
                    do {
86
188k
                        UA_COPY4(op+0, ip+0);
87
188k
                        UA_COPY4(op+4, ip+4);
88
188k
                        op += 8; ip += 8;
89
188k
                        t -= 8;
90
188k
                    } while (t > 0);
91
#else
92
                    MEMCPY8_DS(op,ip,t);
93
#endif
94
1.40k
                    continue;
95
1.40k
                }
96
4.27k
                t += R0MIN;                         /* a short R0 run */
97
4.27k
            }
98
99
28.8k
            NEED_IP(t); NEED_OP(t);
100
            /* copy literal run */
101
28.7k
#if 1 && (LZO_OPT_UNALIGNED32)
102
28.7k
            if (t >= 4)
103
23.4k
            {
104
103k
                do {
105
103k
                    UA_COPY4(op, ip);
106
103k
                    op += 4; ip += 4; t -= 4;
107
103k
                } while (t >= 4);
108
26.5k
                if (t > 0) do *op++ = *ip++; while (--t > 0);
109
23.4k
            }
110
5.35k
            else
111
5.35k
#endif
112
5.35k
            {
113
5.35k
#if (M3O_BITS < 7)
114
31.4k
literal1:
115
31.4k
#endif
116
49.7k
                do *op++ = *ip++; while (--t > 0);
117
31.4k
            }
118
119
#if (M3O_BITS == 7)
120
literal2:
121
#endif
122
123
            /* after a literal a match must follow */
124
54.9k
            while (TEST_IP_AND_TEST_OP)
125
388k
            {
126
388k
                t = *ip++;          /* get R1 marker */
127
388k
                if (t >= R0MIN)
128
54.8k
                    goto match;
129
130
334k
                NEED_IP(2); NEED_OP(M2_MIN_LEN + 1);
131
132
            /* R1 match - a M2_MIN_LEN match + 1 byte literal */
133
334k
                assert((t & M2O_MASK) == t);
134
334k
                m_pos = op - M2_MIN_OFFSET;
135
334k
                m_pos -= t | (((lzo_uint) *ip++) << M2O_BITS);
136
334k
                assert(m_pos >= out); assert(m_pos < op);
137
334k
                TEST_LB(m_pos);
138
334k
                COPY_M2;
139
333k
                *op++ = *ip++;
140
333k
            }
141
142
30
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
143
30
            break;
144
54.9k
#endif
145
54.9k
        }
146
147
151k
match:
148
149
151k
        if (t >= M2_MARKER)             /* a M2 match */
150
98.7k
        {
151
            /* get match offset */
152
98.7k
            NEED_IP(1);
153
98.7k
            m_pos = op - M2_MIN_OFFSET;
154
98.7k
            m_pos -= (t & M2O_MASK) | (((lzo_uint) *ip++) << M2O_BITS);
155
98.7k
            assert(m_pos >= out); assert(m_pos < op);
156
98.7k
            TEST_LB(m_pos);
157
158
            /* get match len */
159
98.7k
            t = (t >> M2O_BITS) - 1;
160
98.7k
            NEED_OP(t + M2_MIN_LEN - 1);
161
98.7k
            COPY_M2X;
162
98.6k
            MEMCPY_DS(op,m_pos,t);
163
98.6k
        }
164
53.0k
        else                            /* a M3 or M4 match */
165
53.0k
        {
166
            /* get match len */
167
53.0k
            t &= M3L_MASK;
168
53.0k
            if (t == 0)         /* a M4 match */
169
17.7k
            {
170
17.7k
                NEED_IP(1);
171
1.27M
                while (*ip == 0)
172
1.25M
                {
173
1.25M
                    t += 255;
174
1.25M
                    ip++;
175
1.25M
                    TEST_OV(t);
176
1.25M
                    NEED_IP(1);
177
1.25M
                }
178
17.7k
                t += (M4_MIN_LEN - M3_MIN_LEN) + *ip++;
179
17.7k
            }
180
181
            /* get match offset */
182
53.0k
            NEED_IP(2);
183
53.0k
            m_pos = op - (M3_MIN_OFFSET - M3_EOF_OFFSET);
184
53.0k
            m_pos -= *ip++ & M3O_MASK;
185
53.0k
            m_pos -= (lzo_uint)(*ip++) << M3O_BITS;
186
53.0k
#if defined(LZO_EOF_CODE)
187
53.0k
            if (m_pos == op)
188
27
                goto eof_found;
189
52.9k
#endif
190
191
            /* copy match */
192
53.0k
            assert(m_pos >= out); assert(m_pos < op);
193
52.9k
            TEST_LB(m_pos); NEED_OP(t + M3_MIN_LEN - 1);
194
52.9k
#if (LZO_OPT_UNALIGNED32)
195
52.9k
            if (t >= 2 * 4 - (M3_MIN_LEN - 1) && (op - m_pos) >= 4)
196
45.0k
            {
197
45.0k
                UA_COPY4(op, m_pos);
198
45.0k
                op += 4; m_pos += 4; t -= 4 - (M3_MIN_LEN - 1);
199
1.96M
                do {
200
1.96M
                    UA_COPY4(op, m_pos);
201
1.96M
                    op += 4; m_pos += 4; t -= 4;
202
1.96M
                } while (t >= 4);
203
62.7k
                if (t > 0) do *op++ = *m_pos++; while (--t > 0);
204
45.0k
            }
205
7.90k
            else
206
7.90k
#endif
207
7.90k
            {
208
7.90k
            COPY_M3X;
209
7.90k
            MEMCPY_DS(op,m_pos,t);
210
7.90k
            }
211
212
213
52.9k
#if (M3O_BITS < 7)
214
52.9k
            t = ip[-2] >> M3O_BITS;
215
52.9k
            if (t)
216
26.1k
            {
217
26.1k
                NEED_IP(t); NEED_OP(t);
218
26.1k
                goto literal1;
219
26.1k
            }
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
52.9k
        }
230
151k
    }
231
232
233
73
#if defined(LZO_EOF_CODE)
234
73
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
235
    /* no EOF code was found */
236
73
    *out_len = pd(op, out);
237
73
    return LZO_E_EOF_NOT_FOUND;
238
0
#endif
239
240
27
eof_found:
241
27
    assert(t == 1);
242
27
#endif
243
27
    *out_len = pd(op, out);
244
27
    return (ip == ip_end ? LZO_E_OK :
245
27
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
246
247
248
0
#if defined(HAVE_NEED_IP)
249
223
input_overrun:
250
223
    *out_len = pd(op, out);
251
223
    return LZO_E_INPUT_OVERRUN;
252
0
#endif
253
254
0
#if defined(HAVE_NEED_OP)
255
38
output_overrun:
256
38
    *out_len = pd(op, out);
257
38
    return LZO_E_OUTPUT_OVERRUN;
258
0
#endif
259
260
0
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
261
123
lookbehind_overrun:
262
123
    *out_len = pd(op, out);
263
123
    return LZO_E_LOOKBEHIND_OVERRUN;
264
484
#endif
265
484
}
266
267
268
/* vim:set ts=4 sw=4 et: */