1 /*****************************************************************************/
2 /* explode.c Copyright (c) Ladislav Zezula 2003 */
3 /*---------------------------------------------------------------------------*/
4 /* Implode function of PKWARE Data Compression library */
5 /*---------------------------------------------------------------------------*/
6 /* Date Ver Who Comment */
7 /* -------- ---- --- ------- */
8 /* 11.03.03 1.00 Lad Splitted from Pkware.cpp */
9 /* 08.04.03 1.01 Lad Renamed to explode.c to be compatible with pklib */
10 /* 02.05.03 1.01 Lad Stress test done */
11 /* 22.04.10 1.01 Lad Documented */
12 /*****************************************************************************/
13
14 #include <assert.h>
15 #include <string.h>
16
17 #include "pklib.h"
18
19 #define PKDCL_OK 0
20 #define PKDCL_STREAM_END 1 // All data from the input stream is read
21 #define PKDCL_NEED_DICT 2 // Need more data (dictionary)
22 #define PKDCL_CONTINUE 10 // Internal flag, not returned to user
23 #define PKDCL_GET_INPUT 11 // Internal flag, not returned to user
24
25 char CopyrightPkware[] = "PKWARE Data Compression Library for Win32\r\n"
26 "Copyright 1989-1995 PKWARE Inc. All Rights Reserved\r\n"
27 "Patent No. 5,051,745\r\n"
28 "PKWARE Data Compression Library Reg. U.S. Pat. and Tm. Off.\r\n"
29 "Version 1.11\r\n";
30
31 //-----------------------------------------------------------------------------
32 // Tables
33
34 unsigned char DistBits[0x40] =
35 {
36 0x02, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
37 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
38 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
39 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
40 };
41
42 unsigned char DistCode[0x40] =
43 {
44 0x03, 0x0D, 0x05, 0x19, 0x09, 0x11, 0x01, 0x3E, 0x1E, 0x2E, 0x0E, 0x36, 0x16, 0x26, 0x06, 0x3A,
45 0x1A, 0x2A, 0x0A, 0x32, 0x12, 0x22, 0x42, 0x02, 0x7C, 0x3C, 0x5C, 0x1C, 0x6C, 0x2C, 0x4C, 0x0C,
46 0x74, 0x34, 0x54, 0x14, 0x64, 0x24, 0x44, 0x04, 0x78, 0x38, 0x58, 0x18, 0x68, 0x28, 0x48, 0x08,
47 0xF0, 0x70, 0xB0, 0x30, 0xD0, 0x50, 0x90, 0x10, 0xE0, 0x60, 0xA0, 0x20, 0xC0, 0x40, 0x80, 0x00
48 };
49
50 unsigned char ExLenBits[0x10] =
51 {
52 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08
53 };
54
55 unsigned short LenBase[0x10] =
56 {
57 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
58 0x0008, 0x000A, 0x000E, 0x0016, 0x0026, 0x0046, 0x0086, 0x0106
59 };
60
61 unsigned char LenBits[0x10] =
62 {
63 0x03, 0x02, 0x03, 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x07, 0x07
64 };
65
66 unsigned char LenCode[0x10] =
67 {
68 0x05, 0x03, 0x01, 0x06, 0x0A, 0x02, 0x0C, 0x14, 0x04, 0x18, 0x08, 0x30, 0x10, 0x20, 0x40, 0x00
69 };
70
71 unsigned char ChBitsAsc[0x100] =
72 {
73 0x0B, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x08, 0x07, 0x0C, 0x0C, 0x07, 0x0C, 0x0C,
74 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
75 0x04, 0x0A, 0x08, 0x0C, 0x0A, 0x0C, 0x0A, 0x08, 0x07, 0x07, 0x08, 0x09, 0x07, 0x06, 0x07, 0x08,
76 0x07, 0x06, 0x07, 0x07, 0x07, 0x07, 0x08, 0x07, 0x07, 0x08, 0x08, 0x0C, 0x0B, 0x07, 0x09, 0x0B,
77 0x0C, 0x06, 0x07, 0x06, 0x06, 0x05, 0x07, 0x08, 0x08, 0x06, 0x0B, 0x09, 0x06, 0x07, 0x06, 0x06,
78 0x07, 0x0B, 0x06, 0x06, 0x06, 0x07, 0x09, 0x08, 0x09, 0x09, 0x0B, 0x08, 0x0B, 0x09, 0x0C, 0x08,
79 0x0C, 0x05, 0x06, 0x06, 0x06, 0x05, 0x06, 0x06, 0x06, 0x05, 0x0B, 0x07, 0x05, 0x06, 0x05, 0x05,
80 0x06, 0x0A, 0x05, 0x05, 0x05, 0x05, 0x08, 0x07, 0x08, 0x08, 0x0A, 0x0B, 0x0B, 0x0C, 0x0C, 0x0C,
81 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
82 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
83 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D,
84 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
85 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
86 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C,
87 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0C, 0x0D,
88 0x0D, 0x0D, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D, 0x0D
89 };
90
91 unsigned short ChCodeAsc[0x100] =
92 {
93 0x0490, 0x0FE0, 0x07E0, 0x0BE0, 0x03E0, 0x0DE0, 0x05E0, 0x09E0,
94 0x01E0, 0x00B8, 0x0062, 0x0EE0, 0x06E0, 0x0022, 0x0AE0, 0x02E0,
95 0x0CE0, 0x04E0, 0x08E0, 0x00E0, 0x0F60, 0x0760, 0x0B60, 0x0360,
96 0x0D60, 0x0560, 0x1240, 0x0960, 0x0160, 0x0E60, 0x0660, 0x0A60,
97 0x000F, 0x0250, 0x0038, 0x0260, 0x0050, 0x0C60, 0x0390, 0x00D8,
98 0x0042, 0x0002, 0x0058, 0x01B0, 0x007C, 0x0029, 0x003C, 0x0098,
99 0x005C, 0x0009, 0x001C, 0x006C, 0x002C, 0x004C, 0x0018, 0x000C,
100 0x0074, 0x00E8, 0x0068, 0x0460, 0x0090, 0x0034, 0x00B0, 0x0710,
101 0x0860, 0x0031, 0x0054, 0x0011, 0x0021, 0x0017, 0x0014, 0x00A8,
102 0x0028, 0x0001, 0x0310, 0x0130, 0x003E, 0x0064, 0x001E, 0x002E,
103 0x0024, 0x0510, 0x000E, 0x0036, 0x0016, 0x0044, 0x0030, 0x00C8,
104 0x01D0, 0x00D0, 0x0110, 0x0048, 0x0610, 0x0150, 0x0060, 0x0088,
105 0x0FA0, 0x0007, 0x0026, 0x0006, 0x003A, 0x001B, 0x001A, 0x002A,
106 0x000A, 0x000B, 0x0210, 0x0004, 0x0013, 0x0032, 0x0003, 0x001D,
107 0x0012, 0x0190, 0x000D, 0x0015, 0x0005, 0x0019, 0x0008, 0x0078,
108 0x00F0, 0x0070, 0x0290, 0x0410, 0x0010, 0x07A0, 0x0BA0, 0x03A0,
109 0x0240, 0x1C40, 0x0C40, 0x1440, 0x0440, 0x1840, 0x0840, 0x1040,
110 0x0040, 0x1F80, 0x0F80, 0x1780, 0x0780, 0x1B80, 0x0B80, 0x1380,
111 0x0380, 0x1D80, 0x0D80, 0x1580, 0x0580, 0x1980, 0x0980, 0x1180,
112 0x0180, 0x1E80, 0x0E80, 0x1680, 0x0680, 0x1A80, 0x0A80, 0x1280,
113 0x0280, 0x1C80, 0x0C80, 0x1480, 0x0480, 0x1880, 0x0880, 0x1080,
114 0x0080, 0x1F00, 0x0F00, 0x1700, 0x0700, 0x1B00, 0x0B00, 0x1300,
115 0x0DA0, 0x05A0, 0x09A0, 0x01A0, 0x0EA0, 0x06A0, 0x0AA0, 0x02A0,
116 0x0CA0, 0x04A0, 0x08A0, 0x00A0, 0x0F20, 0x0720, 0x0B20, 0x0320,
117 0x0D20, 0x0520, 0x0920, 0x0120, 0x0E20, 0x0620, 0x0A20, 0x0220,
118 0x0C20, 0x0420, 0x0820, 0x0020, 0x0FC0, 0x07C0, 0x0BC0, 0x03C0,
119 0x0DC0, 0x05C0, 0x09C0, 0x01C0, 0x0EC0, 0x06C0, 0x0AC0, 0x02C0,
120 0x0CC0, 0x04C0, 0x08C0, 0x00C0, 0x0F40, 0x0740, 0x0B40, 0x0340,
121 0x0300, 0x0D40, 0x1D00, 0x0D00, 0x1500, 0x0540, 0x0500, 0x1900,
122 0x0900, 0x0940, 0x1100, 0x0100, 0x1E00, 0x0E00, 0x0140, 0x1600,
123 0x0600, 0x1A00, 0x0E40, 0x0640, 0x0A40, 0x0A00, 0x1200, 0x0200,
124 0x1C00, 0x0C00, 0x1400, 0x0400, 0x1800, 0x0800, 0x1000, 0x0000
125 };
126
127 //-----------------------------------------------------------------------------
128 // Local functions
129
GenDecodeTabs(unsigned char * positions,unsigned char * start_indexes,unsigned char * length_bits,size_t elements)130 static void GenDecodeTabs(
131 unsigned char * positions, // [out] Table of positions
132 unsigned char * start_indexes, // [in] Table of start indexes
133 unsigned char * length_bits, // [in] Table of lengths. Each length is stored as number of bits
134 size_t elements) // [in] Number of elements in start_indexes and length_bits
135 {
136 unsigned int index;
137 unsigned int length;
138 size_t i;
139
140 for(i = 0; i < elements; i++)
141 {
142 length = 1 << length_bits[i]; // Get the length in bytes
143
144 for(index = start_indexes[i]; index < 0x100; index += length)
145 {
146 positions[index] = (unsigned char)i;
147 }
148 }
149 }
150
GenAscTabs(TDcmpStruct * pWork)151 static void GenAscTabs(TDcmpStruct * pWork)
152 {
153 unsigned short * pChCodeAsc = &ChCodeAsc[0xFF];
154 unsigned int acc, add;
155 unsigned short count;
156
157 for(count = 0x00FF; pChCodeAsc >= ChCodeAsc; pChCodeAsc--, count--)
158 {
159 unsigned char * pChBitsAsc = pWork->ChBitsAsc + count;
160 unsigned char bits_asc = *pChBitsAsc;
161
162 if(bits_asc <= 8)
163 {
164 add = (1 << bits_asc);
165 acc = *pChCodeAsc;
166
167 do
168 {
169 pWork->offs2C34[acc] = (unsigned char)count;
170 acc += add;
171 }
172 while(acc < 0x100);
173 }
174 else if((acc = (*pChCodeAsc & 0xFF)) != 0)
175 {
176 pWork->offs2C34[acc] = 0xFF;
177
178 if(*pChCodeAsc & 0x3F)
179 {
180 bits_asc -= 4;
181 *pChBitsAsc = bits_asc;
182
183 add = (1 << bits_asc);
184 acc = *pChCodeAsc >> 4;
185 do
186 {
187 pWork->offs2D34[acc] = (unsigned char)count;
188 acc += add;
189 }
190 while(acc < 0x100);
191 }
192 else
193 {
194 bits_asc -= 6;
195 *pChBitsAsc = bits_asc;
196
197 add = (1 << bits_asc);
198 acc = *pChCodeAsc >> 6;
199 do
200 {
201 pWork->offs2E34[acc] = (unsigned char)count;
202 acc += add;
203 }
204 while(acc < 0x80);
205 }
206 }
207 else
208 {
209 bits_asc -= 8;
210 *pChBitsAsc = bits_asc;
211
212 add = (1 << bits_asc);
213 acc = *pChCodeAsc >> 8;
214 do
215 {
216 pWork->offs2EB4[acc] = (unsigned char)count;
217 acc += add;
218 }
219 while(acc < 0x100);
220 }
221 }
222 }
223
224 //-----------------------------------------------------------------------------
225 // Removes given number of bits in the bit buffer. New bits are reloaded from
226 // the input buffer, if needed.
227 // Returns: PKDCL_OK: Operation was successful
228 // PKDCL_STREAM_END: There are no more bits in the input buffer
229
WasteBits(TDcmpStruct * pWork,unsigned int nBits)230 static int WasteBits(TDcmpStruct * pWork, unsigned int nBits)
231 {
232 // If number of bits required is less than number of (bits in the buffer) ?
233 if(nBits <= pWork->extra_bits)
234 {
235 pWork->extra_bits -= nBits;
236 pWork->bit_buff >>= nBits;
237 return PKDCL_OK;
238 }
239
240 // Load input buffer if necessary
241 pWork->bit_buff >>= pWork->extra_bits;
242 if(pWork->in_pos == pWork->in_bytes)
243 {
244 pWork->in_pos = sizeof(pWork->in_buff);
245 if((pWork->in_bytes = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param)) == 0)
246 return PKDCL_STREAM_END;
247 pWork->in_pos = 0;
248 }
249
250 // Update bit buffer
251 pWork->bit_buff |= (pWork->in_buff[pWork->in_pos++] << 8);
252 pWork->bit_buff >>= (nBits - pWork->extra_bits);
253 pWork->extra_bits = (pWork->extra_bits - nBits) + 8;
254 return PKDCL_OK;
255 }
256
257 //-----------------------------------------------------------------------------
258 // Decodes next literal from the input (compressed) data.
259 // Returns : 0x000: One byte 0x00
260 // 0x001: One byte 0x01
261 // ...
262 // 0x0FF: One byte 0xFF
263 // 0x100: Repetition, length of 0x02 bytes
264 // 0x101: Repetition, length of 0x03 bytes
265 // ...
266 // 0x304: Repetition, length of 0x206 bytes
267 // 0x305: End of stream
268 // 0x306: Error
269
DecodeLit(TDcmpStruct * pWork)270 static unsigned int DecodeLit(TDcmpStruct * pWork)
271 {
272 unsigned int extra_length_bits; // Number of bits of extra literal length
273 unsigned int length_code; // Length code
274 unsigned int value;
275
276 // Test the current bit in byte buffer. If is not set, simply return the next 8 bits.
277 if(pWork->bit_buff & 1)
278 {
279 // Remove one bit from the input data
280 if(WasteBits(pWork, 1))
281 return 0x306;
282
283 // The next 8 bits hold the index to the length code table
284 length_code = pWork->LengthCodes[pWork->bit_buff & 0xFF];
285
286 // Remove the apropriate number of bits
287 if(WasteBits(pWork, pWork->LenBits[length_code]))
288 return 0x306;
289
290 // Are there some extra bits for the obtained length code ?
291 if((extra_length_bits = pWork->ExLenBits[length_code]) != 0)
292 {
293 unsigned int extra_length = pWork->bit_buff & ((1 << extra_length_bits) - 1);
294
295 if(WasteBits(pWork, extra_length_bits))
296 {
297 if((length_code + extra_length) != 0x10E)
298 return 0x306;
299 }
300 length_code = pWork->LenBase[length_code] + extra_length;
301 }
302
303 // In order to distinguish uncompressed byte from repetition length,
304 // we have to add 0x100 to the length.
305 return length_code + 0x100;
306 }
307
308 // Remove one bit from the input data
309 if(WasteBits(pWork, 1))
310 return 0x306;
311
312 // If the binary compression type, read 8 bits and return them as one byte.
313 if(pWork->ctype == CMP_BINARY)
314 {
315 unsigned int uncompressed_byte = pWork->bit_buff & 0xFF;
316
317 if(WasteBits(pWork, 8))
318 return 0x306;
319 return uncompressed_byte;
320 }
321
322 // When ASCII compression ...
323 if(pWork->bit_buff & 0xFF)
324 {
325 value = pWork->offs2C34[pWork->bit_buff & 0xFF];
326
327 if(value == 0xFF)
328 {
329 if(pWork->bit_buff & 0x3F)
330 {
331 if(WasteBits(pWork, 4))
332 return 0x306;
333
334 value = pWork->offs2D34[pWork->bit_buff & 0xFF];
335 }
336 else
337 {
338 if(WasteBits(pWork, 6))
339 return 0x306;
340
341 value = pWork->offs2E34[pWork->bit_buff & 0x7F];
342 }
343 }
344 }
345 else
346 {
347 if(WasteBits(pWork, 8))
348 return 0x306;
349
350 value = pWork->offs2EB4[pWork->bit_buff & 0xFF];
351 }
352
353 return WasteBits(pWork, pWork->ChBitsAsc[value]) ? 0x306 : value;
354 }
355
356 //-----------------------------------------------------------------------------
357 // Decodes the distance of the repetition, backwards relative to the
358 // current output buffer position
359
DecodeDist(TDcmpStruct * pWork,unsigned int rep_length)360 static unsigned int DecodeDist(TDcmpStruct * pWork, unsigned int rep_length)
361 {
362 unsigned int dist_pos_code; // Distance position code
363 unsigned int dist_pos_bits; // Number of bits of distance position
364 unsigned int distance; // Distance position
365
366 // Next 2-8 bits in the input buffer is the distance position code
367 dist_pos_code = pWork->DistPosCodes[pWork->bit_buff & 0xFF];
368 dist_pos_bits = pWork->DistBits[dist_pos_code];
369 if(WasteBits(pWork, dist_pos_bits))
370 return 0;
371
372 if(rep_length == 2)
373 {
374 // If the repetition is only 2 bytes length,
375 // then take 2 bits from the stream in order to get the distance
376 distance = (dist_pos_code << 2) | (pWork->bit_buff & 0x03);
377 if(WasteBits(pWork, 2))
378 return 0;
379 }
380 else
381 {
382 // If the repetition is more than 2 bytes length,
383 // then take "dsize_bits" bits in order to get the distance
384 distance = (dist_pos_code << pWork->dsize_bits) | (pWork->bit_buff & pWork->dsize_mask);
385 if(WasteBits(pWork, pWork->dsize_bits))
386 return 0;
387 }
388 return distance + 1;
389 }
390
Expand(TDcmpStruct * pWork)391 static unsigned int Expand(TDcmpStruct * pWork)
392 {
393 unsigned int next_literal; // Literal decoded from the compressed data
394 unsigned int result; // Value to be returned
395 unsigned int copyBytes; // Number of bytes to copy to the output buffer
396
397 pWork->outputPos = 0x1000; // Initialize output buffer position
398
399 // Decode the next literal from the input data.
400 // The returned literal can either be an uncompressed byte (next_literal < 0x100)
401 // or an encoded length of the repeating byte sequence that
402 // is to be copied to the current buffer position
403 while((result = next_literal = DecodeLit(pWork)) < 0x305)
404 {
405 // If the literal is greater than 0x100, it holds length
406 // of repeating byte sequence
407 // literal of 0x100 means repeating sequence of 0x2 bytes
408 // literal of 0x101 means repeating sequence of 0x3 bytes
409 // ...
410 // literal of 0x305 means repeating sequence of 0x207 bytes
411 if(next_literal >= 0x100)
412 {
413 unsigned char * source;
414 unsigned char * target;
415 unsigned int rep_length; // Length of the repetition, in bytes
416 unsigned int minus_dist; // Backward distance to the repetition, relative to the current buffer position
417
418 // Get the length of the repeating sequence.
419 // Note that the repeating block may overlap the current output position,
420 // for example if there was a sequence of equal bytes
421 rep_length = next_literal - 0xFE;
422
423 // Get backward distance to the repetition
424 if((minus_dist = DecodeDist(pWork, rep_length)) == 0)
425 {
426 result = 0x306;
427 break;
428 }
429
430 // Target and source pointer
431 target = &pWork->out_buff[pWork->outputPos];
432 source = target - minus_dist;
433
434 // Update buffer output position
435 pWork->outputPos += rep_length;
436
437 // Copy the repeating sequence
438 while(rep_length-- > 0)
439 *target++ = *source++;
440 }
441 else
442 {
443 pWork->out_buff[pWork->outputPos++] = (unsigned char)next_literal;
444 }
445
446 // Flush the output buffer, if number of extracted bytes has reached the end
447 if(pWork->outputPos >= 0x2000)
448 {
449 // Copy decompressed data into user buffer
450 copyBytes = 0x1000;
451 pWork->write_buf((char *)&pWork->out_buff[0x1000], ©Bytes, pWork->param);
452
453 // Now copy the decompressed data to the first half of the buffer.
454 // This is needed because the decompression might reuse them as repetitions.
455 // Note that if the output buffer overflowed previously, the extra decompressed bytes
456 // are stored in "out_buff_overflow", and they will now be
457 // within decompressed part of the output buffer.
458 memmove(pWork->out_buff, &pWork->out_buff[0x1000], pWork->outputPos - 0x1000);
459 pWork->outputPos -= 0x1000;
460 }
461 }
462
463 // Flush any remaining decompressed bytes
464 copyBytes = pWork->outputPos - 0x1000;
465 pWork->write_buf((char *)&pWork->out_buff[0x1000], ©Bytes, pWork->param);
466 return result;
467 }
468
469
470 //-----------------------------------------------------------------------------
471 // Main exploding function.
472
explode(unsigned int (* read_buf)(char * buf,unsigned int * size,void * param),void (* write_buf)(char * buf,unsigned int * size,void * param),char * work_buf,void * param)473 unsigned int PKEXPORT explode(
474 unsigned int (*read_buf)(char *buf, unsigned int *size, void *param),
475 void (*write_buf)(char *buf, unsigned int *size, void *param),
476 char *work_buf,
477 void *param)
478 {
479 TDcmpStruct * pWork = (TDcmpStruct *)work_buf;
480
481 // Initialize work struct and load compressed data
482 // Note: The caller must zero the "work_buff" before passing it to explode
483 pWork->read_buf = read_buf;
484 pWork->write_buf = write_buf;
485 pWork->param = param;
486 pWork->in_pos = sizeof(pWork->in_buff);
487 pWork->in_bytes = pWork->read_buf((char *)pWork->in_buff, &pWork->in_pos, pWork->param);
488 if(pWork->in_bytes <= 4)
489 return CMP_BAD_DATA;
490
491 pWork->ctype = pWork->in_buff[0]; // Get the compression type (CMP_BINARY or CMP_ASCII)
492 pWork->dsize_bits = pWork->in_buff[1]; // Get the dictionary size
493 pWork->bit_buff = pWork->in_buff[2]; // Initialize 16-bit bit buffer
494 pWork->extra_bits = 0; // Extra (over 8) bits
495 pWork->in_pos = 3; // Position in input buffer
496
497 // Test for the valid dictionary size
498 if(4 > pWork->dsize_bits || pWork->dsize_bits > 6)
499 return CMP_INVALID_DICTSIZE;
500
501 pWork->dsize_mask = 0xFFFF >> (0x10 - pWork->dsize_bits); // Shifted by 'sar' instruction
502
503 if(pWork->ctype != CMP_BINARY)
504 {
505 if(pWork->ctype != CMP_ASCII)
506 return CMP_INVALID_MODE;
507
508 memcpy(pWork->ChBitsAsc, ChBitsAsc, sizeof(pWork->ChBitsAsc));
509 GenAscTabs(pWork);
510 }
511
512 memcpy(pWork->LenBits, LenBits, sizeof(pWork->LenBits));
513 GenDecodeTabs(pWork->LengthCodes, LenCode, pWork->LenBits, sizeof(pWork->LenBits));
514 memcpy(pWork->ExLenBits, ExLenBits, sizeof(pWork->ExLenBits));
515 memcpy(pWork->LenBase, LenBase, sizeof(pWork->LenBase));
516 memcpy(pWork->DistBits, DistBits, sizeof(pWork->DistBits));
517 GenDecodeTabs(pWork->DistPosCodes, DistCode, pWork->DistBits, sizeof(pWork->DistBits));
518 if(Expand(pWork) != 0x306)
519 return CMP_NO_ERROR;
520
521 return CMP_ABORT;
522 }
523