license header and line ending fixups
[pngwrite.git] / zinflate.pas
1 Unit  zInflate;\r
2 \r
3 {  inflate.c -- zlib interface to inflate modules\r
4    Copyright (C) 1995-1998 Mark Adler\r
5 \r
6   Pascal tranlastion\r
7   Copyright (C) 1998 by Jacques Nomssi Nzali\r
8   For conditions of distribution and use, see copyright notice in readme.paszlib\r
9 }\r
10 \r
11 interface\r
12 \r
13 {$I zconf.inc}\r
14 \r
15 uses\r
16   zutil, zlib, infblock, infutil;\r
17 \r
18 function inflateInit(var z : z_stream) : int;\r
19 \r
20 {    Initializes the internal stream state for decompression. The fields\r
21    zalloc, zfree and opaque must be initialized before by the caller.  If\r
22    zalloc and zfree are set to Z_NULL, inflateInit updates them to use default\r
23    allocation functions.\r
24 \r
25      inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not\r
26    enough memory, Z_VERSION_ERROR if the zlib library version is incompatible\r
27    with the version assumed by the caller.  msg is set to null if there is no\r
28    error message. inflateInit does not perform any decompression: this will be\r
29    done by inflate(). }\r
30 \r
31 \r
32 \r
33 function inflateInit_(z : z_streamp;\r
34                       const version : string;\r
35                       stream_size : int) : int;\r
36 \r
37 \r
38 function inflateInit2_(var z: z_stream;\r
39                        w : int;\r
40                        const version : string;\r
41                        stream_size : int) : int;\r
42 \r
43 function inflateInit2(var z: z_stream;\r
44                        windowBits : int) : int;\r
45 \r
46 {\r
47      This is another version of inflateInit with an extra parameter. The\r
48    fields next_in, avail_in, zalloc, zfree and opaque must be initialized\r
49    before by the caller.\r
50 \r
51      The windowBits parameter is the base two logarithm of the maximum window\r
52    size (the size of the history buffer).  It should be in the range 8..15 for\r
53    this version of the library. The default value is 15 if inflateInit is used\r
54    instead. If a compressed stream with a larger window size is given as\r
55    input, inflate() will return with the error code Z_DATA_ERROR instead of\r
56    trying to allocate a larger window.\r
57 \r
58       inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough\r
59    memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative\r
60    memLevel). msg is set to null if there is no error message.  inflateInit2\r
61    does not perform any decompression apart from reading the zlib header if\r
62    present: this will be done by inflate(). (So next_in and avail_in may be\r
63    modified, but next_out and avail_out are unchanged.)\r
64 }\r
65 \r
66 \r
67 \r
68 function inflateEnd(var z : z_stream) : int;\r
69 \r
70 {\r
71    All dynamically allocated data structures for this stream are freed.\r
72    This function discards any unprocessed input and does not flush any\r
73    pending output.\r
74 \r
75      inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state\r
76    was inconsistent. In the error case, msg may be set but then points to a\r
77    static string (which must not be deallocated).\r
78 }\r
79 \r
80 function inflateReset(var z : z_stream) : int;\r
81 \r
82 {\r
83    This function is equivalent to inflateEnd followed by inflateInit,\r
84    but does not free and reallocate all the internal decompression state.\r
85    The stream will keep attributes that may have been set by inflateInit2.\r
86 \r
87       inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source\r
88    stream state was inconsistent (such as zalloc or state being NULL).\r
89 }\r
90 \r
91 \r
92 function inflate(var z : z_stream;\r
93                  f : int) : int;\r
94 {\r
95   inflate decompresses as much data as possible, and stops when the input\r
96   buffer becomes empty or the output buffer becomes full. It may introduce\r
97   some output latency (reading input without producing any output)\r
98   except when forced to flush.\r
99 \r
100   The detailed semantics are as follows. inflate performs one or both of the\r
101   following actions:\r
102 \r
103   - Decompress more input starting at next_in and update next_in and avail_in\r
104     accordingly. If not all input can be processed (because there is not\r
105     enough room in the output buffer), next_in is updated and processing\r
106     will resume at this point for the next call of inflate().\r
107 \r
108   - Provide more output starting at next_out and update next_out and avail_out\r
109     accordingly.  inflate() provides as much output as possible, until there\r
110     is no more input data or no more space in the output buffer (see below\r
111     about the flush parameter).\r
112 \r
113   Before the call of inflate(), the application should ensure that at least\r
114   one of the actions is possible, by providing more input and/or consuming\r
115   more output, and updating the next_* and avail_* values accordingly.\r
116   The application can consume the uncompressed output when it wants, for\r
117   example when the output buffer is full (avail_out == 0), or after each\r
118   call of inflate(). If inflate returns Z_OK and with zero avail_out, it\r
119   must be called again after making room in the output buffer because there\r
120   might be more output pending.\r
121 \r
122     If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much\r
123   output as possible to the output buffer. The flushing behavior of inflate is\r
124   not specified for values of the flush parameter other than Z_SYNC_FLUSH\r
125   and Z_FINISH, but the current implementation actually flushes as much output\r
126   as possible anyway.\r
127 \r
128     inflate() should normally be called until it returns Z_STREAM_END or an\r
129   error. However if all decompression is to be performed in a single step\r
130   (a single call of inflate), the parameter flush should be set to\r
131   Z_FINISH. In this case all pending input is processed and all pending\r
132   output is flushed; avail_out must be large enough to hold all the\r
133   uncompressed data. (The size of the uncompressed data may have been saved\r
134   by the compressor for this purpose.) The next operation on this stream must\r
135   be inflateEnd to deallocate the decompression state. The use of Z_FINISH\r
136   is never required, but can be used to inform inflate that a faster routine\r
137   may be used for the single inflate() call.\r
138 \r
139      If a preset dictionary is needed at this point (see inflateSetDictionary\r
140   below), inflate sets strm-adler to the adler32 checksum of the\r
141   dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise \r
142   it sets strm->adler to the adler32 checksum of all output produced\r
143   so far (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or\r
144   an error code as described below. At the end of the stream, inflate()\r
145   checks that its computed adler32 checksum is equal to that saved by the\r
146   compressor and returns Z_STREAM_END only if the checksum is correct.\r
147 \r
148     inflate() returns Z_OK if some progress has been made (more input processed\r
149   or more output produced), Z_STREAM_END if the end of the compressed data has\r
150   been reached and all uncompressed output has been produced, Z_NEED_DICT if a\r
151   preset dictionary is needed at this point, Z_DATA_ERROR if the input data was\r
152   corrupted (input stream not conforming to the zlib format or incorrect\r
153   adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent\r
154   (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not\r
155   enough memory, Z_BUF_ERROR if no progress is possible or if there was not\r
156   enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR\r
157   case, the application may then call inflateSync to look for a good\r
158   compression block.\r
159 }\r
160 \r
161 \r
162 function inflateSetDictionary(var z : z_stream;\r
163                               dictionary : pBytef; {const array of byte}\r
164                               dictLength : uInt) : int;\r
165 \r
166 {\r
167      Initializes the decompression dictionary from the given uncompressed byte\r
168    sequence. This function must be called immediately after a call of inflate\r
169    if this call returned Z_NEED_DICT. The dictionary chosen by the compressor\r
170    can be determined from the Adler32 value returned by this call of\r
171    inflate. The compressor and decompressor must use exactly the same\r
172    dictionary (see deflateSetDictionary).\r
173 \r
174      inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a\r
175    parameter is invalid (such as NULL dictionary) or the stream state is\r
176    inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the\r
177    expected one (incorrect Adler32 value). inflateSetDictionary does not\r
178    perform any decompression: this will be done by subsequent calls of\r
179    inflate().\r
180 }\r
181 \r
182 function inflateSync(var z : z_stream) : int;\r
183 \r
184 {\r
185   Skips invalid compressed data until a full flush point (see above the\r
186   description of deflate with Z_FULL_FLUSH) can be found, or until all\r
187   available input is skipped. No output is provided.\r
188 \r
189     inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR\r
190   if no more input was provided, Z_DATA_ERROR if no flush point has been found,\r
191   or Z_STREAM_ERROR if the stream structure was inconsistent. In the success\r
192   case, the application may save the current current value of total_in which\r
193   indicates where valid compressed data was found. In the error case, the\r
194   application may repeatedly call inflateSync, providing more input each time,\r
195   until success or end of the input data.\r
196 }\r
197 \r
198 \r
199 function inflateSyncPoint(var z : z_stream) : int;\r
200 \r
201 \r
202 implementation\r
203 \r
204 uses\r
205   adler;\r
206 \r
207 function inflateReset(var z : z_stream) : int;\r
208 begin\r
209   if (z.state = Z_NULL) then\r
210   begin\r
211     inflateReset :=  Z_STREAM_ERROR;\r
212     exit;\r
213   end;\r
214   z.total_out := 0;\r
215   z.total_in := 0;\r
216   z.msg := '';\r
217   if z.state^.nowrap then\r
218     z.state^.mode := BLOCKS\r
219   else\r
220     z.state^.mode := METHOD;\r
221   inflate_blocks_reset(z.state^.blocks^, z, Z_NULL);\r
222   {$IFDEF DEBUG}\r
223   Tracev('inflate: reset');\r
224   {$ENDIF}\r
225   inflateReset :=  Z_OK;\r
226 end;\r
227 \r
228 \r
229 function inflateEnd(var z : z_stream) : int;\r
230 begin\r
231   if (z.state = Z_NULL) or not Assigned(z.zfree) then\r
232   begin\r
233     inflateEnd :=  Z_STREAM_ERROR;\r
234     exit;\r
235   end;\r
236   if (z.state^.blocks <> Z_NULL) then\r
237     inflate_blocks_free(z.state^.blocks, z);\r
238   ZFREE(z, z.state);\r
239   z.state := Z_NULL;\r
240   {$IFDEF DEBUG}\r
241   Tracev('inflate: end');\r
242   {$ENDIF}\r
243   inflateEnd :=  Z_OK;\r
244 end;\r
245 \r
246 \r
247 function inflateInit2_(var z: z_stream;\r
248                        w : int;\r
249                        const version : string;\r
250                        stream_size : int) : int;\r
251 begin\r
252   if (version = '') or (version[1] <> ZLIB_VERSION[1]) or\r
253       (stream_size <> sizeof(z_stream)) then\r
254   begin\r
255     inflateInit2_ := Z_VERSION_ERROR;\r
256     exit;\r
257   end;\r
258   { initialize state }\r
259   { SetLength(strm.msg, 255); }\r
260   z.msg := '';\r
261   if not Assigned(z.zalloc) then\r
262   begin\r
263     {$IFDEF FPC}  z.zalloc := @zcalloc;  {$ELSE}\r
264     z.zalloc := zcalloc;\r
265     {$endif}\r
266     z.opaque := voidpf(0);\r
267   end;\r
268   if not Assigned(z.zfree) then\r
269     {$IFDEF FPC}  z.zfree := @zcfree;  {$ELSE}\r
270     z.zfree := zcfree;\r
271     {$ENDIF}\r
272 \r
273   z.state := pInternal_state( ZALLOC(z,1,sizeof(internal_state)) );\r
274   if (z.state = Z_NULL) then\r
275   begin\r
276     inflateInit2_ := Z_MEM_ERROR;\r
277     exit;\r
278   end;\r
279 \r
280   z.state^.blocks := Z_NULL;\r
281 \r
282   { handle undocumented nowrap option (no zlib header or check) }\r
283   z.state^.nowrap := FALSE;\r
284   if (w < 0) then\r
285   begin\r
286     w := - w;\r
287     z.state^.nowrap := TRUE;\r
288   end;\r
289 \r
290   { set window size }\r
291   if (w < 8) or (w > 15) then\r
292   begin\r
293     inflateEnd(z);\r
294     inflateInit2_ := Z_STREAM_ERROR;\r
295     exit;\r
296   end;\r
297   z.state^.wbits := uInt(w);\r
298 \r
299   { create inflate_blocks state }\r
300   if z.state^.nowrap then\r
301     z.state^.blocks := inflate_blocks_new(z, NIL, uInt(1) shl w)\r
302   else\r
303   {$IFDEF FPC}\r
304     z.state^.blocks := inflate_blocks_new(z, @adler32, uInt(1) shl w);\r
305   {$ELSE}\r
306     z.state^.blocks := inflate_blocks_new(z, adler32, uInt(1) shl w);\r
307   {$ENDIF}\r
308   if (z.state^.blocks = Z_NULL) then\r
309   begin\r
310     inflateEnd(z);\r
311     inflateInit2_ := Z_MEM_ERROR;\r
312     exit;\r
313   end;\r
314   {$IFDEF DEBUG}\r
315   Tracev('inflate: allocated');\r
316   {$ENDIF}\r
317   { reset state }\r
318   inflateReset(z);\r
319   inflateInit2_ :=  Z_OK;\r
320 end;\r
321 \r
322 function inflateInit2(var z: z_stream; windowBits : int) : int;\r
323 begin\r
324   inflateInit2 := inflateInit2_(z, windowBits, ZLIB_VERSION, sizeof(z_stream));\r
325 end;\r
326 \r
327 \r
328 function inflateInit(var z : z_stream) : int;\r
329 { inflateInit is a macro to allow checking the zlib version\r
330   and the compiler's view of z_stream:  }\r
331 begin\r
332   inflateInit := inflateInit2_(z, DEF_WBITS, ZLIB_VERSION, sizeof(z_stream));\r
333 end;\r
334 \r
335 function inflateInit_(z : z_streamp;\r
336                       const version : string;\r
337                       stream_size : int) : int;\r
338 begin\r
339   { initialize state }\r
340   if (z = Z_NULL) then\r
341     inflateInit_ := Z_STREAM_ERROR\r
342   else\r
343     inflateInit_ := inflateInit2_(z^, DEF_WBITS, version, stream_size);\r
344 end;\r
345 \r
346 function inflate(var z : z_stream;\r
347                  f : int) : int;\r
348 var\r
349   r : int;\r
350   b : uInt;\r
351 begin\r
352   if (z.state = Z_NULL) or (z.next_in = Z_NULL) then\r
353   begin\r
354     inflate := Z_STREAM_ERROR;\r
355     exit;\r
356   end;\r
357   if f = Z_FINISH then\r
358     f := Z_BUF_ERROR\r
359   else\r
360     f := Z_OK;\r
361   r := Z_BUF_ERROR;\r
362   while True do\r
363   case (z.state^.mode) of\r
364     BLOCKS:\r
365       begin\r
366         r := inflate_blocks(z.state^.blocks^, z, r);\r
367         if (r = Z_DATA_ERROR) then\r
368         begin\r
369           z.state^.mode := BAD;\r
370           z.state^.sub.marker := 0;       { can try inflateSync }\r
371           continue;            { break C-switch }\r
372         end;\r
373         if (r = Z_OK) then\r
374           r := f;\r
375         if (r <> Z_STREAM_END) then\r
376         begin\r
377           inflate := r;\r
378           exit;\r
379         end;\r
380         r := f;\r
381         inflate_blocks_reset(z.state^.blocks^, z, @z.state^.sub.check.was);\r
382         if (z.state^.nowrap) then\r
383         begin\r
384           z.state^.mode := DONE;\r
385           continue;            { break C-switch }\r
386         end;\r
387         z.state^.mode := CHECK4;  { falltrough }\r
388       end;\r
389     CHECK4:\r
390       begin\r
391         {NEEDBYTE}\r
392         if (z.avail_in = 0) then\r
393         begin\r
394           inflate := r;\r
395           exit;\r
396         end;\r
397         r := f;\r
398 \r
399         {z.state^.sub.check.need := uLong(NEXTBYTE(z)) shl 24;}\r
400         Dec(z.avail_in);\r
401         Inc(z.total_in);\r
402         z.state^.sub.check.need := uLong(z.next_in^) shl 24;\r
403         Inc(z.next_in);\r
404 \r
405         z.state^.mode := CHECK3;   { falltrough }\r
406       end;\r
407     CHECK3:\r
408       begin\r
409         {NEEDBYTE}\r
410         if (z.avail_in = 0) then\r
411         begin\r
412           inflate := r;\r
413           exit;\r
414         end;\r
415         r := f;\r
416         {Inc( z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 16);}\r
417         Dec(z.avail_in);\r
418         Inc(z.total_in);\r
419         Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 16);\r
420         Inc(z.next_in);\r
421 \r
422         z.state^.mode := CHECK2;   { falltrough }\r
423       end;\r
424     CHECK2:\r
425       begin\r
426         {NEEDBYTE}\r
427         if (z.avail_in = 0) then\r
428         begin\r
429           inflate := r;\r
430           exit;\r
431         end;\r
432         r := f;\r
433 \r
434         {Inc( z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 8);}\r
435         Dec(z.avail_in);\r
436         Inc(z.total_in);\r
437         Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 8);\r
438         Inc(z.next_in);\r
439 \r
440         z.state^.mode := CHECK1;   { falltrough }\r
441       end;\r
442     CHECK1:\r
443       begin\r
444         {NEEDBYTE}\r
445         if (z.avail_in = 0) then\r
446         begin\r
447           inflate := r;\r
448           exit;\r
449         end;\r
450         r := f;\r
451         {Inc( z.state^.sub.check.need, uLong(NEXTBYTE(z)) );}\r
452         Dec(z.avail_in);\r
453         Inc(z.total_in);\r
454         Inc(z.state^.sub.check.need, uLong(z.next_in^) );\r
455         Inc(z.next_in);\r
456 \r
457 \r
458         if (z.state^.sub.check.was <> z.state^.sub.check.need) then\r
459         begin\r
460           z.state^.mode := BAD;\r
461           z.msg := 'incorrect data check';\r
462           z.state^.sub.marker := 5;       { can't try inflateSync }\r
463           continue;           { break C-switch }\r
464         end;\r
465         {$IFDEF DEBUG}\r
466         Tracev('inflate: zlib check ok');\r
467         {$ENDIF}\r
468         z.state^.mode := DONE; { falltrough }\r
469       end;\r
470     DONE:\r
471       begin\r
472         inflate := Z_STREAM_END;\r
473         exit;\r
474       end;\r
475     METHOD:\r
476       begin\r
477         {NEEDBYTE}\r
478         if (z.avail_in = 0) then\r
479         begin\r
480           inflate := r;\r
481           exit;\r
482         end;\r
483         r := f; {}\r
484 \r
485         {z.state^.sub.method := NEXTBYTE(z);}\r
486         Dec(z.avail_in);\r
487         Inc(z.total_in);\r
488         z.state^.sub.method := z.next_in^;\r
489         Inc(z.next_in);\r
490 \r
491         if ((z.state^.sub.method and $0f) <> Z_DEFLATED) then\r
492         begin\r
493           z.state^.mode := BAD;\r
494           z.msg := 'unknown compression method';\r
495           z.state^.sub.marker := 5;       { can't try inflateSync }\r
496           continue;  { break C-switch }\r
497         end;\r
498         if ((z.state^.sub.method shr 4) + 8 > z.state^.wbits) then\r
499         begin\r
500           z.state^.mode := BAD;\r
501           z.msg := 'invalid window size';\r
502           z.state^.sub.marker := 5;       { can't try inflateSync }\r
503           continue; { break C-switch }\r
504         end;\r
505         z.state^.mode := FLAG;\r
506         { fall trough }\r
507       end;\r
508     FLAG:\r
509       begin\r
510         {NEEDBYTE}\r
511         if (z.avail_in = 0) then\r
512         begin\r
513           inflate := r;\r
514           exit;\r
515         end;\r
516         r := f; {}\r
517         {b := NEXTBYTE(z);}\r
518         Dec(z.avail_in);\r
519         Inc(z.total_in);\r
520         b := z.next_in^;\r
521         Inc(z.next_in);\r
522 \r
523         if (((z.state^.sub.method shl 8) + b) mod 31) <> 0 then {% mod ?}\r
524         begin\r
525           z.state^.mode := BAD;\r
526           z.msg := 'incorrect header check';\r
527           z.state^.sub.marker := 5;       { can't try inflateSync }\r
528           continue;      { break C-switch }\r
529         end;\r
530         {$IFDEF DEBUG}\r
531         Tracev('inflate: zlib header ok');\r
532         {$ENDIF}\r
533         if ((b and PRESET_DICT) = 0) then\r
534         begin\r
535           z.state^.mode := BLOCKS;\r
536           continue;      { break C-switch }\r
537         end;\r
538         z.state^.mode := DICT4;\r
539         { falltrough }\r
540       end;\r
541     DICT4:\r
542       begin\r
543         if (z.avail_in = 0) then\r
544         begin\r
545           inflate := r;\r
546           exit;\r
547         end;\r
548         r := f;\r
549 \r
550         {z.state^.sub.check.need := uLong(NEXTBYTE(z)) shl 24;}\r
551         Dec(z.avail_in);\r
552         Inc(z.total_in);\r
553         z.state^.sub.check.need :=  uLong(z.next_in^) shl 24;\r
554         Inc(z.next_in);\r
555 \r
556         z.state^.mode := DICT3;        { falltrough }\r
557       end;\r
558     DICT3:\r
559       begin\r
560         if (z.avail_in = 0) then\r
561         begin\r
562           inflate := r;\r
563           exit;\r
564         end;\r
565         r := f;\r
566         {Inc(z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 16);}\r
567         Dec(z.avail_in);\r
568         Inc(z.total_in);\r
569         Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 16);\r
570         Inc(z.next_in);\r
571 \r
572         z.state^.mode := DICT2;        { falltrough }\r
573       end;\r
574     DICT2:\r
575       begin\r
576         if (z.avail_in = 0) then\r
577         begin\r
578           inflate := r;\r
579           exit;\r
580         end;\r
581         r := f;\r
582 \r
583         {Inc(z.state^.sub.check.need, uLong(NEXTBYTE(z)) shl 8);}\r
584         Dec(z.avail_in);\r
585         Inc(z.total_in);\r
586         Inc(z.state^.sub.check.need, uLong(z.next_in^) shl 8);\r
587         Inc(z.next_in);\r
588 \r
589         z.state^.mode := DICT1;        { falltrough }\r
590       end;\r
591     DICT1:\r
592       begin\r
593         if (z.avail_in = 0) then\r
594         begin\r
595           inflate := r;\r
596           exit;\r
597         end;\r
598         { r := f;    ---  wird niemals benutzt }\r
599         {Inc(z.state^.sub.check.need, uLong(NEXTBYTE(z)) );}\r
600         Dec(z.avail_in);\r
601         Inc(z.total_in);\r
602         Inc(z.state^.sub.check.need, uLong(z.next_in^) );\r
603         Inc(z.next_in);\r
604 \r
605         z.adler := z.state^.sub.check.need;\r
606         z.state^.mode := DICT0;\r
607         inflate := Z_NEED_DICT;\r
608         exit;\r
609       end;\r
610     DICT0:\r
611       begin\r
612         z.state^.mode := BAD;\r
613         z.msg := 'need dictionary';\r
614         z.state^.sub.marker := 0;         { can try inflateSync }\r
615         inflate := Z_STREAM_ERROR;\r
616         exit;\r
617       end;\r
618     BAD:\r
619       begin\r
620         inflate := Z_DATA_ERROR;\r
621         exit;\r
622       end;\r
623     else\r
624       begin\r
625         inflate := Z_STREAM_ERROR;\r
626         exit;\r
627       end;\r
628   end;\r
629 {$ifdef NEED_DUMMY_result}\r
630   result := Z_STREAM_ERROR;  { Some dumb compilers complain without this }\r
631 {$endif}\r
632 end;\r
633 \r
634 function inflateSetDictionary(var z : z_stream;\r
635                               dictionary : pBytef; {const array of byte}\r
636                               dictLength : uInt) : int;\r
637 var\r
638   length : uInt;\r
639 begin\r
640   length := dictLength;\r
641 \r
642   if (z.state = Z_NULL) or (z.state^.mode <> DICT0) then\r
643   begin\r
644     inflateSetDictionary := Z_STREAM_ERROR;\r
645     exit;\r
646   end;\r
647   if (adler32(Long(1), dictionary, dictLength) <> z.adler) then\r
648   begin\r
649     inflateSetDictionary := Z_DATA_ERROR;\r
650     exit;\r
651   end;\r
652   z.adler := Long(1);\r
653 \r
654   if (length >= (uInt(1) shl z.state^.wbits)) then\r
655   begin\r
656     length := (1 shl z.state^.wbits)-1;\r
657     Inc( dictionary, dictLength - length);\r
658   end;\r
659   inflate_set_dictionary(z.state^.blocks^, dictionary^, length);\r
660   z.state^.mode := BLOCKS;\r
661   inflateSetDictionary := Z_OK;\r
662 end;\r
663 \r
664 \r
665 function inflateSync(var z : z_stream) : int;\r
666 const\r
667   mark : packed array[0..3] of byte = (0, 0, $ff, $ff);\r
668 var\r
669   n : uInt;       { number of bytes to look at }\r
670   p : pBytef;     { pointer to bytes }\r
671   m : uInt;       { number of marker bytes found in a row }\r
672   r, w : uLong;   { temporaries to save total_in and total_out }\r
673 begin\r
674   { set up }\r
675   if (z.state = Z_NULL) then\r
676   begin\r
677     inflateSync := Z_STREAM_ERROR;\r
678     exit;\r
679   end;\r
680   if (z.state^.mode <> BAD) then\r
681   begin\r
682     z.state^.mode := BAD;\r
683     z.state^.sub.marker := 0;\r
684   end;\r
685   n := z.avail_in;\r
686   if (n = 0) then\r
687   begin\r
688     inflateSync := Z_BUF_ERROR;\r
689     exit;\r
690   end;\r
691   p := z.next_in;\r
692   m := z.state^.sub.marker;\r
693 \r
694   { search }\r
695   while (n <> 0) and (m < 4) do\r
696   begin\r
697     if (p^ = mark[m]) then\r
698       Inc(m)\r
699     else\r
700       if (p^ <> 0) then\r
701         m := 0\r
702       else\r
703         m := 4 - m;\r
704     Inc(p);\r
705     Dec(n);\r
706   end;\r
707 \r
708   { restore }\r
709   Inc(z.total_in, ptr2int(p) - ptr2int(z.next_in));\r
710   z.next_in := p;\r
711   z.avail_in := n;\r
712   z.state^.sub.marker := m;\r
713 \r
714 \r
715   { return no joy or set up to restart on a new block }\r
716   if (m <> 4) then\r
717   begin\r
718     inflateSync := Z_DATA_ERROR;\r
719     exit;\r
720   end;\r
721   r := z.total_in;\r
722   w := z.total_out;\r
723   inflateReset(z);\r
724   z.total_in := r;\r
725   z.total_out := w;\r
726   z.state^.mode := BLOCKS;\r
727   inflateSync := Z_OK;\r
728 end;\r
729 \r
730 \r
731 {\r
732   returns true if inflate is currently at the end of a block generated\r
733   by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP\r
734   implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH\r
735   but removes the length bytes of the resulting empty stored block. When\r
736   decompressing, PPP checks that at the end of input packet, inflate is\r
737   waiting for these length bytes.\r
738 }\r
739 \r
740 function inflateSyncPoint(var z : z_stream) : int;\r
741 begin\r
742   if (z.state = Z_NULL) or (z.state^.blocks = Z_NULL) then\r
743   begin\r
744     inflateSyncPoint := Z_STREAM_ERROR;\r
745     exit;\r
746   end;\r
747   inflateSyncPoint := inflate_blocks_sync_point(z.state^.blocks^);\r
748 end;\r
749 \r
750 end.\r