example.c 15 KB

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