example.pas 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664
  1. program example;
  2. { example.c -- usage example of the zlib compression library
  3. Copyright (C) 1995-1998 Jean-loup Gailly.
  4. Pascal tranlastion
  5. Copyright (C) 1998 by Jacques Nomssi Nzali
  6. For conditions of distribution and use, see copyright notice in readme.txt
  7. }
  8. {-$define MemCheck}
  9. {$DEFINE TEST_COMPRESS}
  10. {$DEFINE TEST_GZIO}
  11. {$DEFINE TEST_INFLATE}
  12. {$DEFINE TEST_DEFLATE}
  13. {$DEFINE TEST_SYNC}
  14. {$DEFINE TEST_DICT}
  15. {$DEFINE TEST_FLUSH}
  16. uses
  17. strings,
  18. zbase,
  19. gzio,
  20. zinflate,
  21. zdeflate,
  22. zcompres,
  23. zuncompr
  24. {$ifdef memcheck}
  25. , memcheck in '..\..\monotekt\pas\memcheck\memcheck.pas'
  26. {$endif}
  27. ;
  28. procedure Stop;
  29. begin
  30. Write('Program halted...');
  31. ReadLn;
  32. Halt(1);
  33. end;
  34. procedure CHECK_ERR(err : integer; msg : string);
  35. begin
  36. if (err <> Z_OK) then
  37. begin
  38. Write(msg, ' error: ', err);
  39. Stop;
  40. end;
  41. end;
  42. const
  43. hello : PChar = 'hello, hello!';
  44. { "hello world" would be more standard, but the repeated "hello"
  45. stresses the compression code better, sorry... }
  46. {$IFDEF TEST_DICT}
  47. const
  48. dictionary : PChar = 'hello';
  49. var
  50. dictId : cardinal; { Adler32 value of the dictionary }
  51. {$ENDIF}
  52. { ===========================================================================
  53. Test compress() and uncompress() }
  54. {$IFDEF TEST_COMPRESS}
  55. procedure test_compress(compr : Pbyte; var comprLen : cardinal;
  56. uncompr : Pbyte; uncomprLen : cardinal);
  57. var
  58. err : integer;
  59. len : cardinal;
  60. begin
  61. len := strlen(hello)+1;
  62. err := compress(compr, comprLen, Pbyte(hello)^, len);
  63. CHECK_ERR(err, 'compress');
  64. strcopy(PChar(uncompr), 'garbage');
  65. err := uncompress(uncompr, uncomprLen, compr^, comprLen);
  66. CHECK_ERR(err, 'uncompress');
  67. if (strcomp(PChar(uncompr), hello)) <> 0 then
  68. begin
  69. WriteLn('bad uncompress');
  70. Stop;
  71. end
  72. else
  73. WriteLn('uncompress(): ', StrPas(PChar(uncompr)));
  74. end;
  75. {$ENDIF}
  76. { ===========================================================================
  77. Test read/write of .gz files }
  78. {$IFDEF TEST_GZIO}
  79. procedure test_gzio(const outf : string; { output file }
  80. const inf : string; { input file }
  81. uncompr : Pbyte;
  82. uncomprLen : integer);
  83. var
  84. err : integer;
  85. len : integer;
  86. var
  87. zfile : gzFile;
  88. pos : z_off_t;
  89. begin
  90. len := strlen(hello)+1;
  91. zfile := gzopen(outf, 'w');
  92. if (zfile = NIL) then
  93. begin
  94. WriteLn('_gzopen error');
  95. Stop;
  96. end;
  97. gzputc(zfile, 'h');
  98. if (gzputs(zfile, 'ello') <> 4) then
  99. begin
  100. WriteLn('gzputs err: ', gzerror(zfile, err));
  101. Stop;
  102. end;
  103. {$ifdef GZ_FORMAT_STRING}
  104. if (gzprintf(zfile, ', %s!', 'hello') <> 8) then
  105. begin
  106. WriteLn('gzprintf err: ', gzerror(zfile, err));
  107. Stop;
  108. end;
  109. {$else}
  110. if (gzputs(zfile, ', hello!') <> 8) then
  111. begin
  112. WriteLn('gzputs err: ', gzerror(zfile, err));
  113. Stop;
  114. end;
  115. {$ENDIF}
  116. gzseek(zfile, longint(1), SEEK_CUR); { add one zero byte }
  117. gzclose(zfile);
  118. zfile := gzopen(inf, 'r');
  119. if (zfile = NIL) then
  120. WriteLn('gzopen error');
  121. strcopy(pchar(uncompr), 'garbage');
  122. uncomprLen := gzread(zfile, uncompr, cardinal(uncomprLen));
  123. if (uncomprLen <> len) then
  124. begin
  125. WriteLn('gzread err: ', gzerror(zfile, err));
  126. Stop;
  127. end;
  128. if (strcomp(pchar(uncompr), hello)) <> 0 then
  129. begin
  130. WriteLn('bad gzread: ', pchar(uncompr));
  131. Stop;
  132. end
  133. else
  134. WriteLn('gzread(): ', pchar(uncompr));
  135. pos := gzseek(zfile, longint(-8), SEEK_CUR);
  136. if (pos <> 6) or (gztell(zfile) <> pos) then
  137. begin
  138. WriteLn('gzseek error, pos=',pos,', gztell=',gztell(zfile));
  139. Stop;
  140. end;
  141. if (char(gzgetc(zfile)) <> ' ') then
  142. begin
  143. WriteLn('gzgetc error');
  144. Stop;
  145. end;
  146. gzgets(zfile, pchar(uncompr), uncomprLen);
  147. uncomprLen := strlen(pchar(uncompr));
  148. if (uncomprLen <> 6) then
  149. begin { "hello!" }
  150. WriteLn('gzgets err after gzseek: ', gzerror(zfile, err));
  151. Stop;
  152. end;
  153. if (strcomp(pchar(uncompr), hello+7)) <> 0 then
  154. begin
  155. WriteLn('bad gzgets after gzseek');
  156. Stop;
  157. end
  158. else
  159. WriteLn('gzgets() after gzseek: ', PChar(uncompr));
  160. gzclose(zfile);
  161. end;
  162. {$ENDIF}
  163. { ===========================================================================
  164. Test deflate() with small buffers }
  165. {$IFDEF TEST_DEFLATE}
  166. procedure test_deflate(compr : Pbyte; comprLen : cardinal);
  167. var
  168. c_stream : z_stream; { compression stream }
  169. err : integer;
  170. len : integer;
  171. begin
  172. len := strlen(hello)+1;
  173. err := deflateInit(c_stream, Z_DEFAULT_COMPRESSION);
  174. CHECK_ERR(err, 'deflateInit');
  175. c_stream.next_in := Pbyte(hello);
  176. c_stream.next_out := compr;
  177. while (c_stream.total_in <> cardinal(len)) and (c_stream.total_out < comprLen) do
  178. begin
  179. c_stream.avail_out := 1; { force small buffers }
  180. c_stream.avail_in := 1;
  181. err := deflate(c_stream, Z_NO_FLUSH);
  182. CHECK_ERR(err, 'deflate');
  183. end;
  184. { Finish the stream, still forcing small buffers: }
  185. while TRUE do
  186. begin
  187. c_stream.avail_out := 1;
  188. err := deflate(c_stream, Z_FINISH);
  189. if (err = Z_STREAM_END) then
  190. break;
  191. CHECK_ERR(err, 'deflate');
  192. end;
  193. err := deflateEnd(c_stream);
  194. CHECK_ERR(err, 'deflateEnd');
  195. end;
  196. {$ENDIF}
  197. { ===========================================================================
  198. Test inflate() with small buffers
  199. }
  200. {$IFDEF TEST_INFLATE}
  201. procedure test_inflate(compr : Pbyte; comprLen : cardinal;
  202. uncompr : Pbyte; uncomprLen : cardinal);
  203. var
  204. err : integer;
  205. d_stream : z_stream; { decompression stream }
  206. begin
  207. strcopy(PChar(uncompr), 'garbage');
  208. d_stream.next_in := compr;
  209. d_stream.avail_in := 0;
  210. d_stream.next_out := uncompr;
  211. err := inflateInit(d_stream);
  212. CHECK_ERR(err, 'inflateInit');
  213. while (d_stream.total_out < uncomprLen) and
  214. (d_stream.total_in < comprLen) do
  215. begin
  216. d_stream.avail_out := 1; { force small buffers }
  217. d_stream.avail_in := 1;
  218. err := inflate(d_stream, Z_NO_FLUSH);
  219. if (err = Z_STREAM_END) then
  220. break;
  221. CHECK_ERR(err, 'inflate');
  222. end;
  223. err := inflateEnd(d_stream);
  224. CHECK_ERR(err, 'inflateEnd');
  225. if (strcomp(PChar(uncompr), hello) <> 0) then
  226. begin
  227. WriteLn('bad inflate');
  228. exit;
  229. end
  230. else
  231. begin
  232. WriteLn('inflate(): ', StrPas(PChar(uncompr)));
  233. end;
  234. end;
  235. {$ENDIF}
  236. { ===========================================================================
  237. Test deflate() with large buffers and dynamic change of compression level
  238. }
  239. {$IFDEF TEST_DEFLATE}
  240. procedure test_large_deflate(compr : Pbyte; comprLen : cardinal;
  241. uncompr : Pbyte; uncomprLen : cardinal);
  242. var
  243. c_stream : z_stream; { compression stream }
  244. err : integer;
  245. begin
  246. err := deflateInit(c_stream, Z_BEST_SPEED);
  247. CHECK_ERR(err, 'deflateInit');
  248. c_stream.next_out := compr;
  249. c_stream.avail_out := cardinal(comprLen);
  250. { At this point, uncompr is still mostly zeroes, so it should compress
  251. very well: }
  252. c_stream.next_in := uncompr;
  253. c_stream.avail_in := cardinal(uncomprLen);
  254. err := deflate(c_stream, Z_NO_FLUSH);
  255. CHECK_ERR(err, 'deflate');
  256. if (c_stream.avail_in <> 0) then
  257. begin
  258. WriteLn('deflate not greedy');
  259. exit;
  260. end;
  261. { Feed in already compressed data and switch to no compression: }
  262. deflateParams(c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
  263. c_stream.next_in := compr;
  264. c_stream.avail_in := cardinal(comprLen div 2);
  265. err := deflate(c_stream, Z_NO_FLUSH);
  266. CHECK_ERR(err, 'deflate');
  267. { Switch back to compressing mode: }
  268. deflateParams(c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
  269. c_stream.next_in := uncompr;
  270. c_stream.avail_in := cardinal(uncomprLen);
  271. err := deflate(c_stream, Z_NO_FLUSH);
  272. CHECK_ERR(err, 'deflate');
  273. err := deflate(c_stream, Z_FINISH);
  274. if (err <> Z_STREAM_END) then
  275. begin
  276. WriteLn('deflate should report Z_STREAM_END');
  277. exit;
  278. end;
  279. err := deflateEnd(c_stream);
  280. CHECK_ERR(err, 'deflateEnd');
  281. end;
  282. {$ENDIF}
  283. { ===========================================================================
  284. Test inflate() with large buffers }
  285. {$IFDEF TEST_INFLATE}
  286. procedure test_large_inflate(compr : Pbyte; comprLen : cardinal;
  287. uncompr : Pbyte; uncomprLen : cardinal);
  288. var
  289. err : integer;
  290. d_stream : z_stream; { decompression stream }
  291. begin
  292. strcopy(PChar(uncompr), 'garbage');
  293. d_stream.next_in := compr;
  294. d_stream.avail_in := cardinal(comprLen);
  295. err := inflateInit(d_stream);
  296. CHECK_ERR(err, 'inflateInit');
  297. while TRUE do
  298. begin
  299. d_stream.next_out := uncompr; { discard the output }
  300. d_stream.avail_out := cardinal(uncomprLen);
  301. err := inflate(d_stream, Z_NO_FLUSH);
  302. if (err = Z_STREAM_END) then
  303. break;
  304. CHECK_ERR(err, 'large inflate');
  305. end;
  306. err := inflateEnd(d_stream);
  307. CHECK_ERR(err, 'inflateEnd');
  308. if (d_stream.total_out <> 2*uncomprLen + comprLen div 2) then
  309. begin
  310. WriteLn('bad large inflate: ', d_stream.total_out);
  311. Stop;
  312. end
  313. else
  314. WriteLn('large_inflate(): OK');
  315. end;
  316. {$ENDIF}
  317. { ===========================================================================
  318. Test deflate() with full flush
  319. }
  320. {$IFDEF TEST_FLUSH}
  321. procedure test_flush(compr : Pbyte; var comprLen : cardinal);
  322. var
  323. c_stream : z_stream; { compression stream }
  324. err : integer;
  325. len : integer;
  326. begin
  327. len := strlen(hello)+1;
  328. err := deflateInit(c_stream, Z_DEFAULT_COMPRESSION);
  329. CHECK_ERR(err, 'deflateInit');
  330. c_stream.next_in := Pbyte(hello);
  331. c_stream.next_out := compr;
  332. c_stream.avail_in := 3;
  333. c_stream.avail_out := cardinal(comprLen);
  334. err := deflate(c_stream, Z_FULL_FLUSH);
  335. CHECK_ERR(err, 'deflate');
  336. Inc(pchar(compr)[3]); { force an error in first compressed block }
  337. c_stream.avail_in := len - 3;
  338. err := deflate(c_stream, Z_FINISH);
  339. if (err <> Z_STREAM_END) then
  340. CHECK_ERR(err, 'deflate');
  341. err := deflateEnd(c_stream);
  342. CHECK_ERR(err, 'deflateEnd');
  343. comprLen := c_stream.total_out;
  344. end;
  345. {$ENDIF}
  346. { ===========================================================================
  347. Test inflateSync()
  348. }
  349. {$IFDEF TEST_SYNC}
  350. procedure test_sync(compr : Pbyte; comprLen : cardinal;
  351. uncompr : Pbyte; uncomprLen : cardinal);
  352. var
  353. err : integer;
  354. d_stream : z_stream; { decompression stream }
  355. begin
  356. strcopy(PChar(uncompr), 'garbage');
  357. d_stream.next_in := compr;
  358. d_stream.avail_in := 2; { just read the zlib header }
  359. err := inflateInit(d_stream);
  360. CHECK_ERR(err, 'inflateInit');
  361. d_stream.next_out := uncompr;
  362. d_stream.avail_out := cardinal(uncomprLen);
  363. inflate(d_stream, Z_NO_FLUSH);
  364. CHECK_ERR(err, 'inflate');
  365. d_stream.avail_in := cardinal(comprLen-2); { read all compressed data }
  366. err := inflateSync(d_stream); { but skip the damaged part }
  367. CHECK_ERR(err, 'inflateSync');
  368. err := inflate(d_stream, Z_FINISH);
  369. if (err <> Z_DATA_ERROR) then
  370. begin
  371. WriteLn('inflate should report DATA_ERROR');
  372. { Because of incorrect adler32 }
  373. Stop;
  374. end;
  375. err := inflateEnd(d_stream);
  376. CHECK_ERR(err, 'inflateEnd');
  377. WriteLn('after inflateSync(): hel', StrPas(PChar(uncompr)));
  378. end;
  379. {$ENDIF}
  380. { ===========================================================================
  381. Test deflate() with preset dictionary
  382. }
  383. {$IFDEF TEST_DICT}
  384. procedure test_dict_deflate(compr : Pbyte; comprLen : cardinal);
  385. var
  386. c_stream : z_stream; { compression stream }
  387. err : integer;
  388. begin
  389. err := deflateInit(c_stream, Z_BEST_COMPRESSION);
  390. CHECK_ERR(err, 'deflateInit');
  391. err := deflateSetDictionary(c_stream,
  392. Pbyte(dictionary), StrLen(dictionary));
  393. CHECK_ERR(err, 'deflateSetDictionary');
  394. dictId := c_stream.adler;
  395. c_stream.next_out := compr;
  396. c_stream.avail_out := cardinal(comprLen);
  397. c_stream.next_in := Pbyte(hello);
  398. c_stream.avail_in := cardinal(strlen(hello)+1);
  399. err := deflate(c_stream, Z_FINISH);
  400. if (err <> Z_STREAM_END) then
  401. begin
  402. WriteLn('deflate should report Z_STREAM_END');
  403. exit;
  404. end;
  405. err := deflateEnd(c_stream);
  406. CHECK_ERR(err, 'deflateEnd');
  407. end;
  408. { ===========================================================================
  409. Test inflate() with a preset dictionary }
  410. procedure test_dict_inflate(compr : Pbyte; comprLen : cardinal;
  411. uncompr : Pbyte; uncomprLen : cardinal);
  412. var
  413. err : integer;
  414. d_stream : z_stream; { decompression stream }
  415. begin
  416. strcopy(PChar(uncompr), 'garbage');
  417. d_stream.next_in := compr;
  418. d_stream.avail_in := cardinal(comprLen);
  419. err := inflateInit(d_stream);
  420. CHECK_ERR(err, 'inflateInit');
  421. d_stream.next_out := uncompr;
  422. d_stream.avail_out := cardinal(uncomprLen);
  423. while TRUE do
  424. begin
  425. err := inflate(d_stream, Z_NO_FLUSH);
  426. if (err = Z_STREAM_END) then
  427. break;
  428. if (err = Z_NEED_DICT) then
  429. begin
  430. if (d_stream.adler <> dictId) then
  431. begin
  432. WriteLn('unexpected dictionary');
  433. Stop;
  434. end;
  435. err := inflateSetDictionary(d_stream, Pbyte(dictionary),
  436. StrLen(dictionary));
  437. end;
  438. CHECK_ERR(err, 'inflate with dict');
  439. end;
  440. err := inflateEnd(d_stream);
  441. CHECK_ERR(err, 'inflateEnd');
  442. if (strcomp(PChar(uncompr), hello)) <> 0 then
  443. begin
  444. WriteLn('bad inflate with dict');
  445. Stop;
  446. end
  447. else
  448. begin
  449. WriteLn('inflate with dictionary: ', StrPas(PChar(uncompr)));
  450. end;
  451. end;
  452. {$ENDIF}
  453. function GetFromFile(buf : Pbyte; FName : string;
  454. var MaxLen : cardinal) : boolean;
  455. const
  456. zOfs = 0;
  457. var
  458. f : file;
  459. Len : cardinal;
  460. begin
  461. assign(f, FName);
  462. GetFromFile := false;
  463. {$I-}
  464. filemode := 0; { read only }
  465. reset(f, 1);
  466. if IOresult = 0 then
  467. begin
  468. Len := FileSize(f)-zOfs;
  469. Seek(f, zOfs);
  470. if Len < MaxLen then
  471. MaxLen := Len;
  472. BlockRead(f, buf^, MaxLen);
  473. close(f);
  474. WriteLn(FName);
  475. GetFromFile := (IOresult = 0) and (MaxLen > 0);
  476. end
  477. else
  478. WriteLn('Could not open ', FName);
  479. end;
  480. { ===========================================================================
  481. Usage: example [output.gz [input.gz]]
  482. }
  483. var
  484. compr, uncompr : Pbyte;
  485. const
  486. msdoslen = 25000;
  487. comprLenL : cardinal = msdoslen div sizeof(cardinal); { don't overflow on MSDOS }
  488. uncomprLenL : cardinal = msdoslen div sizeof(cardinal);
  489. var
  490. zVersion,
  491. myVersion : string;
  492. var
  493. comprLen : cardinal;
  494. uncomprLen : cardinal;
  495. begin
  496. {$ifdef MemCheck}
  497. MemChk;
  498. {$endif}
  499. comprLen := comprLenL;
  500. uncomprLen := uncomprLenL;
  501. myVersion := ZLIB_VERSION;
  502. zVersion := zlibVersion;
  503. if (zVersion[1] <> myVersion[1]) then
  504. begin
  505. WriteLn('incompatible zlib version');
  506. Stop;
  507. end
  508. else
  509. if (zVersion <> ZLIB_VERSION) then
  510. begin
  511. WriteLn('warning: different zlib version');
  512. end;
  513. GetMem(compr, comprLen*sizeof(cardinal));
  514. GetMem(uncompr, uncomprLen*sizeof(cardinal));
  515. { compr and uncompr are cleared to avoid reading uninitialized
  516. data and to ensure that uncompr compresses well. }
  517. if (compr = nil) or (uncompr = nil) then
  518. begin
  519. WriteLn('out of memory');
  520. Stop;
  521. end;
  522. FillChar(compr^, comprLen*sizeof(cardinal), 0);
  523. FillChar(uncompr^, uncomprLen*sizeof(cardinal), 0);
  524. if (compr = nil) or (uncompr = nil) then
  525. begin
  526. WriteLn('out of memory');
  527. Stop;
  528. end;
  529. {$IFDEF TEST_COMPRESS}
  530. test_compress(compr, comprLenL, uncompr, uncomprLen);
  531. {$ENDIF}
  532. {$IFDEF TEST_GZIO}
  533. Case ParamCount of
  534. 0: test_gzio('foo.gz', 'foo.gz', uncompr, integer(uncomprLen));
  535. 1: test_gzio(ParamStr(1), 'foo.gz', uncompr, integer(uncomprLen));
  536. else
  537. test_gzio(ParamStr(1), ParamStr(2), uncompr, integer(uncomprLen));
  538. end;
  539. {$ENDIF}
  540. {$IFDEF TEST_DEFLATE}
  541. WriteLn('small buffer Deflate');
  542. test_deflate(compr, comprLen);
  543. {$ENDIF}
  544. {$IFDEF TEST_INFLATE}
  545. {$IFNDEF TEST_DEFLATE}
  546. WriteLn('small buffer Inflate');
  547. if GetFromFile(compr, 'u:\nomssi\paszlib\new\test0.z', comprLen) then
  548. {$ENDIF}
  549. test_inflate(compr, comprLen, uncompr, uncomprLen);
  550. {$ENDIF}
  551. readln;
  552. {$IFDEF TEST_DEFLATE}
  553. WriteLn('large buffer Deflate');
  554. test_large_deflate(compr, comprLen, uncompr, uncomprLen);
  555. {$ENDIF}
  556. {$IFDEF TEST_INFLATE}
  557. WriteLn('large buffer Inflate');
  558. test_large_inflate(compr, comprLen, uncompr, uncomprLen);
  559. {$ENDIF}
  560. {$IFDEF TEST_FLUSH}
  561. test_flush(compr, comprLenL);
  562. {$ENDIF}
  563. {$IFDEF TEST_SYNC}
  564. test_sync(compr, comprLen, uncompr, uncomprLen);
  565. {$ENDIF}
  566. comprLen := uncomprLen;
  567. {$IFDEF TEST_DICT}
  568. test_dict_deflate(compr, comprLen);
  569. test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
  570. {$ENDIF}
  571. readln;
  572. FreeMem(compr, comprLen*sizeof(cardinal));
  573. FreeMem(uncompr, uncomprLen*sizeof(cardinal));
  574. end.