program example;
uses SysUtils, zlibpas;
const TESTFILE = 'foo.gz';
const hello: PChar = 'hello, hello!';
const dictionary: PChar = 'hello';
var dictId: LongInt;
procedure CHECK_ERR(err: Integer; msg: String);
begin
if err <> Z_OK then
begin
WriteLn(msg, ' error: ', err);
Halt(1);
end;
end;
procedure EXIT_ERR(const msg: String);
begin
WriteLn('Error: ', msg);
Halt(1);
end;
procedure test_compress(compr: Pointer; comprLen: LongInt;
uncompr: Pointer; uncomprLen: LongInt);
var err: Integer;
len: LongInt;
begin
len := StrLen(hello)+1;
err := compress(compr, comprLen, hello, len);
CHECK_ERR(err, 'compress');
StrCopy(PChar(uncompr), 'garbage');
err := uncompress(uncompr, uncomprLen, compr, comprLen);
CHECK_ERR(err, 'uncompress');
if StrComp(PChar(uncompr), hello) <> 0 then
EXIT_ERR('bad uncompress')
else
WriteLn('uncompress(): ', PChar(uncompr));
end;
procedure test_gzio(const fname: PChar;
uncompr: Pointer;
uncomprLen: LongInt);
var err: Integer;
len: Integer;
zfile: gzFile;
pos: LongInt;
begin
len := StrLen(hello)+1;
zfile := gzopen(fname, 'wb');
if zfile = NIL then
begin
WriteLn('gzopen error');
Halt(1);
end;
gzputc(zfile, 'h');
if gzputs(zfile, 'ello') <> 4 then
begin
WriteLn('gzputs err: ', gzerror(zfile, err));
Halt(1);
end;
if gzprintf(zfile, ', %s!', 'hello') <> 8 then
begin
WriteLn('gzprintf err: ', gzerror(zfile, err));
Halt(1);
end;
if gzputs(zfile, ', hello!') <> 8 then
begin
WriteLn('gzputs err: ', gzerror(zfile, err));
Halt(1);
end;
gzseek(zfile, 1, SEEK_CUR);
gzclose(zfile);
zfile := gzopen(fname, 'rb');
if zfile = NIL then
begin
WriteLn('gzopen error');
Halt(1);
end;
StrCopy(PChar(uncompr), 'garbage');
if gzread(zfile, uncompr, uncomprLen) <> len then
begin
WriteLn('gzread err: ', gzerror(zfile, err));
Halt(1);
end;
if StrComp(PChar(uncompr), hello) <> 0 then
begin
WriteLn('bad gzread: ', PChar(uncompr));
Halt(1);
end
else
WriteLn('gzread(): ', PChar(uncompr));
pos := gzseek(zfile, -8, SEEK_CUR);
if (pos <> 6) or (gztell(zfile) <> pos) then
begin
WriteLn('gzseek error, pos=', pos, ', gztell=', gztell(zfile));
Halt(1);
end;
if gzgetc(zfile) <> ' ' then
begin
WriteLn('gzgetc error');
Halt(1);
end;
if gzungetc(' ', zfile) <> ' ' then
begin
WriteLn('gzungetc error');
Halt(1);
end;
gzgets(zfile, PChar(uncompr), uncomprLen);
uncomprLen := StrLen(PChar(uncompr));
if uncomprLen <> 7 then
begin
WriteLn('gzgets err after gzseek: ', gzerror(zfile, err));
Halt(1);
end;
if StrComp(PChar(uncompr), hello + 6) <> 0 then
begin
WriteLn('bad gzgets after gzseek');
Halt(1);
end
else
WriteLn('gzgets() after gzseek: ', PChar(uncompr));
gzclose(zfile);
end;
procedure test_deflate(compr: Pointer; comprLen: LongInt);
var c_stream: z_stream;
err: Integer;
len: LongInt;
begin
len := StrLen(hello)+1;
c_stream.zalloc := NIL;
c_stream.zfree := NIL;
c_stream.opaque := NIL;
err := deflateInit(c_stream, Z_DEFAULT_COMPRESSION);
CHECK_ERR(err, 'deflateInit');
c_stream.next_in := hello;
c_stream.next_out := compr;
while (c_stream.total_in <> len) and
(c_stream.total_out < comprLen) do
begin
c_stream.avail_out := 1;
c_stream.avail_in := 1;
err := deflate(c_stream, Z_NO_FLUSH);
CHECK_ERR(err, 'deflate');
end;
while TRUE do
begin
c_stream.avail_out := 1;
err := deflate(c_stream, Z_FINISH);
if err = Z_STREAM_END then
break;
CHECK_ERR(err, 'deflate');
end;
err := deflateEnd(c_stream);
CHECK_ERR(err, 'deflateEnd');
end;
procedure test_inflate(compr: Pointer; comprLen : LongInt;
uncompr: Pointer; uncomprLen : LongInt);
var err: Integer;
d_stream: z_stream;
begin
StrCopy(PChar(uncompr), 'garbage');
d_stream.zalloc := NIL;
d_stream.zfree := NIL;
d_stream.opaque := NIL;
d_stream.next_in := compr;
d_stream.avail_in := 0;
d_stream.next_out := uncompr;
err := inflateInit(d_stream);
CHECK_ERR(err, 'inflateInit');
while (d_stream.total_out < uncomprLen) and
(d_stream.total_in < comprLen) do
begin
d_stream.avail_out := 1;
d_stream.avail_in := 1;
err := inflate(d_stream, Z_NO_FLUSH);
if err = Z_STREAM_END then
break;
CHECK_ERR(err, 'inflate');
end;
err := inflateEnd(d_stream);
CHECK_ERR(err, 'inflateEnd');
if StrComp(PChar(uncompr), hello) <> 0 then
EXIT_ERR('bad inflate')
else
WriteLn('inflate(): ', PChar(uncompr));
end;
procedure test_large_deflate(compr: Pointer; comprLen: LongInt;
uncompr: Pointer; uncomprLen: LongInt);
var c_stream: z_stream;
err: Integer;
begin
c_stream.zalloc := NIL;
c_stream.zfree := NIL;
c_stream.opaque := NIL;
err := deflateInit(c_stream, Z_BEST_SPEED);
CHECK_ERR(err, 'deflateInit');
c_stream.next_out := compr;
c_stream.avail_out := Integer(comprLen);
c_stream.next_in := uncompr;
c_stream.avail_in := Integer(uncomprLen);
err := deflate(c_stream, Z_NO_FLUSH);
CHECK_ERR(err, 'deflate');
if c_stream.avail_in <> 0 then
EXIT_ERR('deflate not greedy');
deflateParams(c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
c_stream.next_in := compr;
c_stream.avail_in := Integer(comprLen div 2);
err := deflate(c_stream, Z_NO_FLUSH);
CHECK_ERR(err, 'deflate');
deflateParams(c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
c_stream.next_in := uncompr;
c_stream.avail_in := Integer(uncomprLen);
err := deflate(c_stream, Z_NO_FLUSH);
CHECK_ERR(err, 'deflate');
err := deflate(c_stream, Z_FINISH);
if err <> Z_STREAM_END then
EXIT_ERR('deflate should report Z_STREAM_END');
err := deflateEnd(c_stream);
CHECK_ERR(err, 'deflateEnd');
end;
procedure test_large_inflate(compr: Pointer; comprLen: LongInt;
uncompr: Pointer; uncomprLen: LongInt);
var err: Integer;
d_stream: z_stream;
begin
StrCopy(PChar(uncompr), 'garbage');
d_stream.zalloc := NIL;
d_stream.zfree := NIL;
d_stream.opaque := NIL;
d_stream.next_in := compr;
d_stream.avail_in := Integer(comprLen);
err := inflateInit(d_stream);
CHECK_ERR(err, 'inflateInit');
while TRUE do
begin
d_stream.next_out := uncompr;
d_stream.avail_out := Integer(uncomprLen);
err := inflate(d_stream, Z_NO_FLUSH);
if err = Z_STREAM_END then
break;
CHECK_ERR(err, 'large inflate');
end;
err := inflateEnd(d_stream);
CHECK_ERR(err, 'inflateEnd');
if d_stream.total_out <> 2 * uncomprLen + comprLen div 2 then
begin
WriteLn('bad large inflate: ', d_stream.total_out);
Halt(1);
end
else
WriteLn('large_inflate(): OK');
end;
procedure test_flush(compr: Pointer; var comprLen : LongInt);
var c_stream: z_stream;
err: Integer;
len: Integer;
begin
len := StrLen(hello)+1;
c_stream.zalloc := NIL;
c_stream.zfree := NIL;
c_stream.opaque := NIL;
err := deflateInit(c_stream, Z_DEFAULT_COMPRESSION);
CHECK_ERR(err, 'deflateInit');
c_stream.next_in := hello;
c_stream.next_out := compr;
c_stream.avail_in := 3;
c_stream.avail_out := Integer(comprLen);
err := deflate(c_stream, Z_FULL_FLUSH);
CHECK_ERR(err, 'deflate');
Inc(PByteArray(compr)^[3]);
c_stream.avail_in := len - 3;
err := deflate(c_stream, Z_FINISH);
if err <> Z_STREAM_END then
CHECK_ERR(err, 'deflate');
err := deflateEnd(c_stream);
CHECK_ERR(err, 'deflateEnd');
comprLen := c_stream.total_out;
end;
procedure test_sync(compr: Pointer; comprLen: LongInt;
uncompr: Pointer; uncomprLen : LongInt);
var err: Integer;
d_stream: z_stream;
begin
StrCopy(PChar(uncompr), 'garbage');
d_stream.zalloc := NIL;
d_stream.zfree := NIL;
d_stream.opaque := NIL;
d_stream.next_in := compr;
d_stream.avail_in := 2;
err := inflateInit(d_stream);
CHECK_ERR(err, 'inflateInit');
d_stream.next_out := uncompr;
d_stream.avail_out := Integer(uncomprLen);
inflate(d_stream, Z_NO_FLUSH);
CHECK_ERR(err, 'inflate');
d_stream.avail_in := Integer(comprLen-2);
err := inflateSync(d_stream);
CHECK_ERR(err, 'inflateSync');
err := inflate(d_stream, Z_FINISH);
if err <> Z_DATA_ERROR then
EXIT_ERR('inflate should report DATA_ERROR');
err := inflateEnd(d_stream);
CHECK_ERR(err, 'inflateEnd');
WriteLn('after inflateSync(): hel', PChar(uncompr));
end;
procedure test_dict_deflate(compr: Pointer; comprLen: LongInt);
var c_stream: z_stream;
err: Integer;
begin
c_stream.zalloc := NIL;
c_stream.zfree := NIL;
c_stream.opaque := NIL;
err := deflateInit(c_stream, Z_BEST_COMPRESSION);
CHECK_ERR(err, 'deflateInit');
err := deflateSetDictionary(c_stream, dictionary, StrLen(dictionary));
CHECK_ERR(err, 'deflateSetDictionary');
dictId := c_stream.adler;
c_stream.next_out := compr;
c_stream.avail_out := Integer(comprLen);
c_stream.next_in := hello;
c_stream.avail_in := StrLen(hello)+1;
err := deflate(c_stream, Z_FINISH);
if err <> Z_STREAM_END then
EXIT_ERR('deflate should report Z_STREAM_END');
err := deflateEnd(c_stream);
CHECK_ERR(err, 'deflateEnd');
end;
procedure test_dict_inflate(compr: Pointer; comprLen: LongInt;
uncompr: Pointer; uncomprLen: LongInt);
var err: Integer;
d_stream: z_stream;
begin
StrCopy(PChar(uncompr), 'garbage');
d_stream.zalloc := NIL;
d_stream.zfree := NIL;
d_stream.opaque := NIL;
d_stream.next_in := compr;
d_stream.avail_in := Integer(comprLen);
err := inflateInit(d_stream);
CHECK_ERR(err, 'inflateInit');
d_stream.next_out := uncompr;
d_stream.avail_out := Integer(uncomprLen);
while TRUE do
begin
err := inflate(d_stream, Z_NO_FLUSH);
if err = Z_STREAM_END then
break;
if err = Z_NEED_DICT then
begin
if d_stream.adler <> dictId then
EXIT_ERR('unexpected dictionary');
err := inflateSetDictionary(d_stream, dictionary, StrLen(dictionary));
end;
CHECK_ERR(err, 'inflate with dict');
end;
err := inflateEnd(d_stream);
CHECK_ERR(err, 'inflateEnd');
if StrComp(PChar(uncompr), hello) <> 0 then
EXIT_ERR('bad inflate with dict')
else
WriteLn('inflate with dictionary: ', PChar(uncompr));
end;
var compr, uncompr: Pointer;
comprLen, uncomprLen: LongInt;
begin
if zlibVersion^ <> ZLIB_VERSION[1] then
EXIT_ERR('Incompatible zlib version');
WriteLn('zlib version: ', zlibVersion);
WriteLn('zlib compile flags: ', Format('0x%x', [zlibCompileFlags]));
comprLen := 10000 * SizeOf(Integer);
uncomprLen := comprLen;
GetMem(compr, comprLen);
GetMem(uncompr, uncomprLen);
if (compr = NIL) or (uncompr = NIL) then
EXIT_ERR('Out of memory');
FillChar(compr^, comprLen, 0);
FillChar(uncompr^, uncomprLen, 0);
WriteLn('** Testing compress');
test_compress(compr, comprLen, uncompr, uncomprLen);
WriteLn('** Testing gzio');
if ParamCount >= 1 then
test_gzio(ParamStr(1), uncompr, uncomprLen)
else
test_gzio(TESTFILE, uncompr, uncomprLen);
WriteLn('** Testing deflate with small buffers');
test_deflate(compr, comprLen);
WriteLn('** Testing inflate with small buffers');
test_inflate(compr, comprLen, uncompr, uncomprLen);
WriteLn('** Testing deflate with large buffers');
test_large_deflate(compr, comprLen, uncompr, uncomprLen);
WriteLn('** Testing inflate with large buffers');
test_large_inflate(compr, comprLen, uncompr, uncomprLen);
WriteLn('** Testing deflate with full flush');
test_flush(compr, comprLen);
WriteLn('** Testing inflateSync');
test_sync(compr, comprLen, uncompr, uncomprLen);
comprLen := uncomprLen;
WriteLn('** Testing deflate and inflate with preset dictionary');
test_dict_deflate(compr, comprLen);
test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
FreeMem(compr, comprLen);
FreeMem(uncompr, uncomprLen);
end.