Blame |
Last modification |
View Log
| RSS feed
/* example.c -- usage example of the zlib compression library
* Copyright (C) 1995-1998 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id: example.c,v 1.1 2003/04/29 21:57:48 ace Exp $ */
#include <stdio.h>
#include "zlib.h"
#ifdef STDC
# include <string.h>
# include <stdlib.h>
#else
extern void exit OF
((int));
#endif
#if defined(VMS) || defined(RISCOS)
# define TESTFILE "foo-gz"
#else
# define TESTFILE "foo.gz"
#endif
#define CHECK_ERR(err, msg) { \
if (err != Z_OK) { \
fprintf(stderr, "%s error: %d\n", msg, err); \
exit(1); \
} \
}
const char hello
[] = "hello, hello!";
/* "hello world" would be more standard, but the repeated "hello"
* stresses the compression code better, sorry...
*/
const char dictionary
[] = "hello";
uLong dictId
; /* Adler32 value of the dictionary */
void test_compress OF
((Byte
*compr
, uLong comprLen
,
Byte
*uncompr
, uLong uncomprLen
));
void test_gzio OF
((const char *out
, const char *in
,
Byte
*uncompr
, int uncomprLen
));
void test_deflate OF
((Byte
*compr
, uLong comprLen
));
void test_inflate OF
((Byte
*compr
, uLong comprLen
,
Byte
*uncompr
, uLong uncomprLen
));
void test_large_deflate OF
((Byte
*compr
, uLong comprLen
,
Byte
*uncompr
, uLong uncomprLen
));
void test_large_inflate OF
((Byte
*compr
, uLong comprLen
,
Byte
*uncompr
, uLong uncomprLen
));
void test_flush OF
((Byte
*compr
, uLong
*comprLen
));
void test_sync OF
((Byte
*compr
, uLong comprLen
,
Byte
*uncompr
, uLong uncomprLen
));
void test_dict_deflate OF
((Byte
*compr
, uLong comprLen
));
void test_dict_inflate OF
((Byte
*compr
, uLong comprLen
,
Byte
*uncompr
, uLong uncomprLen
));
int main OF
((int argc
, char *argv
[]));
/* ===========================================================================
* Test compress() and uncompress()
*/
void test_compress
(compr
, comprLen
, uncompr
, uncomprLen
)
Byte
*compr
, *uncompr
;
uLong comprLen
, uncomprLen
;
{
int err
;
uLong len
= strlen(hello
)+1;
err
= compress
(compr
, &comprLen
, (const Bytef
*)hello
, len
);
CHECK_ERR
(err
, "compress");
strcpy((char*)uncompr
, "garbage");
err
= uncompress
(uncompr
, &uncomprLen
, compr
, comprLen
);
CHECK_ERR
(err
, "uncompress");
if (strcmp((char*)uncompr
, hello
)) {
fprintf(stderr
, "bad uncompress\n");
exit(1);
} else {
printf("uncompress(): %s\n", (char *)uncompr
);
}
}
/* ===========================================================================
* Test read/write of .gz files
*/
void test_gzio
(out
, in
, uncompr
, uncomprLen
)
const char *out
; /* compressed output file */
const char *in
; /* compressed input file */
Byte
*uncompr
;
int uncomprLen
;
{
int err
;
int len
= strlen(hello
)+1;
gzFile file
;
z_off_t pos
;
file
= gzopen
(out
, "wb");
if (file
== NULL
) {
fprintf(stderr
, "gzopen error\n");
exit(1);
}
gzputc
(file
, 'h');
if (gzputs
(file
, "ello") != 4) {
fprintf(stderr
, "gzputs err: %s\n", gzerror
(file
, &err
));
exit(1);
}
if (gzprintf
(file
, ", %s!", "hello") != 8) {
fprintf(stderr
, "gzprintf err: %s\n", gzerror
(file
, &err
));
exit(1);
}
gzseek
(file
, 1L, SEEK_CUR
); /* add one zero byte */
gzclose
(file
);
file
= gzopen
(in
, "rb");
if (file
== NULL
) {
fprintf(stderr
, "gzopen error\n");
}
strcpy((char*)uncompr
, "garbage");
uncomprLen
= gzread
(file
, uncompr
, (unsigned)uncomprLen
);
if (uncomprLen
!= len
) {
fprintf(stderr
, "gzread err: %s\n", gzerror
(file
, &err
));
exit(1);
}
if (strcmp((char*)uncompr
, hello
)) {
fprintf(stderr
, "bad gzread: %s\n", (char*)uncompr
);
exit(1);
} else {
printf("gzread(): %s\n", (char *)uncompr
);
}
pos
= gzseek
(file
, -8L, SEEK_CUR
);
if (pos
!= 6 || gztell
(file
) != pos
) {
fprintf(stderr
, "gzseek error, pos=%ld, gztell=%ld\n",
(long)pos
, (long)gztell
(file
));
exit(1);
}
if (gzgetc
(file
) != ' ') {
fprintf(stderr
, "gzgetc error\n");
exit(1);
}
gzgets
(file
, (char*)uncompr
, uncomprLen
);
uncomprLen
= strlen((char*)uncompr
);
if (uncomprLen
!= 6) { /* "hello!" */
fprintf(stderr
, "gzgets err after gzseek: %s\n", gzerror
(file
, &err
));
exit(1);
}
if (strcmp((char*)uncompr
, hello
+7)) {
fprintf(stderr
, "bad gzgets after gzseek\n");
exit(1);
} else {
printf("gzgets() after gzseek: %s\n", (char *)uncompr
);
}
gzclose
(file
);
}
/* ===========================================================================
* Test deflate() with small buffers
*/
void test_deflate
(compr
, comprLen
)
Byte
*compr
;
uLong comprLen
;
{
z_stream c_stream
; /* compression stream */
int err
;
int len
= strlen(hello
)+1;
c_stream.
zalloc = (alloc_func
)0;
c_stream.
zfree = (free_func
)0;
c_stream.
opaque = (voidpf
)0;
err
= deflateInit
(&c_stream
, Z_DEFAULT_COMPRESSION
);
CHECK_ERR
(err
, "deflateInit");
c_stream.
next_in = (Bytef
*)hello
;
c_stream.
next_out = compr
;
while (c_stream.
total_in != (uLong
)len
&& c_stream.
total_out < comprLen
) {
c_stream.
avail_in = c_stream.
avail_out = 1; /* force small buffers */
err
= deflate
(&c_stream
, Z_NO_FLUSH
);
CHECK_ERR
(err
, "deflate");
}
/* Finish the stream, still forcing small buffers: */
for (;;) {
c_stream.
avail_out = 1;
err
= deflate
(&c_stream
, Z_FINISH
);
if (err
== Z_STREAM_END
) break;
CHECK_ERR
(err
, "deflate");
}
err
= deflateEnd
(&c_stream
);
CHECK_ERR
(err
, "deflateEnd");
}
/* ===========================================================================
* Test inflate() with small buffers
*/
void test_inflate
(compr
, comprLen
, uncompr
, uncomprLen
)
Byte
*compr
, *uncompr
;
uLong comprLen
, uncomprLen
;
{
int err
;
z_stream d_stream
; /* decompression stream */
strcpy((char*)uncompr
, "garbage");
d_stream.
zalloc = (alloc_func
)0;
d_stream.
zfree = (free_func
)0;
d_stream.
opaque = (voidpf
)0;
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
&& d_stream.
total_in < comprLen
) {
d_stream.
avail_in = d_stream.
avail_out = 1; /* force small buffers */
err
= inflate
(&d_stream
, Z_NO_FLUSH
);
if (err
== Z_STREAM_END
) break;
CHECK_ERR
(err
, "inflate");
}
err
= inflateEnd
(&d_stream
);
CHECK_ERR
(err
, "inflateEnd");
if (strcmp((char*)uncompr
, hello
)) {
fprintf(stderr
, "bad inflate\n");
exit(1);
} else {
printf("inflate(): %s\n", (char *)uncompr
);
}
}
/* ===========================================================================
* Test deflate() with large buffers and dynamic change of compression level
*/
void test_large_deflate
(compr
, comprLen
, uncompr
, uncomprLen
)
Byte
*compr
, *uncompr
;
uLong comprLen
, uncomprLen
;
{
z_stream c_stream
; /* compression stream */
int err
;
c_stream.
zalloc = (alloc_func
)0;
c_stream.
zfree = (free_func
)0;
c_stream.
opaque = (voidpf
)0;
err
= deflateInit
(&c_stream
, Z_BEST_SPEED
);
CHECK_ERR
(err
, "deflateInit");
c_stream.
next_out = compr
;
c_stream.
avail_out = (uInt
)comprLen
;
/* At this point, uncompr is still mostly zeroes, so it should compress
* very well:
*/
c_stream.
next_in = uncompr
;
c_stream.
avail_in = (uInt
)uncomprLen
;
err
= deflate
(&c_stream
, Z_NO_FLUSH
);
CHECK_ERR
(err
, "deflate");
if (c_stream.
avail_in != 0) {
fprintf(stderr
, "deflate not greedy\n");
exit(1);
}
/* Feed in already compressed data and switch to no compression: */
deflateParams
(&c_stream
, Z_NO_COMPRESSION
, Z_DEFAULT_STRATEGY
);
c_stream.
next_in = compr
;
c_stream.
avail_in = (uInt
)comprLen
/2;
err
= deflate
(&c_stream
, Z_NO_FLUSH
);
CHECK_ERR
(err
, "deflate");
/* Switch back to compressing mode: */
deflateParams
(&c_stream
, Z_BEST_COMPRESSION
, Z_FILTERED
);
c_stream.
next_in = uncompr
;
c_stream.
avail_in = (uInt
)uncomprLen
;
err
= deflate
(&c_stream
, Z_NO_FLUSH
);
CHECK_ERR
(err
, "deflate");
err
= deflate
(&c_stream
, Z_FINISH
);
if (err
!= Z_STREAM_END
) {
fprintf(stderr
, "deflate should report Z_STREAM_END\n");
exit(1);
}
err
= deflateEnd
(&c_stream
);
CHECK_ERR
(err
, "deflateEnd");
}
/* ===========================================================================
* Test inflate() with large buffers
*/
void test_large_inflate
(compr
, comprLen
, uncompr
, uncomprLen
)
Byte
*compr
, *uncompr
;
uLong comprLen
, uncomprLen
;
{
int err
;
z_stream d_stream
; /* decompression stream */
strcpy((char*)uncompr
, "garbage");
d_stream.
zalloc = (alloc_func
)0;
d_stream.
zfree = (free_func
)0;
d_stream.
opaque = (voidpf
)0;
d_stream.
next_in = compr
;
d_stream.
avail_in = (uInt
)comprLen
;
err
= inflateInit
(&d_stream
);
CHECK_ERR
(err
, "inflateInit");
for (;;) {
d_stream.
next_out = uncompr
; /* discard the output */
d_stream.
avail_out = (uInt
)uncomprLen
;
err
= inflate
(&d_stream
, Z_NO_FLUSH
);
if (err
== Z_STREAM_END
) break;
CHECK_ERR
(err
, "large inflate");
}
err
= inflateEnd
(&d_stream
);
CHECK_ERR
(err
, "inflateEnd");
if (d_stream.
total_out != 2*uncomprLen
+ comprLen
/2) {
fprintf(stderr
, "bad large inflate: %ld\n", d_stream.
total_out);
exit(1);
} else {
printf("large_inflate(): OK\n");
}
}
/* ===========================================================================
* Test deflate() with full flush
*/
void test_flush
(compr
, comprLen
)
Byte
*compr
;
uLong
*comprLen
;
{
z_stream c_stream
; /* compression stream */
int err
;
int len
= strlen(hello
)+1;
c_stream.
zalloc = (alloc_func
)0;
c_stream.
zfree = (free_func
)0;
c_stream.
opaque = (voidpf
)0;
err
= deflateInit
(&c_stream
, Z_DEFAULT_COMPRESSION
);
CHECK_ERR
(err
, "deflateInit");
c_stream.
next_in = (Bytef
*)hello
;
c_stream.
next_out = compr
;
c_stream.
avail_in = 3;
c_stream.
avail_out = (uInt
)*comprLen
;
err
= deflate
(&c_stream
, Z_FULL_FLUSH
);
CHECK_ERR
(err
, "deflate");
compr
[3]++; /* force an error in first compressed block */
c_stream.
avail_in = len
- 3;
err
= deflate
(&c_stream
, Z_FINISH
);
if (err
!= Z_STREAM_END
) {
CHECK_ERR
(err
, "deflate");
}
err
= deflateEnd
(&c_stream
);
CHECK_ERR
(err
, "deflateEnd");
*comprLen
= c_stream.
total_out;
}
/* ===========================================================================
* Test inflateSync()
*/
void test_sync
(compr
, comprLen
, uncompr
, uncomprLen
)
Byte
*compr
, *uncompr
;
uLong comprLen
, uncomprLen
;
{
int err
;
z_stream d_stream
; /* decompression stream */
strcpy((char*)uncompr
, "garbage");
d_stream.
zalloc = (alloc_func
)0;
d_stream.
zfree = (free_func
)0;
d_stream.
opaque = (voidpf
)0;
d_stream.
next_in = compr
;
d_stream.
avail_in = 2; /* just read the zlib header */
err
= inflateInit
(&d_stream
);
CHECK_ERR
(err
, "inflateInit");
d_stream.
next_out = uncompr
;
d_stream.
avail_out = (uInt
)uncomprLen
;
inflate
(&d_stream
, Z_NO_FLUSH
);
CHECK_ERR
(err
, "inflate");
d_stream.
avail_in = (uInt
)comprLen
-2; /* read all compressed data */
err
= inflateSync
(&d_stream
); /* but skip the damaged part */
CHECK_ERR
(err
, "inflateSync");
err
= inflate
(&d_stream
, Z_FINISH
);
if (err
!= Z_DATA_ERROR
) {
fprintf(stderr
, "inflate should report DATA_ERROR\n");
/* Because of incorrect adler32 */
exit(1);
}
err
= inflateEnd
(&d_stream
);
CHECK_ERR
(err
, "inflateEnd");
printf("after inflateSync(): hel%s\n", (char *)uncompr
);
}
/* ===========================================================================
* Test deflate() with preset dictionary
*/
void test_dict_deflate
(compr
, comprLen
)
Byte
*compr
;
uLong comprLen
;
{
z_stream c_stream
; /* compression stream */
int err
;
c_stream.
zalloc = (alloc_func
)0;
c_stream.
zfree = (free_func
)0;
c_stream.
opaque = (voidpf
)0;
err
= deflateInit
(&c_stream
, Z_BEST_COMPRESSION
);
CHECK_ERR
(err
, "deflateInit");
err
= deflateSetDictionary
(&c_stream
,
(const Bytef
*)dictionary
, sizeof(dictionary
));
CHECK_ERR
(err
, "deflateSetDictionary");
dictId
= c_stream.
adler;
c_stream.
next_out = compr
;
c_stream.
avail_out = (uInt
)comprLen
;
c_stream.
next_in = (Bytef
*)hello
;
c_stream.
avail_in = (uInt
)strlen(hello
)+1;
err
= deflate
(&c_stream
, Z_FINISH
);
if (err
!= Z_STREAM_END
) {
fprintf(stderr
, "deflate should report Z_STREAM_END\n");
exit(1);
}
err
= deflateEnd
(&c_stream
);
CHECK_ERR
(err
, "deflateEnd");
}
/* ===========================================================================
* Test inflate() with a preset dictionary
*/
void test_dict_inflate
(compr
, comprLen
, uncompr
, uncomprLen
)
Byte
*compr
, *uncompr
;
uLong comprLen
, uncomprLen
;
{
int err
;
z_stream d_stream
; /* decompression stream */
strcpy((char*)uncompr
, "garbage");
d_stream.
zalloc = (alloc_func
)0;
d_stream.
zfree = (free_func
)0;
d_stream.
opaque = (voidpf
)0;
d_stream.
next_in = compr
;
d_stream.
avail_in = (uInt
)comprLen
;
err
= inflateInit
(&d_stream
);
CHECK_ERR
(err
, "inflateInit");
d_stream.
next_out = uncompr
;
d_stream.
avail_out = (uInt
)uncomprLen
;
for (;;) {
err
= inflate
(&d_stream
, Z_NO_FLUSH
);
if (err
== Z_STREAM_END
) break;
if (err
== Z_NEED_DICT
) {
if (d_stream.
adler != dictId
) {
fprintf(stderr
, "unexpected dictionary");
exit(1);
}
err
= inflateSetDictionary
(&d_stream
, (const Bytef
*)dictionary
,
sizeof(dictionary
));
}
CHECK_ERR
(err
, "inflate with dict");
}
err
= inflateEnd
(&d_stream
);
CHECK_ERR
(err
, "inflateEnd");
if (strcmp((char*)uncompr
, hello
)) {
fprintf(stderr
, "bad inflate with dict\n");
exit(1);
} else {
printf("inflate with dictionary: %s\n", (char *)uncompr
);
}
}
/* ===========================================================================
* Usage: example [output.gz [input.gz]]
*/
int main
(argc
, argv
)
int argc
;
char *argv
[];
{
Byte
*compr
, *uncompr
;
uLong comprLen
= 10000*sizeof(int); /* don't overflow on MSDOS */
uLong uncomprLen
= comprLen
;
static const char* myVersion
= ZLIB_VERSION
;
if (zlibVersion
()[0] != myVersion
[0]) {
fprintf(stderr
, "incompatible zlib version\n");
exit(1);
} else if (strcmp(zlibVersion
(), ZLIB_VERSION
) != 0) {
fprintf(stderr
, "warning: different zlib version\n");
}
compr
= (Byte
*)calloc((uInt
)comprLen
, 1);
uncompr
= (Byte
*)calloc((uInt
)uncomprLen
, 1);
/* compr and uncompr are cleared to avoid reading uninitialized
* data and to ensure that uncompr compresses well.
*/
if (compr
== Z_NULL
|| uncompr
== Z_NULL
) {
printf("out of memory\n");
exit(1);
}
test_compress
(compr
, comprLen
, uncompr
, uncomprLen
);
test_gzio
((argc
> 1 ? argv
[1] : TESTFILE
),
(argc
> 2 ? argv
[2] : TESTFILE
),
uncompr
, (int)uncomprLen
);
test_deflate
(compr
, comprLen
);
test_inflate
(compr
, comprLen
, uncompr
, uncomprLen
);
test_large_deflate
(compr
, comprLen
, uncompr
, uncomprLen
);
test_large_inflate
(compr
, comprLen
, uncompr
, uncomprLen
);
test_flush
(compr
, &comprLen
);
test_sync
(compr
, comprLen
, uncompr
, uncomprLen
);
comprLen
= uncomprLen
;
test_dict_deflate
(compr
, comprLen
);
test_dict_inflate
(compr
, comprLen
, uncompr
, uncomprLen
);
exit(0);
return 0; /* to avoid warning */
}