Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
1 | daniel-mar | 1 | #include "stdafx.h" |
2 | #pragma hdrstop |
||
3 | #include "ZipDflt.h" |
||
4 | //#include "Zip.h" |
||
5 | //#include "ZipErr.h" |
||
6 | #include "dz_errs.h" |
||
7 | |||
8 | #undef _DZ_FILE_ |
||
9 | #define _DZ_FILE_ DZ_ZBITS_CPP |
||
10 | |||
11 | /* Bits.c |
||
12 | * Copyright (C) 1990-1996 Mark Adler, Richard B. Wales, Jean-loup Gailly, |
||
13 | * Kai Uwe Rommel, Onno van der Linden and Igor Mandrichenko. |
||
14 | * Permission is granted to any individual or institution to use, copy, or |
||
15 | * redistribute this software so long as all of the original files are included, |
||
16 | * that it is not sold for profit, and that this copyright notice is retained. |
||
17 | * This version modified by Chris Vleghert and Eric Engler for BCB/Delphi Zip. |
||
18 | |||
19 | Copyright (c) 1990-2007 Info-ZIP. All rights reserved. |
||
20 | |||
21 | See the accompanying file LICENSE, version 2007-Mar-4 or later |
||
22 | (the contents of which are also included in zip.h) for terms of use. |
||
23 | If, for some reason, all these files are missing, the Info-ZIP license |
||
24 | also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html |
||
25 | |||
26 | parts Copyright (C) 1997 Mike White, Eric W. Engler |
||
27 | ************************************************************************ |
||
28 | Copyright (C) 2009, 2010 by Russell J. Peters, Roger Aelbrecht |
||
29 | |||
30 | This file is part of TZipMaster Version 1.9. |
||
31 | |||
32 | TZipMaster is free software: you can redistribute it and/or modify |
||
33 | it under the terms of the GNU Lesser General Public License as published by |
||
34 | the Free Software Foundation, either version 3 of the License, or |
||
35 | (at your option) any later version. |
||
36 | |||
37 | TZipMaster is distributed in the hope that it will be useful, |
||
38 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
39 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
40 | GNU Lesser General Public License for more details. |
||
41 | |||
42 | You should have received a copy of the GNU Lesser General Public License |
||
43 | along with TZipMaster. If not, see <http://www.gnu.org/licenses/>. |
||
44 | |||
45 | contact: problems@delphizip.org (include ZipMaster in the subject). |
||
46 | updates: http://www.delphizip.org |
||
47 | DelphiZip maillist subscribe at http://www.freelists.org/list/delphizip |
||
48 | ************************************************************************/ |
||
49 | |||
50 | /* |
||
51 | * bits.c by Jean-loup Gailly and Kai Uwe Rommel. |
||
52 | * |
||
53 | * This is a new version of im_bits.c originally written by Richard B. Wales |
||
54 | * |
||
55 | * PURPOSE |
||
56 | * |
||
57 | * Output variable-length bit strings. Compression can be done |
||
58 | * to a file or to memory. |
||
59 | * |
||
60 | * DISCUSSION |
||
61 | * |
||
62 | * The PKZIP "deflate" file format interprets compressed file data |
||
63 | * as a sequence of bits. Multi-bit strings in the file may cross |
||
64 | * byte boundaries without restriction. |
||
65 | * |
||
66 | * The first bit of each byte is the low-order bit. |
||
67 | * |
||
68 | * The routines in this file allow a variable-length bit value to |
||
69 | * be output right-to-left (useful for literal values). For |
||
70 | * left-to-right output (useful for code strings from the tree routines), |
||
71 | * the bits must have been reversed first with bi_reverse(). |
||
72 | * |
||
73 | * For in-memory compression, the compressed bit stream goes directly |
||
74 | * into the requested output buffer. The input data is read in blocks |
||
75 | * by the mem_read() function. The buffer is limited to 64K on 16 bit |
||
76 | * machines. |
||
77 | * |
||
78 | * INTERFACE |
||
79 | * |
||
80 | * void bi_init(FILE *zipfile) |
||
81 | * Initialize the bit string routines. |
||
82 | * |
||
83 | * void send_bits(int value, int length) |
||
84 | * Write out a bit string, taking the source bits right to |
||
85 | * left. |
||
86 | * |
||
87 | * int bi_reverse(int value, int length) |
||
88 | * Reverse the bits of a bit string, taking the source bits left to |
||
89 | * right and emitting them right to left. |
||
90 | * |
||
91 | * void bi_windup(void) |
||
92 | * Write out any remaining bits in an incomplete byte. |
||
93 | * |
||
94 | * void copy_block(char *buf, unsigned len, int header) |
||
95 | * Copy a stored block to the zip file, storing first the length and |
||
96 | * its one's complement if requested. |
||
97 | * |
||
98 | * int seekable(void) |
||
99 | * Return true if the zip file can be seeked. |
||
100 | * |
||
101 | * ulg memcompress(char *tgt, ulg tgtsize, char *src, ulg srcsize); |
||
102 | * Compress the source buffer src into the target buffer tgt. |
||
103 | */ |
||
104 | |||
105 | // Number of bits used within bi_buf. (bi_buf might be implemented on more |
||
106 | // than 16 bits on some systems.) |
||
107 | #define Buf_size (8 * 2 * sizeof(char)) |
||
108 | |||
109 | // fout_buf[fout_offset++] = (char)(b); |
||
110 | // Output a 16 bit value to the bit stream, lower (oldest) byte first |
||
111 | #define PUTBYTE(b) \ |
||
112 | { \ |
||
113 | if (fout_offset < sizeof(f_outbuf)) \ |
||
114 | { \ |
||
115 | f_outbuf[fout_offset++] = (char)(b); \ |
||
116 | } \ |
||
117 | else \ |
||
118 | { \ |
||
119 | flush_outbuf((b), 1); \ |
||
120 | } \ |
||
121 | } |
||
122 | |||
123 | // Prototypes for local functions |
||
124 | #ifdef _USE_ASM_ |
||
125 | extern unsigned __fastcall bi_reverse(unsigned code, int len); |
||
126 | #endif |
||
127 | |||
128 | // Initialize the bit string routines. zipfile :: Output zip file, NULL for |
||
129 | // in-memory compression. |
||
130 | void ZipDflt::bi_init(void) //HANDLE zipfile) |
||
131 | { |
||
132 | // fzfile = zipfile; |
||
133 | fbi_buf = 0; |
||
134 | fbi_valid = 0; |
||
135 | #ifdef DEBUG |
||
136 | fbits_sent = 0L; |
||
137 | #endif |
||
138 | // Set the defaults for file compression. They are set by memcompress for |
||
139 | // in-memory compression. |
||
140 | // if (fzfile > 0) //!= INVALID_HANDLE_VALUE) |
||
141 | // if (fhOutz != INVALID_HANDLE_VALUE) |
||
142 | |||
143 | if (fZipOutfile && fZipOutfile->IsOpen()) |
||
144 | { |
||
145 | // fout_buf = ffile_outbuf; |
||
146 | // fout_size = sizeof(ffile_outbuf); |
||
147 | fout_offset = 0; |
||
148 | // fread_buf = &ZipDflt::file_read; |
||
149 | //#if defined(USE_STRM_INPUT) && defined(USE_STRM_OUTPUT) |
||
150 | // ReadingFile = -1; |
||
151 | //#endif |
||
152 | } |
||
153 | } |
||
154 | |||
155 | // Send a value on a given number of bits. IN assertion: length <= 16 and |
||
156 | // value fits in length bits. value :: Value to send. length :: Number of |
||
157 | // bits. |
||
158 | void __fastcall ZipDflt::send_bits(int value, int length) |
||
159 | { |
||
160 | #ifdef DEBUG |
||
161 | Tracevv((_T(" l %2d v %4x ")), (length, value)); |
||
162 | Assert(length > 0 && length <= 15, _T("invalid length")); |
||
163 | fbits_sent += (ulg) length; |
||
164 | #endif |
||
165 | |||
166 | // If not enough room in bi_buf, use (valid) bits from bi_buf and (16 - |
||
167 | // bi_valid) bits from value, leaving (width - (16-bi_valid)) unused bits |
||
168 | // in value. |
||
169 | |||
170 | if (fbi_valid > (int)Buf_size - length) |
||
171 | { |
||
172 | fbi_buf |= (ush)(value << fbi_valid); // RCV Added (ush) |
||
173 | |||
174 | // PUTSHORT(fbi_buf); /* |
||
175 | |||
176 | if (fout_offset < sizeof(f_outbuf) -1) //fout_size - 1) |
||
177 | { |
||
178 | *(ush *)(f_outbuf + fout_offset) = (ush) fbi_buf; |
||
179 | // f_outbuf[fout_offset] = (ush) fbi_buf; |
||
180 | fout_offset += 2; |
||
181 | } |
||
182 | else |
||
183 | { |
||
184 | flush_outbuf((fbi_buf), 2); |
||
185 | } |
||
186 | |||
187 | fbi_buf = (ush)((ush) value >> (Buf_size - fbi_valid)); // RCV Added (ush)(...) |
||
188 | fbi_valid += length - Buf_size; |
||
189 | } |
||
190 | else |
||
191 | { |
||
192 | fbi_buf |= (ush)(value << fbi_valid); // RCV Added (ush) |
||
193 | fbi_valid += length; |
||
194 | } |
||
195 | } |
||
196 | |||
197 | // Reverse the first len bits of a code, using straightforward code (a |
||
198 | // faster method would use a table) IN assertion: 1 <= len <= 15 code :: The |
||
199 | // value to invert. len :: Its bit length. |
||
200 | #ifndef _USE_ASM_ |
||
201 | unsigned __fastcall bi_reverse(unsigned code, int len) |
||
202 | { |
||
203 | register unsigned res = 0; |
||
204 | |||
205 | do |
||
206 | { |
||
207 | res |= code & 1; |
||
208 | code >>= 1, res <<= 1; |
||
209 | } |
||
210 | while (--len > 0); |
||
211 | |||
212 | return (res >> 1); |
||
213 | } |
||
214 | // |
||
215 | //#else |
||
216 | //unsigned __fastcall bi_reverse(unsigned code, int len) |
||
217 | //{ |
||
218 | //#pragma warn - rvl |
||
219 | //#pragma argsused |
||
220 | // asm |
||
221 | // { |
||
222 | // // EAX=code EDX=len |
||
223 | // mov ecx, eax |
||
224 | // xor eax, eax |
||
225 | // |
||
226 | //Loop1: |
||
227 | // dec edx |
||
228 | // jl short doneit |
||
229 | // ror ecx, 1 |
||
230 | // rcl eax, 1 |
||
231 | // jmp short Loop1 |
||
232 | // |
||
233 | //doneit: |
||
234 | // }; |
||
235 | //} |
||
236 | |||
237 | #endif |
||
238 | |||
239 | // Flush the current output buffer. w :: Value to flush. bytes :: Number of |
||
240 | // bytes to flush (0, 1 or 2). |
||
241 | void __fastcall ZipDflt::flush_outbuf(unsigned w, unsigned bytes) |
||
242 | { |
||
243 | // Encrypt and write the output buffer: |
||
244 | if (fout_offset != 0) |
||
245 | { |
||
246 | if (!zfwrite(f_outbuf, (::extent) fout_offset)) |
||
247 | { |
||
248 | diag(_T("Write error in flush_outbuf")); |
||
249 | // FatalError(ZEN_WRITE01); |
||
250 | throw DZException(DZ_ERM_ERROR_WRITE); |
||
251 | } |
||
252 | } |
||
253 | |||
254 | fout_offset = 0; |
||
255 | |||
256 | if (bytes == 2) |
||
257 | { |
||
258 | // PUTSHORT(w); /* |
||
259 | if (fout_offset < sizeof(f_outbuf) - 1)//fout_size - 1) |
||
260 | { |
||
261 | *(ush *)(f_outbuf + fout_offset) = (ush) w; |
||
262 | // f_outbuf[fout_offset] = (ush) w; |
||
263 | fout_offset += 2; |
||
264 | } |
||
265 | else |
||
266 | { |
||
267 | flush_outbuf((w), 2); |
||
268 | } |
||
269 | } |
||
270 | else |
||
271 | if (bytes == 1) |
||
272 | f_outbuf[fout_offset++] = (char)(w & 0xFF); |
||
273 | } |
||
274 | |||
275 | // Write out any remaining bits in an incomplete byte. |
||
276 | void __fastcall ZipDflt::bi_windup(void) |
||
277 | { |
||
278 | if (fbi_valid > 8) |
||
279 | { |
||
280 | if (fout_offset < sizeof(f_outbuf) - 1)//fout_size - 1) |
||
281 | { |
||
282 | *(ush *)(f_outbuf + fout_offset) = (ush) fbi_buf; |
||
283 | // f_outbuf[fout_offset] = (ush) fbi_buf; |
||
284 | fout_offset += 2; |
||
285 | } |
||
286 | else |
||
287 | { |
||
288 | flush_outbuf((fbi_buf), 2); |
||
289 | } |
||
290 | } |
||
291 | else |
||
292 | if (fbi_valid > 0) |
||
293 | { |
||
294 | PUTBYTE(fbi_buf); |
||
295 | } |
||
296 | |||
297 | if (fZipOutfile->IsOpen()) |
||
298 | flush_outbuf(0, 0); |
||
299 | |||
300 | fbi_buf = 0; |
||
301 | fbi_valid = 0; |
||
302 | #ifdef DEBUG |
||
303 | fbits_sent = (fbits_sent + 7) & ~7; |
||
304 | #endif |
||
305 | } |
||
306 | |||
307 | // Copy a stored block to the zip file, storing first the length and its |
||
308 | // one's complement if requested. block :: The input data. len :: Its length. |
||
309 | // header :: True if block header must be written. |
||
310 | void __fastcall ZipDflt::copy_block(const uch *block, unsigned len, int header) |
||
311 | { |
||
312 | bi_windup(); // align on byte boundary |
||
313 | |||
314 | if (header) |
||
315 | { |
||
316 | if (fout_offset < sizeof(f_outbuf) -1)// fout_size - 1) |
||
317 | { |
||
318 | *(ush *)(f_outbuf + fout_offset) = (ush) len; |
||
319 | fout_offset += 2; |
||
320 | } |
||
321 | else |
||
322 | { |
||
323 | flush_outbuf((len), 2); |
||
324 | } |
||
325 | |||
326 | // PUTSHORT((ush)~len); |
||
327 | if (fout_offset < sizeof(f_outbuf) -1)// fout_size - 1) |
||
328 | { |
||
329 | *(ush *)(f_outbuf + fout_offset) = (ush)~len; |
||
330 | fout_offset += 2; |
||
331 | } |
||
332 | else |
||
333 | { |
||
334 | flush_outbuf((~len), 2); |
||
335 | } |
||
336 | |||
337 | #ifdef DEBUG |
||
338 | fbits_sent += 2 * 16; |
||
339 | #endif |
||
340 | } |
||
341 | |||
342 | // if (fzfile) |
||
343 | // if (fhOutz != INVALID_HANDLE_VALUE) |
||
344 | if (fZipOutfile) |
||
345 | { |
||
346 | flush_outbuf(0, 0); |
||
347 | |||
348 | if (!zfwrite(block, len)) |
||
349 | throw DZException(DZ_ERM_ERROR_WRITE); |
||
350 | |||
351 | // FatalError(ZEN_WRITE02); |
||
352 | } |
||
353 | else |
||
354 | { |
||
355 | if (fout_offset + len > sizeof(f_outbuf))//fout_size) |
||
356 | throw DZException(DZ_ERM_LOGIC_ERROR); |
||
357 | |||
358 | // FatalError(ZEN_LOGIC01); |
||
359 | // else |
||
360 | // { |
||
361 | memcpy(f_outbuf + fout_offset, block, len); |
||
362 | fout_offset += len; |
||
363 | |||
364 | } |
||
365 | |||
366 | #ifdef DEBUG |
||
367 | fbits_sent += (ulg) len << 3; |
||
368 | #endif |
||
369 | } |
||
370 | |||
371 | //// Return true if the zip file can be seeked. This is used to check if the |
||
372 | //// local header can be re-rewritten. This function always returns true for |
||
373 | //// in-memory compression. IN assertion: the local header has already been |
||
374 | //// written (ftell() > 0). |
||
375 | //int ZipDflt::seekable(void) |
||
376 | //{ |
||
377 | // return fZipOutfile->IsSeekable; |
||
378 | //} |
||
379 | |||
380 | |||
381 | //#ifdef USING_MEM_STRMS |
||
382 | //// In-memory compression. This version can be used only if the entire input |
||
383 | //// fits in one memory buffer. The compression is then done in a single call |
||
384 | //// of memcompress(). (An extension to allow repeated calls would be possible |
||
385 | //// but is not needed here.) The first two bytes of the compressed output are |
||
386 | //// set to a short with the method used (DEFLATE or STORE). The following four |
||
387 | //// bytes contain the CRC. The values are stored in little-endian order on all |
||
388 | //// machines. This function returns the byte size of the compressed output, |
||
389 | //// including the first six bytes (method and crc). tgt, *src :: Target and |
||
390 | //// source buffers. tgtsize, srcsize :: Target and source sizes. |
||
391 | //ulg ZipDflt::memcompress(char *tgt, ulg tgtsize, char *src, ulg srcsize) |
||
392 | //{ |
||
393 | // ush att = (ush) UNKNOWN; |
||
394 | // ush flags = 0; |
||
395 | // ulg crc; // RCV Removed ...= 0; |
||
396 | // int method = DEFLATE; |
||
397 | // |
||
398 | // if (tgtsize <= 6L) |
||
399 | // throw DZException(DZ_ERM_ERROR_LOGIC); |
||
400 | // |
||
401 | //// FatalError(ZEN_LOGIC02); |
||
402 | // |
||
403 | // crc = crc32(0L, (uch *)NULL, 0); |
||
404 | // crc = crc32(crc, (uch *)src, (extent) srcsize); |
||
405 | // |
||
406 | //// fread_buf = &ZipDflt::mem_read; |
||
407 | // ReadingFile = 0; |
||
408 | // fin_buf = src; |
||
409 | // fin_size = (unsigned)srcsize; |
||
410 | // fin_offset = 0; |
||
411 | // fout_buf = tgt; |
||
412 | // fout_size = (unsigned)tgtsize; |
||
413 | // fout_offset = 2 + 4; |
||
414 | // fwindow_size = 0L; |
||
415 | // if (fZipOutfile) |
||
416 | // { |
||
417 | // delete fZipOutfile; |
||
418 | // fZipOutfile = NULL; |
||
419 | // } |
||
420 | // |
||
421 | //// if (fhOutz != INVALID_HANDLE_VALUE) |
||
422 | //// Close_Handle(&fhOutz); // should not happen but... |
||
423 | // bi_init(); //NULL); |
||
424 | // ct_init(&att, &method); |
||
425 | // lm_init((flevel != 0 ? flevel : 1), &flags); |
||
426 | // deflate(); |
||
427 | // fwindow_size = 0L; // was updated by lm_init() |
||
428 | // // For portability, force little-endian order on all machines: |
||
429 | // tgt[0] = (char)(method & 0xFF); |
||
430 | // tgt[1] = (char)((method >> 8) & 0xFF); |
||
431 | // tgt[2] = (char)(crc & 0xFF); |
||
432 | // tgt[3] = (char)((crc >> 8) & 0xFF); |
||
433 | // tgt[4] = (char)((crc >> 16) & 0xFF); |
||
434 | // tgt[5] = (char)((crc >> 24) & 0xFF); |
||
435 | // |
||
436 | // return (ulg) fout_offset; |
||
437 | //} |
||
438 | // |
||
439 | //// In-memory read function. As opposed to file_read(), this function does |
||
440 | //// not perform end-of-line translation, and does not update the crc and input |
||
441 | //// size. Note that the size of the entire input buffer is an unsigned long, |
||
442 | //// but the size used in mem_read() is only an unsigned int. This makes a |
||
443 | //// difference on 16 bit machines. mem_read() may be called several times for |
||
444 | //// an in-memory compression. |
||
445 | //int ZipDflt::mem_read(unsigned char *b, unsigned bsize) |
||
446 | //{ |
||
447 | // if (fin_offset < fin_size) |
||
448 | // { |
||
449 | // ulg block_size = fin_size - fin_offset; |
||
450 | // |
||
451 | // if (block_size > (ulg) bsize) |
||
452 | // block_size = (ulg) bsize; |
||
453 | // |
||
454 | // memcpy(b, fin_buf + fin_offset, (unsigned)block_size); |
||
455 | // fin_offset += (unsigned)block_size; |
||
456 | // return (int)block_size; |
||
457 | // } |
||
458 | // |
||
459 | // return 0; // end of input |
||
460 | //} |
||
461 | // |
||
462 | //#endif |
||
463 | |||
464 | |||
465 | |||
466 |