Coverage Report

Created: 2025-08-26 06:41

/src/lzo-2.10/src/lzo1b_d.ch
Line
Count
Source (jump to first uncovered line)
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
5.88k
{
41
5.88k
    lzo_bytep op;
42
5.88k
    const lzo_bytep ip;
43
5.88k
    lzo_uint t;
44
5.88k
    const lzo_bytep m_pos;
45
46
5.88k
    const lzo_bytep const ip_end = in + in_len;
47
#if defined(HAVE_ANY_OP)
48
    lzo_bytep const op_end = out + *out_len;
49
#endif
50
51
5.88k
    LZO_UNUSED(wrkmem);
52
53
5.88k
    op = out;
54
5.88k
    ip = in;
55
56
1.38M
    while (TEST_IP_AND_TEST_OP)
57
1.38M
    {
58
1.38M
        t = *ip++;      /* get marker */
59
60
1.38M
        if (t < R0MIN)      /* a literal run */
61
572k
        {
62
572k
            if (t == 0)             /* a R0 literal run */
63
60.5k
            {
64
60.5k
                NEED_IP(1);
65
60.5k
                t = *ip++;
66
60.5k
                if (t >= R0FAST - R0MIN)            /* a long R0 run */
67
18.7k
                {
68
18.7k
                    t -= R0FAST - R0MIN;
69
18.7k
                    if (t == 0)
70
7.71k
                        t = R0FAST;
71
11.0k
                    else
72
11.0k
                    {
73
#if 0
74
                        t = 256u << ((unsigned) t);
75
#else
76
                        /* help the optimizer */
77
11.0k
                        lzo_uint tt = 256;
78
21.3k
                        do tt <<= 1; while (--t > 0);
79
11.0k
                        t = tt;
80
11.0k
#endif
81
11.0k
                    }
82
83
18.7k
                    NEED_IP(t); NEED_OP(t);
84
18.7k
#if 1 && (LZO_OPT_UNALIGNED32)
85
2.64M
                    do {
86
2.64M
                        UA_COPY4(op+0, ip+0);
87
2.64M
                        UA_COPY4(op+4, ip+4);
88
2.64M
                        op += 8; ip += 8;
89
2.64M
                        t -= 8;
90
2.64M
                    } while (t > 0);
91
#else
92
                    MEMCPY8_DS(op,ip,t);
93
#endif
94
18.7k
                    continue;
95
18.7k
                }
96
41.7k
                t += R0MIN;                         /* a short R0 run */
97
41.7k
            }
98
99
553k
            NEED_IP(t); NEED_OP(t);
100
            /* copy literal run */
101
553k
#if 1 && (LZO_OPT_UNALIGNED32)
102
553k
            if (t >= 4)
103
226k
            {
104
1.43M
                do {
105
1.43M
                    UA_COPY4(op, ip);
106
1.43M
                    op += 4; ip += 4; t -= 4;
107
1.43M
                } while (t >= 4);
108
278k
                if (t > 0) do *op++ = *ip++; while (--t > 0);
109
226k
            }
110
327k
            else
111
327k
#endif
112
327k
            {
113
#if (M3O_BITS < 7)
114
138k
literal1:
115
138k
#endif
116
636k
                do *op++ = *ip++; while (--t > 0);
117
138k
            }
118
119
#if (M3O_BITS == 7)
120
literal2:
121
#endif
122
123
            /* after a literal a match must follow */
124
656k
            while (TEST_IP_AND_TEST_OP)
125
656k
            {
126
656k
                t = *ip++;          /* get R1 marker */
127
656k
                if (t >= R0MIN)
128
616k
                    goto match;
129
130
39.9k
                NEED_IP(2); NEED_OP(M2_MIN_LEN + 1);
131
132
            /* R1 match - a M2_MIN_LEN match + 1 byte literal */
133
39.9k
                assert((t & M2O_MASK) == t);
134
39.9k
                m_pos = op - M2_MIN_OFFSET;
135
39.9k
                m_pos -= t | (((lzo_uint) *ip++) << M2O_BITS);
136
39.9k
                assert(m_pos >= out); assert(m_pos < op);
137
39.9k
                TEST_LB(m_pos);
138
39.9k
                COPY_M2;
139
39.9k
                *op++ = *ip++;
140
39.9k
            }
141
142
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
143
            break;
144
#endif
145
206k
        }
146
147
1.42M
match:
148
149
1.42M
        if (t >= M2_MARKER)             /* a M2 match */
150
940k
        {
151
            /* get match offset */
152
940k
            NEED_IP(1);
153
940k
            m_pos = op - M2_MIN_OFFSET;
154
940k
            m_pos -= (t & M2O_MASK) | (((lzo_uint) *ip++) << M2O_BITS);
155
940k
            assert(m_pos >= out); assert(m_pos < op);
156
940k
            TEST_LB(m_pos);
157
158
            /* get match len */
159
940k
            t = (t >> M2O_BITS) - 1;
160
940k
            NEED_OP(t + M2_MIN_LEN - 1);
161
940k
            COPY_M2X;
162
940k
            MEMCPY_DS(op,m_pos,t);
163
940k
        }
164
488k
        else                            /* a M3 or M4 match */
165
488k
        {
166
            /* get match len */
167
488k
            t &= M3L_MASK;
168
488k
            if (t == 0)         /* a M4 match */
169
147k
            {
170
147k
                NEED_IP(1);
171
564k
                while (*ip == 0)
172
416k
                {
173
416k
                    t += 255;
174
416k
                    ip++;
175
416k
                    TEST_OV(t);
176
416k
                    NEED_IP(1);
177
416k
                }
178
147k
                t += (M4_MIN_LEN - M3_MIN_LEN) + *ip++;
179
147k
            }
180
181
            /* get match offset */
182
488k
            NEED_IP(2);
183
488k
            m_pos = op - (M3_MIN_OFFSET - M3_EOF_OFFSET);
184
488k
            m_pos -= *ip++ & M3O_MASK;
185
488k
            m_pos -= (lzo_uint)(*ip++) << M3O_BITS;
186
488k
#if defined(LZO_EOF_CODE)
187
488k
            if (m_pos == op)
188
5.88k
                goto eof_found;
189
482k
#endif
190
191
            /* copy match */
192
482k
            assert(m_pos >= out); assert(m_pos < op);
193
482k
            TEST_LB(m_pos); NEED_OP(t + M3_MIN_LEN - 1);
194
482k
#if (LZO_OPT_UNALIGNED32)
195
482k
            if (t >= 2 * 4 - (M3_MIN_LEN - 1) && (op - m_pos) >= 4)
196
360k
            {
197
360k
                UA_COPY4(op, m_pos);
198
360k
                op += 4; m_pos += 4; t -= 4 - (M3_MIN_LEN - 1);
199
14.0M
                do {
200
14.0M
                    UA_COPY4(op, m_pos);
201
14.0M
                    op += 4; m_pos += 4; t -= 4;
202
14.0M
                } while (t >= 4);
203
493k
                if (t > 0) do *op++ = *m_pos++; while (--t > 0);
204
360k
            }
205
122k
            else
206
122k
#endif
207
122k
            {
208
122k
            COPY_M3X;
209
122k
            MEMCPY_DS(op,m_pos,t);
210
122k
            }
211
212
213
#if (M3O_BITS < 7)
214
156k
            t = ip[-2] >> M3O_BITS;
215
156k
            if (t)
216
63.1k
            {
217
63.1k
                NEED_IP(t); NEED_OP(t);
218
63.1k
                goto literal1;
219
63.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
482k
        }
230
1.42M
    }
231
232
233
0
#if defined(LZO_EOF_CODE)
234
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
235
    /* no EOF code was found */
236
    *out_len = pd(op, out);
237
    return LZO_E_EOF_NOT_FOUND;
238
#endif
239
240
5.88k
eof_found:
241
5.88k
    assert(t == 1);
242
5.88k
#endif
243
5.88k
    *out_len = pd(op, out);
244
5.88k
    return (ip == ip_end ? LZO_E_OK :
245
5.88k
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
246
247
248
#if defined(HAVE_NEED_IP)
249
input_overrun:
250
    *out_len = pd(op, out);
251
    return LZO_E_INPUT_OVERRUN;
252
#endif
253
254
#if defined(HAVE_NEED_OP)
255
output_overrun:
256
    *out_len = pd(op, out);
257
    return LZO_E_OUTPUT_OVERRUN;
258
#endif
259
260
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
261
lookbehind_overrun:
262
    *out_len = pd(op, out);
263
    return LZO_E_LOOKBEHIND_OVERRUN;
264
#endif
265
5.88k
}
lzo1b_decompress
Line
Count
Source
40
3.78k
{
41
3.78k
    lzo_bytep op;
42
3.78k
    const lzo_bytep ip;
43
3.78k
    lzo_uint t;
44
3.78k
    const lzo_bytep m_pos;
45
46
3.78k
    const lzo_bytep const ip_end = in + in_len;
47
#if defined(HAVE_ANY_OP)
48
    lzo_bytep const op_end = out + *out_len;
49
#endif
50
51
3.78k
    LZO_UNUSED(wrkmem);
52
53
3.78k
    op = out;
54
3.78k
    ip = in;
55
56
1.01M
    while (TEST_IP_AND_TEST_OP)
57
1.01M
    {
58
1.01M
        t = *ip++;      /* get marker */
59
60
1.01M
        if (t < R0MIN)      /* a literal run */
61
421k
        {
62
421k
            if (t == 0)             /* a R0 literal run */
63
38.9k
            {
64
38.9k
                NEED_IP(1);
65
38.9k
                t = *ip++;
66
38.9k
                if (t >= R0FAST - R0MIN)            /* a long R0 run */
67
11.0k
                {
68
11.0k
                    t -= R0FAST - R0MIN;
69
11.0k
                    if (t == 0)
70
4.79k
                        t = R0FAST;
71
6.27k
                    else
72
6.27k
                    {
73
#if 0
74
                        t = 256u << ((unsigned) t);
75
#else
76
                        /* help the optimizer */
77
6.27k
                        lzo_uint tt = 256;
78
11.6k
                        do tt <<= 1; while (--t > 0);
79
6.27k
                        t = tt;
80
6.27k
#endif
81
6.27k
                    }
82
83
11.0k
                    NEED_IP(t); NEED_OP(t);
84
11.0k
#if 1 && (LZO_OPT_UNALIGNED32)
85
1.33M
                    do {
86
1.33M
                        UA_COPY4(op+0, ip+0);
87
1.33M
                        UA_COPY4(op+4, ip+4);
88
1.33M
                        op += 8; ip += 8;
89
1.33M
                        t -= 8;
90
1.33M
                    } while (t > 0);
91
#else
92
                    MEMCPY8_DS(op,ip,t);
93
#endif
94
11.0k
                    continue;
95
11.0k
                }
96
27.9k
                t += R0MIN;                         /* a short R0 run */
97
27.9k
            }
98
99
409k
            NEED_IP(t); NEED_OP(t);
100
            /* copy literal run */
101
409k
#if 1 && (LZO_OPT_UNALIGNED32)
102
409k
            if (t >= 4)
103
157k
            {
104
953k
                do {
105
953k
                    UA_COPY4(op, ip);
106
953k
                    op += 4; ip += 4; t -= 4;
107
953k
                } while (t >= 4);
108
193k
                if (t > 0) do *op++ = *ip++; while (--t > 0);
109
157k
            }
110
252k
            else
111
252k
#endif
112
252k
            {
113
#if (M3O_BITS < 7)
114
literal1:
115
#endif
116
420k
                do *op++ = *ip++; while (--t > 0);
117
252k
            }
118
119
#if (M3O_BITS == 7)
120
literal2:
121
#endif
122
123
            /* after a literal a match must follow */
124
436k
            while (TEST_IP_AND_TEST_OP)
125
436k
            {
126
436k
                t = *ip++;          /* get R1 marker */
127
436k
                if (t >= R0MIN)
128
409k
                    goto match;
129
130
26.6k
                NEED_IP(2); NEED_OP(M2_MIN_LEN + 1);
131
132
            /* R1 match - a M2_MIN_LEN match + 1 byte literal */
133
26.6k
                assert((t & M2O_MASK) == t);
134
26.6k
                m_pos = op - M2_MIN_OFFSET;
135
26.6k
                m_pos -= t | (((lzo_uint) *ip++) << M2O_BITS);
136
26.6k
                assert(m_pos >= out); assert(m_pos < op);
137
26.6k
                TEST_LB(m_pos);
138
26.6k
                COPY_M2;
139
26.6k
                *op++ = *ip++;
140
26.6k
            }
141
142
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
143
            break;
144
#endif
145
409k
        }
146
147
1.00M
match:
148
149
1.00M
        if (t >= M2_MARKER)             /* a M2 match */
150
676k
        {
151
            /* get match offset */
152
676k
            NEED_IP(1);
153
676k
            m_pos = op - M2_MIN_OFFSET;
154
676k
            m_pos -= (t & M2O_MASK) | (((lzo_uint) *ip++) << M2O_BITS);
155
676k
            assert(m_pos >= out); assert(m_pos < op);
156
676k
            TEST_LB(m_pos);
157
158
            /* get match len */
159
676k
            t = (t >> M2O_BITS) - 1;
160
676k
            NEED_OP(t + M2_MIN_LEN - 1);
161
676k
            COPY_M2X;
162
676k
            MEMCPY_DS(op,m_pos,t);
163
676k
        }
164
329k
        else                            /* a M3 or M4 match */
165
329k
        {
166
            /* get match len */
167
329k
            t &= M3L_MASK;
168
329k
            if (t == 0)         /* a M4 match */
169
89.1k
            {
170
89.1k
                NEED_IP(1);
171
330k
                while (*ip == 0)
172
241k
                {
173
241k
                    t += 255;
174
241k
                    ip++;
175
241k
                    TEST_OV(t);
176
241k
                    NEED_IP(1);
177
241k
                }
178
89.1k
                t += (M4_MIN_LEN - M3_MIN_LEN) + *ip++;
179
89.1k
            }
180
181
            /* get match offset */
182
329k
            NEED_IP(2);
183
329k
            m_pos = op - (M3_MIN_OFFSET - M3_EOF_OFFSET);
184
329k
            m_pos -= *ip++ & M3O_MASK;
185
329k
            m_pos -= (lzo_uint)(*ip++) << M3O_BITS;
186
329k
#if defined(LZO_EOF_CODE)
187
329k
            if (m_pos == op)
188
3.78k
                goto eof_found;
189
325k
#endif
190
191
            /* copy match */
192
325k
            assert(m_pos >= out); assert(m_pos < op);
193
325k
            TEST_LB(m_pos); NEED_OP(t + M3_MIN_LEN - 1);
194
325k
#if (LZO_OPT_UNALIGNED32)
195
325k
            if (t >= 2 * 4 - (M3_MIN_LEN - 1) && (op - m_pos) >= 4)
196
231k
            {
197
231k
                UA_COPY4(op, m_pos);
198
231k
                op += 4; m_pos += 4; t -= 4 - (M3_MIN_LEN - 1);
199
8.86M
                do {
200
8.86M
                    UA_COPY4(op, m_pos);
201
8.86M
                    op += 4; m_pos += 4; t -= 4;
202
8.86M
                } while (t >= 4);
203
335k
                if (t > 0) do *op++ = *m_pos++; while (--t > 0);
204
231k
            }
205
93.8k
            else
206
93.8k
#endif
207
93.8k
            {
208
93.8k
            COPY_M3X;
209
93.8k
            MEMCPY_DS(op,m_pos,t);
210
93.8k
            }
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
325k
        }
230
1.00M
    }
231
232
233
0
#if defined(LZO_EOF_CODE)
234
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
235
    /* no EOF code was found */
236
    *out_len = pd(op, out);
237
    return LZO_E_EOF_NOT_FOUND;
238
#endif
239
240
3.78k
eof_found:
241
3.78k
    assert(t == 1);
242
3.78k
#endif
243
3.78k
    *out_len = pd(op, out);
244
3.78k
    return (ip == ip_end ? LZO_E_OK :
245
3.78k
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
246
247
248
#if defined(HAVE_NEED_IP)
249
input_overrun:
250
    *out_len = pd(op, out);
251
    return LZO_E_INPUT_OVERRUN;
252
#endif
253
254
#if defined(HAVE_NEED_OP)
255
output_overrun:
256
    *out_len = pd(op, out);
257
    return LZO_E_OUTPUT_OVERRUN;
258
#endif
259
260
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
261
lookbehind_overrun:
262
    *out_len = pd(op, out);
263
    return LZO_E_LOOKBEHIND_OVERRUN;
264
#endif
265
3.78k
}
lzo1c_decompress
Line
Count
Source
40
2.10k
{
41
2.10k
    lzo_bytep op;
42
2.10k
    const lzo_bytep ip;
43
2.10k
    lzo_uint t;
44
2.10k
    const lzo_bytep m_pos;
45
46
2.10k
    const lzo_bytep const ip_end = in + in_len;
47
#if defined(HAVE_ANY_OP)
48
    lzo_bytep const op_end = out + *out_len;
49
#endif
50
51
2.10k
    LZO_UNUSED(wrkmem);
52
53
2.10k
    op = out;
54
2.10k
    ip = in;
55
56
368k
    while (TEST_IP_AND_TEST_OP)
57
368k
    {
58
368k
        t = *ip++;      /* get marker */
59
60
368k
        if (t < R0MIN)      /* a literal run */
61
151k
        {
62
151k
            if (t == 0)             /* a R0 literal run */
63
21.5k
            {
64
21.5k
                NEED_IP(1);
65
21.5k
                t = *ip++;
66
21.5k
                if (t >= R0FAST - R0MIN)            /* a long R0 run */
67
7.69k
                {
68
7.69k
                    t -= R0FAST - R0MIN;
69
7.69k
                    if (t == 0)
70
2.91k
                        t = R0FAST;
71
4.77k
                    else
72
4.77k
                    {
73
#if 0
74
                        t = 256u << ((unsigned) t);
75
#else
76
                        /* help the optimizer */
77
4.77k
                        lzo_uint tt = 256;
78
9.66k
                        do tt <<= 1; while (--t > 0);
79
4.77k
                        t = tt;
80
4.77k
#endif
81
4.77k
                    }
82
83
7.69k
                    NEED_IP(t); NEED_OP(t);
84
7.69k
#if 1 && (LZO_OPT_UNALIGNED32)
85
1.30M
                    do {
86
1.30M
                        UA_COPY4(op+0, ip+0);
87
1.30M
                        UA_COPY4(op+4, ip+4);
88
1.30M
                        op += 8; ip += 8;
89
1.30M
                        t -= 8;
90
1.30M
                    } while (t > 0);
91
#else
92
                    MEMCPY8_DS(op,ip,t);
93
#endif
94
7.69k
                    continue;
95
7.69k
                }
96
13.8k
                t += R0MIN;                         /* a short R0 run */
97
13.8k
            }
98
99
143k
            NEED_IP(t); NEED_OP(t);
100
            /* copy literal run */
101
143k
#if 1 && (LZO_OPT_UNALIGNED32)
102
143k
            if (t >= 4)
103
68.9k
            {
104
481k
                do {
105
481k
                    UA_COPY4(op, ip);
106
481k
                    op += 4; ip += 4; t -= 4;
107
481k
                } while (t >= 4);
108
85.6k
                if (t > 0) do *op++ = *ip++; while (--t > 0);
109
68.9k
            }
110
74.8k
            else
111
74.8k
#endif
112
74.8k
            {
113
74.8k
#if (M3O_BITS < 7)
114
138k
literal1:
115
138k
#endif
116
216k
                do *op++ = *ip++; while (--t > 0);
117
138k
            }
118
119
#if (M3O_BITS == 7)
120
literal2:
121
#endif
122
123
            /* after a literal a match must follow */
124
220k
            while (TEST_IP_AND_TEST_OP)
125
220k
            {
126
220k
                t = *ip++;          /* get R1 marker */
127
220k
                if (t >= R0MIN)
128
206k
                    goto match;
129
130
13.2k
                NEED_IP(2); NEED_OP(M2_MIN_LEN + 1);
131
132
            /* R1 match - a M2_MIN_LEN match + 1 byte literal */
133
13.2k
                assert((t & M2O_MASK) == t);
134
13.2k
                m_pos = op - M2_MIN_OFFSET;
135
13.2k
                m_pos -= t | (((lzo_uint) *ip++) << M2O_BITS);
136
13.2k
                assert(m_pos >= out); assert(m_pos < op);
137
13.2k
                TEST_LB(m_pos);
138
13.2k
                COPY_M2;
139
13.2k
                *op++ = *ip++;
140
13.2k
            }
141
142
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
143
            break;
144
#endif
145
206k
        }
146
147
423k
match:
148
149
423k
        if (t >= M2_MARKER)             /* a M2 match */
150
264k
        {
151
            /* get match offset */
152
264k
            NEED_IP(1);
153
264k
            m_pos = op - M2_MIN_OFFSET;
154
264k
            m_pos -= (t & M2O_MASK) | (((lzo_uint) *ip++) << M2O_BITS);
155
264k
            assert(m_pos >= out); assert(m_pos < op);
156
264k
            TEST_LB(m_pos);
157
158
            /* get match len */
159
264k
            t = (t >> M2O_BITS) - 1;
160
264k
            NEED_OP(t + M2_MIN_LEN - 1);
161
264k
            COPY_M2X;
162
264k
            MEMCPY_DS(op,m_pos,t);
163
264k
        }
164
159k
        else                            /* a M3 or M4 match */
165
159k
        {
166
            /* get match len */
167
159k
            t &= M3L_MASK;
168
159k
            if (t == 0)         /* a M4 match */
169
58.1k
            {
170
58.1k
                NEED_IP(1);
171
233k
                while (*ip == 0)
172
175k
                {
173
175k
                    t += 255;
174
175k
                    ip++;
175
175k
                    TEST_OV(t);
176
175k
                    NEED_IP(1);
177
175k
                }
178
58.1k
                t += (M4_MIN_LEN - M3_MIN_LEN) + *ip++;
179
58.1k
            }
180
181
            /* get match offset */
182
159k
            NEED_IP(2);
183
159k
            m_pos = op - (M3_MIN_OFFSET - M3_EOF_OFFSET);
184
159k
            m_pos -= *ip++ & M3O_MASK;
185
159k
            m_pos -= (lzo_uint)(*ip++) << M3O_BITS;
186
159k
#if defined(LZO_EOF_CODE)
187
159k
            if (m_pos == op)
188
2.10k
                goto eof_found;
189
156k
#endif
190
191
            /* copy match */
192
156k
            assert(m_pos >= out); assert(m_pos < op);
193
156k
            TEST_LB(m_pos); NEED_OP(t + M3_MIN_LEN - 1);
194
156k
#if (LZO_OPT_UNALIGNED32)
195
156k
            if (t >= 2 * 4 - (M3_MIN_LEN - 1) && (op - m_pos) >= 4)
196
128k
            {
197
128k
                UA_COPY4(op, m_pos);
198
128k
                op += 4; m_pos += 4; t -= 4 - (M3_MIN_LEN - 1);
199
5.21M
                do {
200
5.21M
                    UA_COPY4(op, m_pos);
201
5.21M
                    op += 4; m_pos += 4; t -= 4;
202
5.21M
                } while (t >= 4);
203
158k
                if (t > 0) do *op++ = *m_pos++; while (--t > 0);
204
128k
            }
205
28.5k
            else
206
28.5k
#endif
207
28.5k
            {
208
28.5k
            COPY_M3X;
209
28.5k
            MEMCPY_DS(op,m_pos,t);
210
28.5k
            }
211
212
213
156k
#if (M3O_BITS < 7)
214
156k
            t = ip[-2] >> M3O_BITS;
215
156k
            if (t)
216
63.1k
            {
217
63.1k
                NEED_IP(t); NEED_OP(t);
218
63.1k
                goto literal1;
219
63.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
156k
        }
230
423k
    }
231
232
233
0
#if defined(LZO_EOF_CODE)
234
#if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
235
    /* no EOF code was found */
236
    *out_len = pd(op, out);
237
    return LZO_E_EOF_NOT_FOUND;
238
#endif
239
240
2.10k
eof_found:
241
2.10k
    assert(t == 1);
242
2.10k
#endif
243
2.10k
    *out_len = pd(op, out);
244
2.10k
    return (ip == ip_end ? LZO_E_OK :
245
2.10k
           (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
246
247
248
#if defined(HAVE_NEED_IP)
249
input_overrun:
250
    *out_len = pd(op, out);
251
    return LZO_E_INPUT_OVERRUN;
252
#endif
253
254
#if defined(HAVE_NEED_OP)
255
output_overrun:
256
    *out_len = pd(op, out);
257
    return LZO_E_OUTPUT_OVERRUN;
258
#endif
259
260
#if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
261
lookbehind_overrun:
262
    *out_len = pd(op, out);
263
    return LZO_E_LOOKBEHIND_OVERRUN;
264
#endif
265
2.10k
}
266
267
268
/* vim:set ts=4 sw=4 et: */