/src/lzo-2.10/src/lzo2a_d.ch
Line | Count | Source (jump to first uncovered line) |
1 | | /* lzo2a_d.ch -- implementation of the LZO2A 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 | 34.9k | #define _NEEDBYTE NEED_IP(1) |
37 | 34.9k | #define _NEXTBYTE (*ip++) |
38 | | |
39 | | LZO_PUBLIC(int) |
40 | | DO_DECOMPRESS ( const lzo_bytep in , lzo_uint in_len, |
41 | | lzo_bytep out, lzo_uintp out_len, |
42 | | lzo_voidp wrkmem ) |
43 | 189 | { |
44 | 189 | lzo_bytep op; |
45 | 189 | const lzo_bytep ip; |
46 | 189 | const lzo_bytep m_pos; |
47 | | |
48 | 189 | lzo_uint t; |
49 | 189 | const lzo_bytep const ip_end = in + in_len; |
50 | 189 | #if defined(HAVE_ANY_OP) |
51 | 189 | lzo_bytep const op_end = out + *out_len; |
52 | 189 | #endif |
53 | | |
54 | 189 | lzo_uint32_t b = 0; /* bit buffer */ |
55 | 189 | unsigned k = 0; /* bits in bit buffer */ |
56 | | |
57 | 189 | LZO_UNUSED(wrkmem); |
58 | | |
59 | 189 | op = out; |
60 | 189 | ip = in; |
61 | | |
62 | 189 | while (TEST_IP_AND_TEST_OP) |
63 | 260k | { |
64 | 260k | NEEDBITS(1); |
65 | 260k | if (MASKBITS(1) == 0) |
66 | 252k | { |
67 | 252k | DUMPBITS(1); |
68 | | /* a literal */ |
69 | 252k | NEED_IP(1); NEED_OP(1); |
70 | 252k | *op++ = *ip++; |
71 | 252k | continue; |
72 | 252k | } |
73 | 8.42k | DUMPBITS(1); |
74 | | |
75 | 8.42k | NEEDBITS(1); |
76 | 8.42k | if (MASKBITS(1) == 0) |
77 | 4.77k | { |
78 | 4.77k | DUMPBITS(1); |
79 | | /* a M1 match */ |
80 | 4.77k | NEEDBITS(2); |
81 | 4.77k | t = M1_MIN_LEN + (lzo_uint) MASKBITS(2); |
82 | 4.77k | DUMPBITS(2); |
83 | 4.77k | NEED_IP(1); NEED_OP(t); |
84 | 4.76k | m_pos = op - 1 - *ip++; |
85 | 4.76k | assert(m_pos >= out); assert(m_pos < op); |
86 | 4.76k | TEST_LB(m_pos); |
87 | 4.74k | MEMCPY_DS(op,m_pos,t); |
88 | 4.74k | continue; |
89 | 4.76k | } |
90 | 3.64k | DUMPBITS(1); |
91 | | |
92 | 3.64k | NEED_IP(2); |
93 | 3.63k | t = *ip++; |
94 | 3.63k | m_pos = op; |
95 | 3.63k | m_pos -= (t & 31) | (((lzo_uint) *ip++) << 5); |
96 | 3.63k | t >>= 5; |
97 | 3.63k | if (t == 0) |
98 | 1.02k | { |
99 | | #if (SWD_N >= 8192) |
100 | | NEEDBITS(1); |
101 | | t = MASKBITS(1); |
102 | | DUMPBITS(1); |
103 | | if (t == 0) |
104 | | t = 10 - 1; |
105 | | else |
106 | | { |
107 | | /* a M3 match */ |
108 | | m_pos -= 8192; /* t << 13 */ |
109 | | t = M3_MIN_LEN - 1; |
110 | | } |
111 | | #else |
112 | 1.02k | t = 10 - 1; |
113 | 1.02k | #endif |
114 | 1.02k | NEED_IP(1); |
115 | 1.73M | while (*ip == 0) |
116 | 1.73M | { |
117 | 1.73M | t += 255; |
118 | 1.73M | ip++; |
119 | 1.73M | TEST_OV(t); |
120 | 1.73M | NEED_IP(1); |
121 | 1.73M | } |
122 | 1.00k | t += *ip++; |
123 | 1.00k | } |
124 | 2.61k | else |
125 | 2.61k | { |
126 | 2.61k | #if defined(LZO_EOF_CODE) |
127 | 2.61k | if (m_pos == op) |
128 | 4 | goto eof_found; |
129 | 2.61k | #endif |
130 | 2.61k | t += 2; |
131 | 2.61k | } |
132 | 3.61k | assert(m_pos >= out); assert(m_pos < op); |
133 | 3.61k | TEST_LB(m_pos); |
134 | 3.55k | NEED_OP(t); |
135 | 3.54k | MEMCPY_DS(op,m_pos,t); |
136 | 3.54k | } |
137 | | |
138 | | |
139 | 53 | #if defined(LZO_EOF_CODE) |
140 | 53 | #if defined(HAVE_TEST_IP) || defined(HAVE_TEST_OP) |
141 | | /* no EOF code was found */ |
142 | 53 | *out_len = pd(op, out); |
143 | 53 | return LZO_E_EOF_NOT_FOUND; |
144 | 0 | #endif |
145 | | |
146 | 4 | eof_found: |
147 | 4 | assert(t == 1); |
148 | 4 | #endif |
149 | 4 | *out_len = pd(op, out); |
150 | 4 | return (ip == ip_end ? LZO_E_OK : |
151 | 4 | (ip < ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN)); |
152 | | |
153 | | |
154 | 0 | #if defined(HAVE_NEED_IP) |
155 | 42 | input_overrun: |
156 | 42 | *out_len = pd(op, out); |
157 | 42 | return LZO_E_INPUT_OVERRUN; |
158 | 0 | #endif |
159 | | |
160 | 0 | #if defined(HAVE_NEED_OP) |
161 | 9 | output_overrun: |
162 | 9 | *out_len = pd(op, out); |
163 | 9 | return LZO_E_OUTPUT_OVERRUN; |
164 | 0 | #endif |
165 | | |
166 | 0 | #if defined(LZO_TEST_OVERRUN_LOOKBEHIND) |
167 | 81 | lookbehind_overrun: |
168 | 81 | *out_len = pd(op, out); |
169 | 81 | return LZO_E_LOOKBEHIND_OVERRUN; |
170 | 189 | #endif |
171 | 189 | } |
172 | | |
173 | | |
174 | | /* vim:set ts=4 sw=4 et: */ |