1 (* example.c -- usage example of the zlib compression library
2 * Copyright (C) 1995-2003 Jean-loup Gailly.
3 * For conditions of distribution and use, see copyright notice in zlib.h
6 * Copyright (C) 1998 by Jacques Nomssi Nzali.
7 * For conditions of distribution and use, see copyright notice in readme.txt
9 * Adaptation to the zlibpas interface
10 * Copyright (C) 2003 by Cosmin Truta.
11 * For conditions of distribution and use, see copyright notice in readme.txt
16 {$DEFINE TEST_COMPRESS}
17 {DO NOT $DEFINE TEST_GZIO}
18 {$DEFINE TEST_DEFLATE}
19 {$DEFINE TEST_INFLATE}
24 uses SysUtils
, zlibpas
;
26 const TESTFILE
= 'foo.gz';
28 (* "hello world" would be more standard, but the repeated "hello"
29 * stresses the compression code better, sorry...
31 const hello
: PChar
= 'hello, hello!';
33 const dictionary
: PChar
= 'hello';
35 var dictId
: LongInt; (* Adler32 value of the dictionary *)
37 procedure CHECK_ERR(err
: Integer; msg
: String);
41 WriteLn(msg
, ' error: ', err
);
46 procedure EXIT_ERR(const msg
: String);
48 WriteLn('Error: ', msg
);
52 (* ===========================================================================
53 * Test compress and uncompress
55 {$IFDEF TEST_COMPRESS}
56 procedure test_compress(compr
: Pointer; comprLen
: LongInt;
57 uncompr
: Pointer; uncomprLen
: LongInt);
61 len
:= StrLen(hello
)+1;
63 err
:= compress(compr
, comprLen
, hello
, len
);
64 CHECK_ERR(err
, 'compress');
66 StrCopy(PChar(uncompr
), 'garbage');
68 err
:= uncompress(uncompr
, uncomprLen
, compr
, comprLen
);
69 CHECK_ERR(err
, 'uncompress');
71 if StrComp(PChar(uncompr
), hello
) <> 0 then
72 EXIT_ERR('bad uncompress')
74 WriteLn('uncompress(): ', PChar(uncompr
));
78 (* ===========================================================================
79 * Test read/write of .gz files
82 procedure test_gzio(const fname
: PChar
; (* compressed file name *)
90 len
:= StrLen(hello
)+1;
92 zfile
:= gzopen(fname
, 'wb');
95 WriteLn('gzopen error');
99 if gzputs(zfile
, 'ello') <> 4 then
101 WriteLn('gzputs err: ', gzerror(zfile
, err
));
104 {$IFDEF GZ_FORMAT_STRING}
105 if gzprintf(zfile
, ', %s!', 'hello') <> 8 then
107 WriteLn('gzprintf err: ', gzerror(zfile
, err
));
111 if gzputs(zfile
, ', hello!') <> 8 then
113 WriteLn('gzputs err: ', gzerror(zfile
, err
));
117 gzseek(zfile
, 1, SEEK_CUR
); (* add one zero byte *)
120 zfile
:= gzopen(fname
, 'rb');
123 WriteLn('gzopen error');
127 StrCopy(PChar(uncompr
), 'garbage');
129 if gzread(zfile
, uncompr
, uncomprLen
) <> len
then
131 WriteLn('gzread err: ', gzerror(zfile
, err
));
134 if StrComp(PChar(uncompr
), hello
) <> 0 then
136 WriteLn('bad gzread: ', PChar(uncompr
));
140 WriteLn('gzread(): ', PChar(uncompr
));
142 pos
:= gzseek(zfile
, -8, SEEK_CUR
);
143 if (pos
<> 6) or (gztell(zfile
) <> pos
) then
145 WriteLn('gzseek error, pos=', pos
, ', gztell=', gztell(zfile
));
149 if gzgetc(zfile
) <> ' ' then
151 WriteLn('gzgetc error');
155 if gzungetc(' ', zfile
) <> ' ' then
157 WriteLn('gzungetc error');
161 gzgets(zfile
, PChar(uncompr
), uncomprLen
);
162 uncomprLen
:= StrLen(PChar(uncompr
));
163 if uncomprLen
<> 7 then (* " hello!" *)
165 WriteLn('gzgets err after gzseek: ', gzerror(zfile
, err
));
168 if StrComp(PChar(uncompr
), hello
+ 6) <> 0 then
170 WriteLn('bad gzgets after gzseek');
174 WriteLn('gzgets() after gzseek: ', PChar(uncompr
));
180 (* ===========================================================================
181 * Test deflate with small buffers
183 {$IFDEF TEST_DEFLATE}
184 procedure test_deflate(compr
: Pointer; comprLen
: LongInt);
185 var c_stream
: z_stream
; (* compression stream *)
189 len
:= StrLen(hello
)+1;
191 c_stream
.zalloc
:= NIL;
192 c_stream
.zfree
:= NIL;
193 c_stream
.opaque
:= NIL;
195 err
:= deflateInit(c_stream
, Z_DEFAULT_COMPRESSION
);
196 CHECK_ERR(err
, 'deflateInit');
198 c_stream
.next_in
:= hello
;
199 c_stream
.next_out
:= compr
;
201 while (c_stream
.total_in
<> len
) and
202 (c_stream
.total_out
< comprLen
) do
204 c_stream
.avail_out
:= 1; { force small buffers }
205 c_stream
.avail_in
:= 1;
206 err
:= deflate(c_stream
, Z_NO_FLUSH
);
207 CHECK_ERR(err
, 'deflate');
210 (* Finish the stream, still forcing small buffers: *)
213 c_stream
.avail_out
:= 1;
214 err
:= deflate(c_stream
, Z_FINISH
);
215 if err
= Z_STREAM_END
then
217 CHECK_ERR(err
, 'deflate');
220 err
:= deflateEnd(c_stream
);
221 CHECK_ERR(err
, 'deflateEnd');
225 (* ===========================================================================
226 * Test inflate with small buffers
228 {$IFDEF TEST_INFLATE}
229 procedure test_inflate(compr
: Pointer; comprLen
: LongInt;
230 uncompr
: Pointer; uncomprLen
: LongInt);
232 d_stream
: z_stream
; (* decompression stream *)
234 StrCopy(PChar(uncompr
), 'garbage');
236 d_stream
.zalloc
:= NIL;
237 d_stream
.zfree
:= NIL;
238 d_stream
.opaque
:= NIL;
240 d_stream
.next_in
:= compr
;
241 d_stream
.avail_in
:= 0;
242 d_stream
.next_out
:= uncompr
;
244 err
:= inflateInit(d_stream
);
245 CHECK_ERR(err
, 'inflateInit');
247 while (d_stream
.total_out
< uncomprLen
) and
248 (d_stream
.total_in
< comprLen
) do
250 d_stream
.avail_out
:= 1; (* force small buffers *)
251 d_stream
.avail_in
:= 1;
252 err
:= inflate(d_stream
, Z_NO_FLUSH
);
253 if err
= Z_STREAM_END
then
255 CHECK_ERR(err
, 'inflate');
258 err
:= inflateEnd(d_stream
);
259 CHECK_ERR(err
, 'inflateEnd');
261 if StrComp(PChar(uncompr
), hello
) <> 0 then
262 EXIT_ERR('bad inflate')
264 WriteLn('inflate(): ', PChar(uncompr
));
268 (* ===========================================================================
269 * Test deflate with large buffers and dynamic change of compression level
271 {$IFDEF TEST_DEFLATE}
272 procedure test_large_deflate(compr
: Pointer; comprLen
: LongInt;
273 uncompr
: Pointer; uncomprLen
: LongInt);
274 var c_stream
: z_stream
; (* compression stream *)
277 c_stream
.zalloc
:= NIL;
278 c_stream
.zfree
:= NIL;
279 c_stream
.opaque
:= NIL;
281 err
:= deflateInit(c_stream
, Z_BEST_SPEED
);
282 CHECK_ERR(err
, 'deflateInit');
284 c_stream
.next_out
:= compr
;
285 c_stream
.avail_out
:= Integer(comprLen
);
287 (* At this point, uncompr is still mostly zeroes, so it should compress
290 c_stream
.next_in
:= uncompr
;
291 c_stream
.avail_in
:= Integer(uncomprLen
);
292 err
:= deflate(c_stream
, Z_NO_FLUSH
);
293 CHECK_ERR(err
, 'deflate');
294 if c_stream
.avail_in
<> 0 then
295 EXIT_ERR('deflate not greedy');
297 (* Feed in already compressed data and switch to no compression: *)
298 deflateParams(c_stream
, Z_NO_COMPRESSION
, Z_DEFAULT_STRATEGY
);
299 c_stream
.next_in
:= compr
;
300 c_stream
.avail_in
:= Integer(comprLen
div 2);
301 err
:= deflate(c_stream
, Z_NO_FLUSH
);
302 CHECK_ERR(err
, 'deflate');
304 (* Switch back to compressing mode: *)
305 deflateParams(c_stream
, Z_BEST_COMPRESSION
, Z_FILTERED
);
306 c_stream
.next_in
:= uncompr
;
307 c_stream
.avail_in
:= Integer(uncomprLen
);
308 err
:= deflate(c_stream
, Z_NO_FLUSH
);
309 CHECK_ERR(err
, 'deflate');
311 err
:= deflate(c_stream
, Z_FINISH
);
312 if err
<> Z_STREAM_END
then
313 EXIT_ERR('deflate should report Z_STREAM_END');
315 err
:= deflateEnd(c_stream
);
316 CHECK_ERR(err
, 'deflateEnd');
320 (* ===========================================================================
321 * Test inflate with large buffers
323 {$IFDEF TEST_INFLATE}
324 procedure test_large_inflate(compr
: Pointer; comprLen
: LongInt;
325 uncompr
: Pointer; uncomprLen
: LongInt);
327 d_stream
: z_stream
; (* decompression stream *)
329 StrCopy(PChar(uncompr
), 'garbage');
331 d_stream
.zalloc
:= NIL;
332 d_stream
.zfree
:= NIL;
333 d_stream
.opaque
:= NIL;
335 d_stream
.next_in
:= compr
;
336 d_stream
.avail_in
:= Integer(comprLen
);
338 err
:= inflateInit(d_stream
);
339 CHECK_ERR(err
, 'inflateInit');
343 d_stream
.next_out
:= uncompr
; (* discard the output *)
344 d_stream
.avail_out
:= Integer(uncomprLen
);
345 err
:= inflate(d_stream
, Z_NO_FLUSH
);
346 if err
= Z_STREAM_END
then
348 CHECK_ERR(err
, 'large inflate');
351 err
:= inflateEnd(d_stream
);
352 CHECK_ERR(err
, 'inflateEnd');
354 if d_stream
.total_out
<> 2 * uncomprLen
+ comprLen
div 2 then
356 WriteLn('bad large inflate: ', d_stream
.total_out
);
360 WriteLn('large_inflate(): OK');
364 (* ===========================================================================
365 * Test deflate with full flush
368 procedure test_flush(compr
: Pointer; var comprLen
: LongInt);
369 var c_stream
: z_stream
; (* compression stream *)
373 len
:= StrLen(hello
)+1;
375 c_stream
.zalloc
:= NIL;
376 c_stream
.zfree
:= NIL;
377 c_stream
.opaque
:= NIL;
379 err
:= deflateInit(c_stream
, Z_DEFAULT_COMPRESSION
);
380 CHECK_ERR(err
, 'deflateInit');
382 c_stream
.next_in
:= hello
;
383 c_stream
.next_out
:= compr
;
384 c_stream
.avail_in
:= 3;
385 c_stream
.avail_out
:= Integer(comprLen
);
386 err
:= deflate(c_stream
, Z_FULL_FLUSH
);
387 CHECK_ERR(err
, 'deflate');
389 Inc(PByteArray(compr
)^[3]); (* force an error in first compressed block *)
390 c_stream
.avail_in
:= len
- 3;
392 err
:= deflate(c_stream
, Z_FINISH
);
393 if err
<> Z_STREAM_END
then
394 CHECK_ERR(err
, 'deflate');
396 err
:= deflateEnd(c_stream
);
397 CHECK_ERR(err
, 'deflateEnd');
399 comprLen
:= c_stream
.total_out
;
403 (* ===========================================================================
407 procedure test_sync(compr
: Pointer; comprLen
: LongInt;
408 uncompr
: Pointer; uncomprLen
: LongInt);
410 d_stream
: z_stream
; (* decompression stream *)
412 StrCopy(PChar(uncompr
), 'garbage');
414 d_stream
.zalloc
:= NIL;
415 d_stream
.zfree
:= NIL;
416 d_stream
.opaque
:= NIL;
418 d_stream
.next_in
:= compr
;
419 d_stream
.avail_in
:= 2; (* just read the zlib header *)
421 err
:= inflateInit(d_stream
);
422 CHECK_ERR(err
, 'inflateInit');
424 d_stream
.next_out
:= uncompr
;
425 d_stream
.avail_out
:= Integer(uncomprLen
);
427 inflate(d_stream
, Z_NO_FLUSH
);
428 CHECK_ERR(err
, 'inflate');
430 d_stream
.avail_in
:= Integer(comprLen
-2); (* read all compressed data *)
431 err
:= inflateSync(d_stream
); (* but skip the damaged part *)
432 CHECK_ERR(err
, 'inflateSync');
434 err
:= inflate(d_stream
, Z_FINISH
);
435 if err
<> Z_DATA_ERROR
then
436 EXIT_ERR('inflate should report DATA_ERROR');
437 (* Because of incorrect adler32 *)
439 err
:= inflateEnd(d_stream
);
440 CHECK_ERR(err
, 'inflateEnd');
442 WriteLn('after inflateSync(): hel', PChar(uncompr
));
446 (* ===========================================================================
447 * Test deflate with preset dictionary
450 procedure test_dict_deflate(compr
: Pointer; comprLen
: LongInt);
451 var c_stream
: z_stream
; (* compression stream *)
454 c_stream
.zalloc
:= NIL;
455 c_stream
.zfree
:= NIL;
456 c_stream
.opaque
:= NIL;
458 err
:= deflateInit(c_stream
, Z_BEST_COMPRESSION
);
459 CHECK_ERR(err
, 'deflateInit');
461 err
:= deflateSetDictionary(c_stream
, dictionary
, StrLen(dictionary
));
462 CHECK_ERR(err
, 'deflateSetDictionary');
464 dictId
:= c_stream
.adler
;
465 c_stream
.next_out
:= compr
;
466 c_stream
.avail_out
:= Integer(comprLen
);
468 c_stream
.next_in
:= hello
;
469 c_stream
.avail_in
:= StrLen(hello
)+1;
471 err
:= deflate(c_stream
, Z_FINISH
);
472 if err
<> Z_STREAM_END
then
473 EXIT_ERR('deflate should report Z_STREAM_END');
475 err
:= deflateEnd(c_stream
);
476 CHECK_ERR(err
, 'deflateEnd');
480 (* ===========================================================================
481 * Test inflate with a preset dictionary
484 procedure test_dict_inflate(compr
: Pointer; comprLen
: LongInt;
485 uncompr
: Pointer; uncomprLen
: LongInt);
487 d_stream
: z_stream
; (* decompression stream *)
489 StrCopy(PChar(uncompr
), 'garbage');
491 d_stream
.zalloc
:= NIL;
492 d_stream
.zfree
:= NIL;
493 d_stream
.opaque
:= NIL;
495 d_stream
.next_in
:= compr
;
496 d_stream
.avail_in
:= Integer(comprLen
);
498 err
:= inflateInit(d_stream
);
499 CHECK_ERR(err
, 'inflateInit');
501 d_stream
.next_out
:= uncompr
;
502 d_stream
.avail_out
:= Integer(uncomprLen
);
506 err
:= inflate(d_stream
, Z_NO_FLUSH
);
507 if err
= Z_STREAM_END
then
509 if err
= Z_NEED_DICT
then
511 if d_stream
.adler
<> dictId
then
512 EXIT_ERR('unexpected dictionary');
513 err
:= inflateSetDictionary(d_stream
, dictionary
, StrLen(dictionary
));
515 CHECK_ERR(err
, 'inflate with dict');
518 err
:= inflateEnd(d_stream
);
519 CHECK_ERR(err
, 'inflateEnd');
521 if StrComp(PChar(uncompr
), hello
) <> 0 then
522 EXIT_ERR('bad inflate with dict')
524 WriteLn('inflate with dictionary: ', PChar(uncompr
));
528 var compr
, uncompr
: Pointer;
529 comprLen
, uncomprLen
: LongInt;
532 if zlibVersion
^ <> ZLIB_VERSION
[1] then
533 EXIT_ERR('Incompatible zlib version');
535 WriteLn('zlib version: ', zlibVersion
);
536 WriteLn('zlib compile flags: ', Format('0x%x', [zlibCompileFlags
]));
538 comprLen
:= 10000 * SizeOf(Integer); (* don't overflow on MSDOS *)
539 uncomprLen
:= comprLen
;
540 GetMem(compr
, comprLen
);
541 GetMem(uncompr
, uncomprLen
);
542 if (compr
= NIL) or (uncompr
= NIL) then
543 EXIT_ERR('Out of memory');
544 (* compr and uncompr are cleared to avoid reading uninitialized
545 * data and to ensure that uncompr compresses well.
547 FillChar(compr
^, comprLen
, 0);
548 FillChar(uncompr
^, uncomprLen
, 0);
550 {$IFDEF TEST_COMPRESS}
551 WriteLn('** Testing compress');
552 test_compress(compr
, comprLen
, uncompr
, uncomprLen
);
556 WriteLn('** Testing gzio');
557 if ParamCount
>= 1 then
558 test_gzio(ParamStr(1), uncompr
, uncomprLen
)
560 test_gzio(TESTFILE
, uncompr
, uncomprLen
);
563 {$IFDEF TEST_DEFLATE}
564 WriteLn('** Testing deflate with small buffers');
565 test_deflate(compr
, comprLen
);
567 {$IFDEF TEST_INFLATE}
568 WriteLn('** Testing inflate with small buffers');
569 test_inflate(compr
, comprLen
, uncompr
, uncomprLen
);
572 {$IFDEF TEST_DEFLATE}
573 WriteLn('** Testing deflate with large buffers');
574 test_large_deflate(compr
, comprLen
, uncompr
, uncomprLen
);
576 {$IFDEF TEST_INFLATE}
577 WriteLn('** Testing inflate with large buffers');
578 test_large_inflate(compr
, comprLen
, uncompr
, uncomprLen
);
582 WriteLn('** Testing deflate with full flush');
583 test_flush(compr
, comprLen
);
586 WriteLn('** Testing inflateSync');
587 test_sync(compr
, comprLen
, uncompr
, uncomprLen
);
589 comprLen
:= uncomprLen
;
592 WriteLn('** Testing deflate and inflate with preset dictionary');
593 test_dict_deflate(compr
, comprLen
);
594 test_dict_inflate(compr
, comprLen
, uncompr
, uncomprLen
);
597 FreeMem(compr
, comprLen
);
598 FreeMem(uncompr
, uncomprLen
);