example.pas 16 KB

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