Fossil SCM

fossil-scm / compat / zlib / test / example.c
Blame History Raw 553 lines
1
/* example.c -- usage example of the zlib compression library
2
* Copyright (C) 1995-2026 Jean-loup Gailly
3
* For conditions of distribution and use, see copyright notice in zlib.h
4
*/
5
6
/* @(#) $Id$ */
7
8
#if defined(_WIN32) && !defined(_CRT_SECURE_NO_WARNINGS)
9
# define _CRT_SECURE_NO_WARNINGS
10
#endif
11
12
#include "zlib.h"
13
#include <stdio.h>
14
15
#ifdef STDC
16
# include <string.h>
17
# include <stdlib.h>
18
#endif
19
20
#if defined(VMS)
21
# define TESTFILE "foo-gz"
22
#elif defined(__riscos) && !defined(__TARGET_UNIXLIB__)
23
# define TESTFILE "foo/gz"
24
#else
25
# define TESTFILE "foo.gz"
26
#endif
27
28
#define CHECK_ERR(err, msg) { \
29
if (err != Z_OK) { \
30
fprintf(stderr, "%s error: %d\n", msg, err); \
31
exit(1); \
32
} \
33
}
34
35
static z_const char hello[] = "hello, hello!";
36
/* "hello world" would be more standard, but the repeated "hello"
37
* stresses the compression code better, sorry...
38
*/
39
40
static const char dictionary[] = "hello";
41
static uLong dictId; /* Adler32 value of the dictionary */
42
43
#ifdef Z_SOLO
44
45
static void *myalloc(void *q, unsigned n, unsigned m) {
46
(void)q;
47
return calloc(n, m);
48
}
49
50
static void myfree(void *q, void *p) {
51
(void)q;
52
free(p);
53
}
54
55
static alloc_func zalloc = myalloc;
56
static free_func zfree = myfree;
57
58
#else /* !Z_SOLO */
59
60
static alloc_func zalloc = (alloc_func)0;
61
static free_func zfree = (free_func)0;
62
63
/* ===========================================================================
64
* Test compress() and uncompress()
65
*/
66
static void test_compress(Byte *compr, uLong comprLen, Byte *uncompr,
67
uLong uncomprLen) {
68
int err;
69
uLong len = (uLong)strlen(hello)+1;
70
71
err = compress(compr, &comprLen, (const Bytef*)hello, len);
72
CHECK_ERR(err, "compress");
73
74
strcpy((char*)uncompr, "garbage");
75
76
err = uncompress(uncompr, &uncomprLen, compr, comprLen);
77
CHECK_ERR(err, "uncompress");
78
79
if (strcmp((char*)uncompr, hello)) {
80
fprintf(stderr, "bad uncompress\n");
81
exit(1);
82
} else {
83
printf("uncompress(): %s\n", (char *)uncompr);
84
}
85
}
86
87
/* ===========================================================================
88
* Test read/write of .gz files
89
*/
90
static void test_gzio(const char *fname, Byte *uncompr, uLong uncomprLen) {
91
#ifdef NO_GZCOMPRESS
92
fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
93
#else
94
int err;
95
int len = (int)strlen(hello)+1;
96
gzFile file;
97
z_off_t pos;
98
99
file = gzopen(fname, "wb");
100
if (file == NULL) {
101
fprintf(stderr, "gzopen error\n");
102
exit(1);
103
}
104
gzputc(file, 'h');
105
if (gzputs(file, "ello") != 4) {
106
fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
107
exit(1);
108
}
109
if (gzprintf(file, ", %s!", "hello") != 8) {
110
fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
111
exit(1);
112
}
113
gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
114
gzclose(file);
115
116
file = gzopen(fname, "rb");
117
if (file == NULL) {
118
fprintf(stderr, "gzopen error\n");
119
exit(1);
120
}
121
strcpy((char*)uncompr, "garbage");
122
123
if (gzread(file, uncompr, (unsigned)uncomprLen) != len) {
124
fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
125
exit(1);
126
}
127
if (strcmp((char*)uncompr, hello)) {
128
fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
129
exit(1);
130
} else {
131
printf("gzread(): %s\n", (char*)uncompr);
132
}
133
134
pos = gzseek(file, -8L, SEEK_CUR);
135
if (pos != 6 || gztell(file) != pos) {
136
fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
137
(long)pos, (long)gztell(file));
138
exit(1);
139
}
140
141
if (gzgetc(file) != ' ') {
142
fprintf(stderr, "gzgetc error\n");
143
exit(1);
144
}
145
146
if (gzungetc(' ', file) != ' ') {
147
fprintf(stderr, "gzungetc error\n");
148
exit(1);
149
}
150
151
gzgets(file, (char*)uncompr, (int)uncomprLen);
152
if (strlen((char*)uncompr) != 7) { /* " hello!" */
153
fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
154
exit(1);
155
}
156
if (strcmp((char*)uncompr, hello + 6)) {
157
fprintf(stderr, "bad gzgets after gzseek\n");
158
exit(1);
159
} else {
160
printf("gzgets() after gzseek: %s\n", (char*)uncompr);
161
}
162
163
gzclose(file);
164
#endif
165
}
166
167
#endif /* Z_SOLO */
168
169
/* ===========================================================================
170
* Test deflate() with small buffers
171
*/
172
static void test_deflate(Byte *compr, uLong comprLen) {
173
z_stream c_stream; /* compression stream */
174
int err;
175
uLong len = (uLong)strlen(hello)+1;
176
177
c_stream.zalloc = zalloc;
178
c_stream.zfree = zfree;
179
c_stream.opaque = (voidpf)0;
180
181
err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
182
CHECK_ERR(err, "deflateInit");
183
184
c_stream.next_in = (z_const unsigned char *)hello;
185
c_stream.next_out = compr;
186
187
while (c_stream.total_in != len && c_stream.total_out < comprLen) {
188
c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
189
err = deflate(&c_stream, Z_NO_FLUSH);
190
CHECK_ERR(err, "deflate");
191
}
192
/* Finish the stream, still forcing small buffers: */
193
for (;;) {
194
c_stream.avail_out = 1;
195
err = deflate(&c_stream, Z_FINISH);
196
if (err == Z_STREAM_END) break;
197
CHECK_ERR(err, "deflate");
198
}
199
200
err = deflateEnd(&c_stream);
201
CHECK_ERR(err, "deflateEnd");
202
}
203
204
/* ===========================================================================
205
* Test inflate() with small buffers
206
*/
207
static void test_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
208
uLong uncomprLen) {
209
int err;
210
z_stream d_stream; /* decompression stream */
211
212
strcpy((char*)uncompr, "garbage");
213
214
d_stream.zalloc = zalloc;
215
d_stream.zfree = zfree;
216
d_stream.opaque = (voidpf)0;
217
218
d_stream.next_in = compr;
219
d_stream.avail_in = 0;
220
d_stream.next_out = uncompr;
221
222
err = inflateInit(&d_stream);
223
CHECK_ERR(err, "inflateInit");
224
225
while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
226
d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
227
err = inflate(&d_stream, Z_NO_FLUSH);
228
if (err == Z_STREAM_END) break;
229
CHECK_ERR(err, "inflate");
230
}
231
232
err = inflateEnd(&d_stream);
233
CHECK_ERR(err, "inflateEnd");
234
235
if (strcmp((char*)uncompr, hello)) {
236
fprintf(stderr, "bad inflate\n");
237
exit(1);
238
} else {
239
printf("inflate(): %s\n", (char *)uncompr);
240
}
241
}
242
243
/* ===========================================================================
244
* Test deflate() with large buffers and dynamic change of compression level
245
*/
246
static void test_large_deflate(Byte *compr, uLong comprLen, Byte *uncompr,
247
uLong uncomprLen) {
248
z_stream c_stream; /* compression stream */
249
int err;
250
251
c_stream.zalloc = zalloc;
252
c_stream.zfree = zfree;
253
c_stream.opaque = (voidpf)0;
254
255
err = deflateInit(&c_stream, Z_BEST_SPEED);
256
CHECK_ERR(err, "deflateInit");
257
258
c_stream.next_out = compr;
259
c_stream.avail_out = (uInt)comprLen;
260
261
/* At this point, uncompr is still mostly zeroes, so it should compress
262
* very well:
263
*/
264
c_stream.next_in = uncompr;
265
c_stream.avail_in = (uInt)uncomprLen;
266
err = deflate(&c_stream, Z_NO_FLUSH);
267
CHECK_ERR(err, "deflate");
268
if (c_stream.avail_in != 0) {
269
fprintf(stderr, "deflate not greedy\n");
270
exit(1);
271
}
272
273
/* Feed in already compressed data and switch to no compression: */
274
deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
275
c_stream.next_in = compr;
276
c_stream.avail_in = (uInt)uncomprLen/2;
277
err = deflate(&c_stream, Z_NO_FLUSH);
278
CHECK_ERR(err, "deflate");
279
280
/* Switch back to compressing mode: */
281
deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
282
c_stream.next_in = uncompr;
283
c_stream.avail_in = (uInt)uncomprLen;
284
err = deflate(&c_stream, Z_NO_FLUSH);
285
CHECK_ERR(err, "deflate");
286
287
err = deflate(&c_stream, Z_FINISH);
288
if (err != Z_STREAM_END) {
289
fprintf(stderr, "deflate should report Z_STREAM_END\n");
290
exit(1);
291
}
292
err = deflateEnd(&c_stream);
293
CHECK_ERR(err, "deflateEnd");
294
}
295
296
/* ===========================================================================
297
* Test inflate() with large buffers
298
*/
299
static void test_large_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
300
uLong uncomprLen) {
301
int err;
302
z_stream d_stream; /* decompression stream */
303
304
strcpy((char*)uncompr, "garbage");
305
306
d_stream.zalloc = zalloc;
307
d_stream.zfree = zfree;
308
d_stream.opaque = (voidpf)0;
309
310
d_stream.next_in = compr;
311
d_stream.avail_in = (uInt)comprLen;
312
313
err = inflateInit(&d_stream);
314
CHECK_ERR(err, "inflateInit");
315
316
for (;;) {
317
d_stream.next_out = uncompr; /* discard the output */
318
d_stream.avail_out = (uInt)uncomprLen;
319
err = inflate(&d_stream, Z_NO_FLUSH);
320
if (err == Z_STREAM_END) break;
321
CHECK_ERR(err, "large inflate");
322
}
323
324
err = inflateEnd(&d_stream);
325
CHECK_ERR(err, "inflateEnd");
326
327
if (d_stream.total_out != 2*uncomprLen + uncomprLen/2) {
328
fprintf(stderr, "bad large inflate: %lu\n", d_stream.total_out);
329
exit(1);
330
} else {
331
printf("large_inflate(): OK\n");
332
}
333
}
334
335
/* ===========================================================================
336
* Test deflate() with full flush
337
*/
338
static void test_flush(Byte *compr, uLong *comprLen) {
339
z_stream c_stream; /* compression stream */
340
int err;
341
uInt len = (uInt)strlen(hello)+1;
342
343
c_stream.zalloc = zalloc;
344
c_stream.zfree = zfree;
345
c_stream.opaque = (voidpf)0;
346
347
err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
348
CHECK_ERR(err, "deflateInit");
349
350
c_stream.next_in = (z_const unsigned char *)hello;
351
c_stream.next_out = compr;
352
c_stream.avail_in = 3;
353
c_stream.avail_out = (uInt)*comprLen;
354
err = deflate(&c_stream, Z_FULL_FLUSH);
355
CHECK_ERR(err, "deflate");
356
357
compr[3]++; /* force an error in first compressed block */
358
c_stream.avail_in = len - 3;
359
360
err = deflate(&c_stream, Z_FINISH);
361
if (err != Z_STREAM_END) {
362
CHECK_ERR(err, "deflate");
363
}
364
err = deflateEnd(&c_stream);
365
CHECK_ERR(err, "deflateEnd");
366
367
*comprLen = c_stream.total_out;
368
}
369
370
/* ===========================================================================
371
* Test inflateSync()
372
*/
373
static void test_sync(Byte *compr, uLong comprLen, Byte *uncompr,
374
uLong uncomprLen) {
375
int err;
376
z_stream d_stream; /* decompression stream */
377
378
strcpy((char*)uncompr, "garbage");
379
380
d_stream.zalloc = zalloc;
381
d_stream.zfree = zfree;
382
d_stream.opaque = (voidpf)0;
383
384
d_stream.next_in = compr;
385
d_stream.avail_in = 2; /* just read the zlib header */
386
387
err = inflateInit(&d_stream);
388
CHECK_ERR(err, "inflateInit");
389
390
d_stream.next_out = uncompr;
391
d_stream.avail_out = (uInt)uncomprLen;
392
393
err = inflate(&d_stream, Z_NO_FLUSH);
394
CHECK_ERR(err, "inflate");
395
396
d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */
397
err = inflateSync(&d_stream); /* but skip the damaged part */
398
CHECK_ERR(err, "inflateSync");
399
400
err = inflate(&d_stream, Z_FINISH);
401
if (err != Z_STREAM_END) {
402
fprintf(stderr, "inflate should report Z_STREAM_END\n");
403
exit(1);
404
}
405
err = inflateEnd(&d_stream);
406
CHECK_ERR(err, "inflateEnd");
407
408
printf("after inflateSync(): hel%s\n", (char *)uncompr);
409
}
410
411
/* ===========================================================================
412
* Test deflate() with preset dictionary
413
*/
414
static void test_dict_deflate(Byte *compr, uLong comprLen) {
415
z_stream c_stream; /* compression stream */
416
int err;
417
418
c_stream.zalloc = zalloc;
419
c_stream.zfree = zfree;
420
c_stream.opaque = (voidpf)0;
421
422
err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
423
CHECK_ERR(err, "deflateInit");
424
425
err = deflateSetDictionary(&c_stream,
426
(const Bytef*)dictionary, (int)sizeof(dictionary));
427
CHECK_ERR(err, "deflateSetDictionary");
428
429
dictId = c_stream.adler;
430
c_stream.next_out = compr;
431
c_stream.avail_out = (uInt)comprLen;
432
433
c_stream.next_in = (z_const unsigned char *)hello;
434
c_stream.avail_in = (uInt)strlen(hello)+1;
435
436
err = deflate(&c_stream, Z_FINISH);
437
if (err != Z_STREAM_END) {
438
fprintf(stderr, "deflate should report Z_STREAM_END\n");
439
exit(1);
440
}
441
err = deflateEnd(&c_stream);
442
CHECK_ERR(err, "deflateEnd");
443
}
444
445
/* ===========================================================================
446
* Test inflate() with a preset dictionary
447
*/
448
static void test_dict_inflate(Byte *compr, uLong comprLen, Byte *uncompr,
449
uLong uncomprLen) {
450
int err;
451
z_stream d_stream; /* decompression stream */
452
453
strcpy((char*)uncompr, "garbage");
454
455
d_stream.zalloc = zalloc;
456
d_stream.zfree = zfree;
457
d_stream.opaque = (voidpf)0;
458
459
d_stream.next_in = compr;
460
d_stream.avail_in = (uInt)comprLen;
461
462
err = inflateInit(&d_stream);
463
CHECK_ERR(err, "inflateInit");
464
465
d_stream.next_out = uncompr;
466
d_stream.avail_out = (uInt)uncomprLen;
467
468
for (;;) {
469
err = inflate(&d_stream, Z_NO_FLUSH);
470
if (err == Z_STREAM_END) break;
471
if (err == Z_NEED_DICT) {
472
if (d_stream.adler != dictId) {
473
fprintf(stderr, "unexpected dictionary");
474
exit(1);
475
}
476
err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
477
(int)sizeof(dictionary));
478
}
479
CHECK_ERR(err, "inflate with dict");
480
}
481
482
err = inflateEnd(&d_stream);
483
CHECK_ERR(err, "inflateEnd");
484
485
if (strcmp((char*)uncompr, hello)) {
486
fprintf(stderr, "bad inflate with dict\n");
487
exit(1);
488
} else {
489
printf("inflate with dictionary: %s\n", (char *)uncompr);
490
}
491
}
492
493
/* ===========================================================================
494
* Usage: example [output.gz [input.gz]]
495
*/
496
497
int main(int argc, char *argv[]) {
498
Byte *compr, *uncompr;
499
uLong uncomprLen = 20000;
500
uLong comprLen = 3 * uncomprLen;
501
static const char* myVersion = ZLIB_VERSION;
502
503
if (zlibVersion()[0] != myVersion[0]) {
504
fprintf(stderr, "incompatible zlib version\n");
505
exit(1);
506
507
} else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
508
fprintf(stderr, "warning: different zlib version linked: %s\n",
509
zlibVersion());
510
}
511
512
printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
513
ZLIB_VERSION, (unsigned)ZLIB_VERNUM, zlibCompileFlags());
514
515
compr = (Byte*)calloc((uInt)comprLen, 1);
516
uncompr = (Byte*)calloc((uInt)uncomprLen, 1);
517
/* compr and uncompr are cleared to avoid reading uninitialized
518
* data and to ensure that uncompr compresses well.
519
*/
520
if (compr == Z_NULL || uncompr == Z_NULL) {
521
printf("out of memory\n");
522
exit(1);
523
}
524
525
#ifdef Z_SOLO
526
(void)argc;
527
(void)argv;
528
#else
529
test_compress(compr, comprLen, uncompr, uncomprLen);
530
531
test_gzio((argc > 1 ? argv[1] : TESTFILE),
532
uncompr, uncomprLen);
533
#endif
534
535
test_deflate(compr, comprLen);
536
test_inflate(compr, comprLen, uncompr, uncomprLen);
537
538
test_large_deflate(compr, comprLen, uncompr, uncomprLen);
539
test_large_inflate(compr, comprLen, uncompr, uncomprLen);
540
541
test_flush(compr, &comprLen);
542
test_sync(compr, comprLen, uncompr, uncomprLen);
543
comprLen = 3 * uncomprLen;
544
545
test_dict_deflate(compr, comprLen);
546
test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
547
548
free(compr);
549
free(uncompr);
550
551
return 0;
552
}
553

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button