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], &copyBytes, 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], &copyBytes, 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