DEADSOFTWARE

hopefully no more windows
[d2df-editor.git] / src / lib / vampimg / ZLib / imzinflate.pas
1 Unit imzinflate;
3 { inflate.c -- zlib interface to inflate modules
4 Copyright (C) 1995-1998 Mark Adler
6 Pascal tranlastion
7 Copyright (C) 1998 by Jacques Nomssi Nzali
8 For conditions of distribution and use, see copyright notice in readme.txt
9 }
11 interface
13 {$I imzconf.inc}
15 uses
16 imzutil, impaszlib, iminfblock, iminfutil;
18 function inflateInit(var z : z_stream) : int;
20 { Initializes the internal stream state for decompression. The fields
21 zalloc, zfree and opaque must be initialized before by the caller. If
22 zalloc and zfree are set to Z_NULL, inflateInit updates them to use default
23 allocation functions.
25 inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
26 enough memory, Z_VERSION_ERROR if the zlib library version is incompatible
27 with the version assumed by the caller. msg is set to null if there is no
28 error message. inflateInit does not perform any decompression: this will be
29 done by inflate(). }
33 function inflateInit_(z : z_streamp;
34 const version : AnsiString;
35 stream_size : int) : int;
38 function inflateInit2_(var z: z_stream;
39 w : int;
40 const version : AnsiString;
41 stream_size : int) : int;
43 function inflateInit2(var z: z_stream;
44 windowBits : int) : int;
46 {
47 This is another version of inflateInit with an extra parameter. The
48 fields next_in, avail_in, zalloc, zfree and opaque must be initialized
49 before by the caller.
51 The windowBits parameter is the base two logarithm of the maximum window
52 size (the size of the history buffer). It should be in the range 8..15 for
53 this version of the library. The default value is 15 if inflateInit is used
54 instead. If a compressed stream with a larger window size is given as
55 input, inflate() will return with the error code Z_DATA_ERROR instead of
56 trying to allocate a larger window.
58 inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
59 memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
60 memLevel). msg is set to null if there is no error message. inflateInit2
61 does not perform any decompression apart from reading the zlib header if
62 present: this will be done by inflate(). (So next_in and avail_in may be
63 modified, but next_out and avail_out are unchanged.)
64 }
68 function inflateEnd(var z : z_stream) : int;
70 {
71 All dynamically allocated data structures for this stream are freed.
72 This function discards any unprocessed input and does not flush any
73 pending output.
75 inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
76 was inconsistent. In the error case, msg may be set but then points to a
77 static string (which must not be deallocated).
78 }
80 function inflateReset(var z : z_stream) : int;
82 {
83 This function is equivalent to inflateEnd followed by inflateInit,
84 but does not free and reallocate all the internal decompression state.
85 The stream will keep attributes that may have been set by inflateInit2.
87 inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
88 stream state was inconsistent (such as zalloc or state being NULL).
89 }
92 function inflate(var z : z_stream;
93 f : int) : int;
94 {
95 inflate decompresses as much data as possible, and stops when the input
96 buffer becomes empty or the output buffer becomes full. It may introduce
97 some output latency (reading input without producing any output)
98 except when forced to flush.
100 The detailed semantics are as follows. inflate performs one or both of the
101 following actions:
103 - Decompress more input starting at next_in and update next_in and avail_in
104 accordingly. If not all input can be processed (because there is not
105 enough room in the output buffer), next_in is updated and processing
106 will resume at this point for the next call of inflate().
108 - Provide more output starting at next_out and update next_out and avail_out
109 accordingly. inflate() provides as much output as possible, until there
110 is no more input data or no more space in the output buffer (see below
111 about the flush parameter).
113 Before the call of inflate(), the application should ensure that at least
114 one of the actions is possible, by providing more input and/or consuming
115 more output, and updating the next_* and avail_* values accordingly.
116 The application can consume the uncompressed output when it wants, for
117 example when the output buffer is full (avail_out == 0), or after each
118 call of inflate(). If inflate returns Z_OK and with zero avail_out, it
119 must be called again after making room in the output buffer because there
120 might be more output pending.
122 If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
123 output as possible to the output buffer. The flushing behavior of inflate is
124 not specified for values of the flush parameter other than Z_SYNC_FLUSH
125 and Z_FINISH, but the current implementation actually flushes as much output
126 as possible anyway.
128 inflate() should normally be called until it returns Z_STREAM_END or an
129 error. However if all decompression is to be performed in a single step
130 (a single call of inflate), the parameter flush should be set to
131 Z_FINISH. In this case all pending input is processed and all pending
132 output is flushed; avail_out must be large enough to hold all the
133 uncompressed data. (The size of the uncompressed data may have been saved
134 by the compressor for this purpose.) The next operation on this stream must
135 be inflateEnd to deallocate the decompression state. The use of Z_FINISH
136 is never required, but can be used to inform inflate that a faster routine
137 may be used for the single inflate() call.
139 If a preset dictionary is needed at this point (see inflateSetDictionary
140 below), inflate sets strm-adler to the adler32 checksum of the
141 dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise
142 it sets strm->adler to the adler32 checksum of all output produced
143 so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
144 an error code as described below. At the end of the stream, inflate()
145 checks that its computed adler32 checksum is equal to that saved by the
146 compressor and returns Z_STREAM_END only if the checksum is correct.
148 inflate() returns Z_OK if some progress has been made (more input processed
149 or more output produced), Z_STREAM_END if the end of the compressed data has
150 been reached and all uncompressed output has been produced, Z_NEED_DICT if a
151 preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
152 corrupted (input stream not conforming to the zlib format or incorrect
153 adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
154 (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
155 enough memory, Z_BUF_ERROR if no progress is possible or if there was not
156 enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
157 case, the application may then call inflateSync to look for a good
158 compression block.
162 function inflateSetDictionary(var z : z_stream;
163 dictionary : pBytef; {const array of byte}
164 dictLength : uInt) : int;
167 Initializes the decompression dictionary from the given uncompressed byte
168 sequence. This function must be called immediately after a call of inflate
169 if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
170 can be determined from the Adler32 value returned by this call of
171 inflate. The compressor and decompressor must use exactly the same
172 dictionary (see deflateSetDictionary).
174 inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
175 parameter is invalid (such as NULL dictionary) or the stream state is
176 inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
177 expected one (incorrect Adler32 value). inflateSetDictionary does not
178 perform any decompression: this will be done by subsequent calls of
179 inflate().
182 function inflateSync(var z : z_stream) : int;
185 Skips invalid compressed data until a full flush point (see above the
186 description of deflate with Z_FULL_FLUSH) can be found, or until all
187 available input is skipped. No output is provided.
189 inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
190 if no more input was provided, Z_DATA_ERROR if no flush point has been found,
191 or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
192 case, the application may save the current current value of total_in which
193 indicates where valid compressed data was found. In the error case, the
194 application may repeatedly call inflateSync, providing more input each time,
195 until success or end of the input data.
199 function inflateSyncPoint(var z : z_stream) : int;
202 implementation
204 uses
205 imadler;
207 function inflateReset(var z : z_stream) : int;
208 begin
209 if (z.state = Z_NULL) then
210 begin
211 inflateReset := Z_STREAM_ERROR;
212 exit;
213 end;
214 z.total_out := 0;
215 z.total_in := 0;
216 z.msg := '';
217 if z.state^.nowrap then
218 z.state^.mode := BLOCKS
219 else
220 z.state^.mode := METHOD;
221 inflate_blocks_reset(z.state^.blocks^, z, Z_NULL);
222 {$IFDEF DEBUG}
223 Tracev('inflate: reset');
224 {$ENDIF}
225 inflateReset := Z_OK;
226 end;
229 function inflateEnd(var z : z_stream) : int;
230 begin
231 if (z.state = Z_NULL) or not Assigned(z.zfree) then
232 begin
233 inflateEnd := Z_STREAM_ERROR;
234 exit;
235 end;
236 if (z.state^.blocks <> Z_NULL) then
237 inflate_blocks_free(z.state^.blocks, z);
238 ZFREE(z, z.state);
239 z.state := Z_NULL;
240 {$IFDEF DEBUG}
241 Tracev('inflate: end');
242 {$ENDIF}
243 inflateEnd := Z_OK;
244 end;
247 function inflateInit2_(var z: z_stream;
248 w : int;
249 const version : AnsiString;
250 stream_size : int) : int;
251 begin
252 if (version = '') or (version[1] <> ZLIB_VERSION[1]) or
253 (stream_size <> sizeof(z_stream)) then
254 begin
255 inflateInit2_ := Z_VERSION_ERROR;
256 exit;
257 end;
258 { initialize state }
259 { SetLength(strm.msg, 255); }
260 z.msg := '';
261 if not Assigned(z.zalloc) then
262 begin
263 {$IFDEF FPC} z.zalloc := @zcalloc; {$ELSE}
264 z.zalloc := zcalloc;
265 {$endif}
266 z.opaque := voidpf(0);
267 end;
268 if not Assigned(z.zfree) then
269 {$IFDEF FPC} z.zfree := @zcfree; {$ELSE}
270 z.zfree := zcfree;
271 {$ENDIF}
273 z.state := pInternal_state( ZALLOC(z,1,sizeof(internal_state)) );
274 if (z.state = Z_NULL) then
275 begin
276 inflateInit2_ := Z_MEM_ERROR;
277 exit;
278 end;
280 z.state^.blocks := Z_NULL;
282 { handle undocumented nowrap option (no zlib header or check) }
283 z.state^.nowrap := FALSE;
284 if (w < 0) then
285 begin
286 w := - w;
287 z.state^.nowrap := TRUE;
288 end;
290 { set window size }
291 if (w < 8) or (w > 15) then
292 begin
293 inflateEnd(z);
294 inflateInit2_ := Z_STREAM_ERROR;
295 exit;
296 end;
297 z.state^.wbits := uInt(w);
299 { create inflate_blocks state }
300 if z.state^.nowrap then
301 z.state^.blocks := inflate_blocks_new(z, NIL, uInt(1) shl w)
302 else
303 {$IFDEF FPC}
304 z.state^.blocks := inflate_blocks_new(z, @adler32, uInt(1) shl w);
305 {$ELSE}
306 z.state^.blocks := inflate_blocks_new(z, adler32, uInt(1) shl w);
307 {$ENDIF}
308 if (z.state^.blocks = Z_NULL) then
309 begin
310 inflateEnd(z);
311 inflateInit2_ := Z_MEM_ERROR;
312 exit;
313 end;
314 {$IFDEF DEBUG}
315 Tracev('inflate: allocated');
316 {$ENDIF}
317 { reset state }
318 inflateReset(z);
319 inflateInit2_ := Z_OK;
320 end;
322 function inflateInit2(var z: z_stream; windowBits : int) : int;
323 begin
324 inflateInit2 := inflateInit2_(z, windowBits, ZLIB_VERSION, sizeof(z_stream));
325 end;
328 function inflateInit(var z : z_stream) : int;
329 { inflateInit is a macro to allow checking the zlib version
330 and the compiler's view of z_stream: }
331 begin
332 inflateInit := inflateInit2_(z, DEF_WBITS, ZLIB_VERSION, sizeof(z_stream));
333 end;
335 function inflateInit_(z : z_streamp;
336 const version : AnsiString;
337 stream_size : int) : int;
338 begin
339 { initialize state }
340 if (z = Z_NULL) then
341 inflateInit_ := Z_STREAM_ERROR
342 else
343 inflateInit_ := inflateInit2_(z^, DEF_WBITS, version, stream_size);
344 end;
346 function inflate(var z : z_stream;
347 f : int) : int;
348 var
349 r : int;
350 b : uInt;
351 begin
352 if (z.state = Z_NULL) or (z.next_in = Z_NULL) then
353 begin
354 inflate := Z_STREAM_ERROR;
355 exit;
356 end;
357 if f = Z_FINISH then
358 f := Z_BUF_ERROR
359 else
360 f := Z_OK;
361 r := Z_BUF_ERROR;
362 while True do
363 case (z.state^.mode) of
364 BLOCKS:
365 begin
366 r := inflate_blocks(z.state^.blocks^, z, r);
367 if (r = Z_DATA_ERROR) then
368 begin
369 z.state^.mode := BAD;
370 z.state^.sub.marker := 0; { can try inflateSync }
371 continue; { break C-switch }
372 end;
373 if (r = Z_OK) then
374 r := f;
375 if (r <> Z_STREAM_END) then
376 begin
377 inflate := r;
378 exit;
379 end;
380 r := f;
381 inflate_blocks_reset(z.state^.blocks^, z, @z.state^.sub.check.was);
382 if (z.state^.nowrap) then
383 begin
384 z.state^.mode := DONE;
385 continue; { break C-switch }
386 end;
387 z.state^.mode := CHECK4; { falltrough }
388 end;
389 CHECK4:
390 begin
391 {NEEDBYTE}
392 if (z.avail_in = 0) then
393 begin
394 inflate := r;
395 exit;
396 end;
397 r := f;
399 {z.state^.sub.check.need := uLong(NEXTBYTE(z)) shl 24;}
400 Dec(z.avail_in);
401 Inc(z.total_in);
402 z.state^.sub.check.need := uLong(z.next_in^) shl 24;
403 Inc(z.next_in);
405 z.state^.mode := CHECK3; { falltrough }
406 end;
407 CHECK3:
408 begin
409 {NEEDBYTE}
410 if (z.avail_in = 0) then
411 begin
412 inflate := r;
413 exit;
414 end;
415 r := f;
416 {Inc( z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 16);}
417 Dec(z.avail_in);
418 Inc(z.total_in);
419 Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 16);
420 Inc(z.next_in);
422 z.state^.mode := CHECK2; { falltrough }
423 end;
424 CHECK2:
425 begin
426 {NEEDBYTE}
427 if (z.avail_in = 0) then
428 begin
429 inflate := r;
430 exit;
431 end;
432 r := f;
434 {Inc( z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 8);}
435 Dec(z.avail_in);
436 Inc(z.total_in);
437 Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 8);
438 Inc(z.next_in);
440 z.state^.mode := CHECK1; { falltrough }
441 end;
442 CHECK1:
443 begin
444 {NEEDBYTE}
445 if (z.avail_in = 0) then
446 begin
447 inflate := r;
448 exit;
449 end;
450 r := f;
451 {Inc( z.state^.sub.check.need, uLong(NEXTBYTE(z)) );}
452 Dec(z.avail_in);
453 Inc(z.total_in);
454 Inc(z.state^.sub.check.need, uLong(z.next_in^) );
455 Inc(z.next_in);
458 if (z.state^.sub.check.was <> z.state^.sub.check.need) then
459 begin
460 z.state^.mode := BAD;
461 z.msg := 'incorrect data check';
462 z.state^.sub.marker := 5; { can't try inflateSync }
463 continue; { break C-switch }
464 end;
465 {$IFDEF DEBUG}
466 Tracev('inflate: zlib check ok');
467 {$ENDIF}
468 z.state^.mode := DONE; { falltrough }
469 end;
470 DONE:
471 begin
472 inflate := Z_STREAM_END;
473 exit;
474 end;
475 METHOD:
476 begin
477 {NEEDBYTE}
478 if (z.avail_in = 0) then
479 begin
480 inflate := r;
481 exit;
482 end;
483 r := f; {}
485 {z.state^.sub.method := NEXTBYTE(z);}
486 Dec(z.avail_in);
487 Inc(z.total_in);
488 z.state^.sub.method := z.next_in^;
489 Inc(z.next_in);
491 if ((z.state^.sub.method and $0f) <> Z_DEFLATED) then
492 begin
493 z.state^.mode := BAD;
494 z.msg := 'unknown compression method';
495 z.state^.sub.marker := 5; { can't try inflateSync }
496 continue; { break C-switch }
497 end;
498 if ((z.state^.sub.method shr 4) + 8 > z.state^.wbits) then
499 begin
500 z.state^.mode := BAD;
501 z.msg := 'invalid window size';
502 z.state^.sub.marker := 5; { can't try inflateSync }
503 continue; { break C-switch }
504 end;
505 z.state^.mode := FLAG;
506 { fall trough }
507 end;
508 FLAG:
509 begin
510 {NEEDBYTE}
511 if (z.avail_in = 0) then
512 begin
513 inflate := r;
514 exit;
515 end;
516 r := f; {}
517 {b := NEXTBYTE(z);}
518 Dec(z.avail_in);
519 Inc(z.total_in);
520 b := z.next_in^;
521 Inc(z.next_in);
523 if (((z.state^.sub.method shl 8) + b) mod 31) <> 0 then {% mod ?}
524 begin
525 z.state^.mode := BAD;
526 z.msg := 'incorrect header check';
527 z.state^.sub.marker := 5; { can't try inflateSync }
528 continue; { break C-switch }
529 end;
530 {$IFDEF DEBUG}
531 Tracev('inflate: zlib header ok');
532 {$ENDIF}
533 if ((b and PRESET_DICT) = 0) then
534 begin
535 z.state^.mode := BLOCKS;
536 continue; { break C-switch }
537 end;
538 z.state^.mode := DICT4;
539 { falltrough }
540 end;
541 DICT4:
542 begin
543 if (z.avail_in = 0) then
544 begin
545 inflate := r;
546 exit;
547 end;
548 r := f;
550 {z.state^.sub.check.need := uLong(NEXTBYTE(z)) shl 24;}
551 Dec(z.avail_in);
552 Inc(z.total_in);
553 z.state^.sub.check.need := uLong(z.next_in^) shl 24;
554 Inc(z.next_in);
556 z.state^.mode := DICT3; { falltrough }
557 end;
558 DICT3:
559 begin
560 if (z.avail_in = 0) then
561 begin
562 inflate := r;
563 exit;
564 end;
565 r := f;
566 {Inc(z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 16);}
567 Dec(z.avail_in);
568 Inc(z.total_in);
569 Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 16);
570 Inc(z.next_in);
572 z.state^.mode := DICT2; { falltrough }
573 end;
574 DICT2:
575 begin
576 if (z.avail_in = 0) then
577 begin
578 inflate := r;
579 exit;
580 end;
581 r := f;
583 {Inc(z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 8);}
584 Dec(z.avail_in);
585 Inc(z.total_in);
586 Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 8);
587 Inc(z.next_in);
589 z.state^.mode := DICT1; { falltrough }
590 end;
591 DICT1:
592 begin
593 if (z.avail_in = 0) then
594 begin
595 inflate := r;
596 exit;
597 end;
598 { r := f; --- wird niemals benutzt }
599 {Inc(z.state^.sub.check.need, uLong(NEXTBYTE(z)) );}
600 Dec(z.avail_in);
601 Inc(z.total_in);
602 Inc(z.state^.sub.check.need, uLong(z.next_in^) );
603 Inc(z.next_in);
605 z.adler := z.state^.sub.check.need;
606 z.state^.mode := DICT0;
607 inflate := Z_NEED_DICT;
608 exit;
609 end;
610 DICT0:
611 begin
612 z.state^.mode := BAD;
613 z.msg := 'need dictionary';
614 z.state^.sub.marker := 0; { can try inflateSync }
615 inflate := Z_STREAM_ERROR;
616 exit;
617 end;
618 BAD:
619 begin
620 inflate := Z_DATA_ERROR;
621 exit;
622 end;
623 else
624 begin
625 inflate := Z_STREAM_ERROR;
626 exit;
627 end;
628 end;
629 {$ifdef NEED_DUMMY_result}
630 result := Z_STREAM_ERROR; { Some dumb compilers complain without this }
631 {$endif}
632 end;
634 function inflateSetDictionary(var z : z_stream;
635 dictionary : pBytef; {const array of byte}
636 dictLength : uInt) : int;
637 var
638 length : uInt;
639 begin
640 length := dictLength;
642 if (z.state = Z_NULL) or (z.state^.mode <> DICT0) then
643 begin
644 inflateSetDictionary := Z_STREAM_ERROR;
645 exit;
646 end;
647 if (adler32(Long(1), dictionary, dictLength) <> z.adler) then
648 begin
649 inflateSetDictionary := Z_DATA_ERROR;
650 exit;
651 end;
652 z.adler := Long(1);
654 if (length >= (uInt(1) shl z.state^.wbits)) then
655 begin
656 length := (1 shl z.state^.wbits)-1;
657 Inc( dictionary, dictLength - length);
658 end;
659 inflate_set_dictionary(z.state^.blocks^, dictionary^, length);
660 z.state^.mode := BLOCKS;
661 inflateSetDictionary := Z_OK;
662 end;
665 function inflateSync(var z : z_stream) : int;
666 const
667 mark : packed array[0..3] of byte = (0, 0, $ff, $ff);
668 var
669 n : uInt; { number of bytes to look at }
670 p : pBytef; { pointer to bytes }
671 m : uInt; { number of marker bytes found in a row }
672 r, w : uLong; { temporaries to save total_in and total_out }
673 begin
674 { set up }
675 if (z.state = Z_NULL) then
676 begin
677 inflateSync := Z_STREAM_ERROR;
678 exit;
679 end;
680 if (z.state^.mode <> BAD) then
681 begin
682 z.state^.mode := BAD;
683 z.state^.sub.marker := 0;
684 end;
685 n := z.avail_in;
686 if (n = 0) then
687 begin
688 inflateSync := Z_BUF_ERROR;
689 exit;
690 end;
691 p := z.next_in;
692 m := z.state^.sub.marker;
694 { search }
695 while (n <> 0) and (m < 4) do
696 begin
697 if (p^ = mark[m]) then
698 Inc(m)
699 else
700 if (p^ <> 0) then
701 m := 0
702 else
703 m := 4 - m;
704 Inc(p);
705 Dec(n);
706 end;
708 { restore }
709 Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in));
710 z.next_in := p;
711 z.avail_in := n;
712 z.state^.sub.marker := m;
715 { return no joy or set up to restart on a new block }
716 if (m <> 4) then
717 begin
718 inflateSync := Z_DATA_ERROR;
719 exit;
720 end;
721 r := z.total_in;
722 w := z.total_out;
723 inflateReset(z);
724 z.total_in := r;
725 z.total_out := w;
726 z.state^.mode := BLOCKS;
727 inflateSync := Z_OK;
728 end;
732 returns true if inflate is currently at the end of a block generated
733 by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
734 implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
735 but removes the length bytes of the resulting empty stored block. When
736 decompressing, PPP checks that at the end of input packet, inflate is
737 waiting for these length bytes.
740 function inflateSyncPoint(var z : z_stream) : int;
741 begin
742 if (z.state = Z_NULL) or (z.state^.blocks = Z_NULL) then
743 begin
744 inflateSyncPoint := Z_STREAM_ERROR;
745 exit;
746 end;
747 inflateSyncPoint := inflate_blocks_sync_point(z.state^.blocks^);
748 end;
750 end.