lzo: update to 2.09
[tomato.git] / release / src / router / lzo / src / lzo1f_d.ch
blobc5093c19ff4425055be52dbbae6461b66245534e
1 /* lzo1f_d.ch -- implementation of the LZO1F decompression algorithm
3    This file is part of the LZO real-time data compression library.
5    Copyright (C) 1996-2015 Markus Franz Xaver Johannes Oberhumer
6    All Rights Reserved.
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.
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.
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.
23    Markus F.X.J. Oberhumer
24    <markus@oberhumer.com>
25    http://www.oberhumer.com/opensource/lzo/
26  */
29 #include "lzo1_d.ch"
32 /***********************************************************************
33 // decompress a block of data.
34 ************************************************************************/
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 )
41     lzo_bytep op;
42     const lzo_bytep ip;
43     lzo_uint t;
44     const lzo_bytep m_pos;
46     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
51     LZO_UNUSED(wrkmem);
53     *out_len = 0;
55     op = out;
56     ip = in;
58     while (TEST_IP_AND_TEST_OP)
59     {
60         t = *ip++;
61         if (t > 31)
62             goto match;
64         /* a literal run */
65         if (t == 0)
66         {
67             NEED_IP(1);
68             while (*ip == 0)
69             {
70                 t += 255;
71                 ip++;
72                 TEST_IV(t);
73                 NEED_IP(1);
74             }
75             t += 31 + *ip++;
76         }
77         /* copy literals */
78         assert(t > 0); NEED_OP(t); NEED_IP(t+1);
79 #if (LZO_OPT_UNALIGNED32)
80         if (t >= 4)
81         {
82             do {
83                 UA_COPY4(op, ip);
84                 op += 4; ip += 4; t -= 4;
85             } while (t >= 4);
86             if (t > 0) do *op++ = *ip++; while (--t > 0);
87         }
88         else
89 #endif
90         do *op++ = *ip++; while (--t > 0);
92         t = *ip++;
94         while (TEST_IP_AND_TEST_OP)
95         {
96             /* handle matches */
97             if (t < 32)
98             {
99                 m_pos = op - 1 - 0x800;
100                 m_pos -= (t >> 2) & 7;
101                 m_pos -= *ip++ << 3;
102                 TEST_LB(m_pos); NEED_OP(3);
103                 *op++ = *m_pos++; *op++ = *m_pos++; *op++ = *m_pos++;
104             }
105             else
106             {
107 match:
108                 if (t < M3_MARKER)
109                 {
110                     m_pos = op - 1;
111                     m_pos -= (t >> 2) & 7;
112                     m_pos -= *ip++ << 3;
113                     t >>= 5;
114                     TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
115                     goto copy_match;
116                 }
117                 else
118                 {
119                     t &= 31;
120                     if (t == 0)
121                     {
122                         NEED_IP(1);
123                         while (*ip == 0)
124                         {
125                             t += 255;
126                             ip++;
127                             TEST_OV(t);
128                             NEED_IP(1);
129                         }
130                         t += 31 + *ip++;
131                     }
132                     NEED_IP(2);
133                     m_pos = op;
134 #if (LZO_OPT_UNALIGNED16) && (LZO_ABI_LITTLE_ENDIAN)
135                     m_pos -= UA_GET_LE16(ip) >> 2;
136                     ip += 2;
137 #else
138                     m_pos -= *ip++ >> 2;
139                     m_pos -= *ip++ << 6;
140 #endif
141                     if (m_pos == op)
142                         goto eof_found;
143                 }
145                 /* copy match */
146                 TEST_LB(m_pos); assert(t > 0); NEED_OP(t+3-1);
147 #if (LZO_OPT_UNALIGNED32)
148                 if (t >= 2 * 4 - (3 - 1) && (op - m_pos) >= 4)
149                 {
150                     UA_COPY4(op, m_pos);
151                     op += 4; m_pos += 4; t -= 4 - (3 - 1);
152                     do {
153                         UA_COPY4(op, m_pos);
154                         op += 4; m_pos += 4; t -= 4;
155                     } while (t >= 4);
156                     if (t > 0) do *op++ = *m_pos++; while (--t > 0);
157                 }
158                 else
159 #endif
160                 {
161 copy_match:
162                 *op++ = *m_pos++; *op++ = *m_pos++;
163                 do *op++ = *m_pos++; while (--t > 0);
164                 }
165             }
166             t = ip[-2] & 3;
167             if (t == 0)
168                 break;
170             /* copy literals */
171             assert(t > 0); NEED_OP(t); NEED_IP(t+1);
172             do *op++ = *ip++; while (--t > 0);
173             t = *ip++;
174         }
175     }
177 #if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP)
178     /* no EOF code was found */
179     *out_len = pd(op, out);
180     return LZO_E_EOF_NOT_FOUND;
181 #endif
183 eof_found:
184     assert(t == 1);
185     *out_len = pd(op, out);
186     return (ip == ip_end ? LZO_E_OK :
187            (ip < ip_end  ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
190 #if defined(HAVE_NEED_IP)
191 input_overrun:
192     *out_len = pd(op, out);
193     return LZO_E_INPUT_OVERRUN;
194 #endif
196 #if defined(HAVE_NEED_OP)
197 output_overrun:
198     *out_len = pd(op, out);
199     return LZO_E_OUTPUT_OVERRUN;
200 #endif
202 #if defined(LZO_TEST_OVERRUN_LOOKBEHIND)
203 lookbehind_overrun:
204     *out_len = pd(op, out);
205     return LZO_E_LOOKBEHIND_OVERRUN;
206 #endif
210 /* vim:set ts=4 sw=4 et: */