Commit | Line | Data |
---|---|---|
25f0751f PM |
1 | /* Filename: Zlib.xs |
2 | * Author : Paul Marquess, <pmqs@cpan.org> | |
3 | * Created : 22nd January 1996 | |
4 | * Version : 2.000 | |
5 | * | |
9b5fd1d4 | 6 | * Copyright (c) 1995-2010 Paul Marquess. All rights reserved. |
25f0751f PM |
7 | * This program is free software; you can redistribute it and/or |
8 | * modify it under the same terms as Perl itself. | |
9 | * | |
10 | */ | |
11 | ||
12 | /* Parts of this code are based on the files gzio.c and gzappend.c from | |
13 | * the standard zlib source distribution. Below are the copyright statements | |
14 | * from each. | |
15 | */ | |
16 | ||
17 | /* gzio.c -- IO on .gz files | |
18 | * Copyright (C) 1995 Jean-loup Gailly. | |
19 | * For conditions of distribution and use, see copyright notice in zlib.h | |
20 | */ | |
21 | ||
22 | /* gzappend -- command to append to a gzip file | |
23 | ||
24 | Copyright (C) 2003 Mark Adler, all rights reserved | |
25 | version 1.1, 4 Nov 2003 | |
26 | */ | |
27 | ||
28 | ||
29 | ||
30 | #include "EXTERN.h" | |
31 | #include "perl.h" | |
32 | #include "XSUB.h" | |
33 | ||
f02c02ec | 34 | #include "zlib.h" |
25f0751f PM |
35 | |
36 | /* zlib prior to 1.06 doesn't know about z_off_t */ | |
37 | #ifndef z_off_t | |
38 | # define z_off_t long | |
39 | #endif | |
40 | ||
41 | #if ! defined(ZLIB_VERNUM) || ZLIB_VERNUM < 0x1200 | |
42 | # define NEED_DUMMY_BYTE_AT_END | |
43 | #endif | |
44 | ||
45 | #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1210 | |
46 | # define MAGIC_APPEND | |
589c1691 | 47 | # define AT_LEAST_ZLIB_1_2_1 |
25f0751f PM |
48 | #endif |
49 | ||
50 | #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1221 | |
51 | # define AT_LEAST_ZLIB_1_2_2_1 | |
52 | #endif | |
53 | ||
e11a3f9e PM |
54 | #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1222 |
55 | # define AT_LEAST_ZLIB_1_2_2_2 | |
56 | #endif | |
57 | ||
25f0751f PM |
58 | #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1223 |
59 | # define AT_LEAST_ZLIB_1_2_2_3 | |
60 | #endif | |
61 | ||
62 | #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1230 | |
63 | # define AT_LEAST_ZLIB_1_2_3 | |
64 | #endif | |
65 | ||
589c1691 CBW |
66 | #if defined(ZLIB_VERNUM) && ZLIB_VERNUM >= 0x1252 |
67 | /* | |
68 | Use Z_SOLO to build source means need own malloc/free | |
69 | */ | |
70 | # define AT_LEAST_ZLIB_1_2_5_2 | |
71 | #endif | |
72 | ||
9f44f717 JH |
73 | #ifdef USE_PPPORT_H |
74 | # define NEED_sv_2pvbyte | |
75 | # define NEED_sv_2pv_nolen | |
76 | # include "ppport.h" | |
77 | #endif | |
25f0751f | 78 | |
be714331 PM |
79 | #if PERL_REVISION == 5 && PERL_VERSION == 9 |
80 | /* For Andreas */ | |
81 | # define sv_pvbyte_force(sv,lp) sv_pvbyten_force(sv,lp) | |
82 | #endif | |
83 | ||
258133d1 | 84 | #if PERL_REVISION == 5 && (PERL_VERSION < 8 || (PERL_VERSION == 8 && PERL_SUBVERSION < 4 )) |
25f0751f PM |
85 | |
86 | # ifdef SvPVbyte_force | |
87 | # undef SvPVbyte_force | |
88 | # endif | |
89 | ||
90 | # define SvPVbyte_force(sv,lp) SvPV_force(sv,lp) | |
91 | ||
258133d1 | 92 | #endif |
25f0751f | 93 | |
258133d1 | 94 | #ifndef SvPVbyte_nolen |
25f0751f | 95 | # define SvPVbyte_nolen SvPV_nolen |
258133d1 | 96 | #endif |
25f0751f PM |
97 | |
98 | ||
25f0751f | 99 | |
258133d1 | 100 | #if 0 |
25f0751f PM |
101 | # ifndef SvPVbyte_nolen |
102 | # define SvPVbyte_nolen SvPV_nolen | |
103 | # endif | |
104 | ||
105 | # ifndef SvPVbyte_force | |
106 | # define SvPVbyte_force(sv,lp) SvPV_force(sv,lp) | |
107 | # endif | |
258133d1 | 108 | #endif |
25f0751f PM |
109 | |
110 | #if PERL_REVISION == 5 && (PERL_VERSION >= 8 || (PERL_VERSION == 8 && PERL_SUBVERSION < 4 )) | |
111 | # define UTF8_AVAILABLE | |
112 | #endif | |
113 | ||
114 | typedef int DualType ; | |
115 | typedef int int_undef ; | |
116 | ||
117 | typedef struct di_stream { | |
118 | int flags ; | |
119 | #define FLAG_APPEND 1 | |
120 | #define FLAG_CRC32 2 | |
121 | #define FLAG_ADLER32 4 | |
122 | #define FLAG_CONSUME_INPUT 8 | |
9253672d | 123 | #define FLAG_LIMIT_OUTPUT 16 |
25f0751f PM |
124 | uLong crc32 ; |
125 | uLong adler32 ; | |
126 | z_stream stream; | |
127 | uLong bufsize; | |
25f0751f PM |
128 | SV * dictionary ; |
129 | uLong dict_adler ; | |
130 | int last_error ; | |
131 | bool zip_mode ; | |
132 | #define SETP_BYTE | |
133 | #ifdef SETP_BYTE | |
134 | bool deflateParams_out_valid ; | |
135 | Bytef deflateParams_out_byte; | |
136 | #else | |
137 | #define deflateParams_BUFFER_SIZE 0x4000 | |
138 | uLong deflateParams_out_length; | |
139 | Bytef* deflateParams_out_buffer; | |
140 | #endif | |
141 | int Level; | |
142 | int Method; | |
143 | int WindowBits; | |
144 | int MemLevel; | |
145 | int Strategy; | |
146 | uLong bytesInflated ; | |
147 | uLong compressedBytes ; | |
148 | uLong uncompressedBytes ; | |
149 | #ifdef MAGIC_APPEND | |
150 | ||
151 | #define WINDOW_SIZE 32768U | |
152 | ||
153 | bool matchedEndBlock; | |
154 | Bytef* window ; | |
155 | int window_lastbit, window_left, window_full; | |
156 | unsigned window_have; | |
157 | off_t window_lastoff, window_end; | |
158 | off_t window_endOffset; | |
159 | ||
160 | uLong lastBlockOffset ; | |
161 | unsigned char window_lastByte ; | |
162 | ||
163 | ||
164 | #endif | |
165 | } di_stream; | |
166 | ||
167 | typedef di_stream * deflateStream ; | |
168 | typedef di_stream * Compress__Raw__Zlib__deflateStream ; | |
169 | typedef di_stream * inflateStream ; | |
170 | typedef di_stream * Compress__Raw__Zlib__inflateStream ; | |
171 | typedef di_stream * Compress__Raw__Zlib__inflateScanStream ; | |
172 | ||
25f0751f PM |
173 | #define ZMALLOC(to, typ) ((to = (typ *)safemalloc(sizeof(typ))), \ |
174 | Zero(to,1,typ)) | |
175 | ||
176 | /* Figure out the Operating System */ | |
177 | #ifdef MSDOS | |
178 | # define OS_CODE 0x00 | |
179 | #endif | |
180 | ||
181 | #if defined(AMIGA) || defined(AMIGAOS) | |
182 | # define OS_CODE 0x01 | |
183 | #endif | |
184 | ||
185 | #if defined(VAXC) || defined(VMS) | |
186 | # define OS_CODE 0x02 | |
187 | #endif | |
188 | ||
189 | #if 0 /* VM/CMS */ | |
190 | # define OS_CODE 0x04 | |
191 | #endif | |
192 | ||
193 | #if defined(ATARI) || defined(atarist) | |
194 | # define OS_CODE 0x05 | |
195 | #endif | |
196 | ||
197 | #ifdef OS2 | |
198 | # define OS_CODE 0x06 | |
199 | #endif | |
200 | ||
201 | #if defined(MACOS) || defined(TARGET_OS_MAC) | |
202 | # define OS_CODE 0x07 | |
203 | #endif | |
204 | ||
205 | #if 0 /* Z-System */ | |
206 | # define OS_CODE 0x08 | |
207 | #endif | |
208 | ||
209 | #if 0 /* CP/M */ | |
210 | # define OS_CODE 0x09 | |
211 | #endif | |
212 | ||
213 | #ifdef TOPS20 | |
214 | # define OS_CODE 0x0a | |
215 | #endif | |
216 | ||
217 | #ifdef WIN32 /* Window 95 & Windows NT */ | |
218 | # define OS_CODE 0x0b | |
219 | #endif | |
220 | ||
221 | #if 0 /* QDOS */ | |
222 | # define OS_CODE 0x0c | |
223 | #endif | |
224 | ||
225 | #if 0 /* Acorn RISCOS */ | |
226 | # define OS_CODE 0x0d | |
227 | #endif | |
228 | ||
229 | #if 0 /* ??? */ | |
230 | # define OS_CODE 0x0e | |
231 | #endif | |
232 | ||
233 | #ifdef __50SERIES /* Prime/PRIMOS */ | |
234 | # define OS_CODE 0x0F | |
235 | #endif | |
236 | ||
237 | /* Default to UNIX */ | |
238 | #ifndef OS_CODE | |
239 | # define OS_CODE 0x03 /* assume Unix */ | |
240 | #endif | |
241 | ||
242 | #ifndef GZIP_OS_CODE | |
243 | # define GZIP_OS_CODE OS_CODE | |
244 | #endif | |
245 | ||
246 | #define adlerInitial adler32(0L, Z_NULL, 0) | |
247 | #define crcInitial crc32(0L, Z_NULL, 0) | |
248 | ||
d5e10e57 | 249 | /* static const char * const my_z_errmsg[] = { */ |
d54256af | 250 | static const char my_z_errmsg[][32] = { |
25f0751f PM |
251 | "need dictionary", /* Z_NEED_DICT 2 */ |
252 | "stream end", /* Z_STREAM_END 1 */ | |
253 | "", /* Z_OK 0 */ | |
254 | "file error", /* Z_ERRNO (-1) */ | |
255 | "stream error", /* Z_STREAM_ERROR (-2) */ | |
256 | "data error", /* Z_DATA_ERROR (-3) */ | |
257 | "insufficient memory", /* Z_MEM_ERROR (-4) */ | |
258 | "buffer error", /* Z_BUF_ERROR (-5) */ | |
259 | "incompatible version",/* Z_VERSION_ERROR(-6) */ | |
260 | ""}; | |
261 | ||
262 | #define setDUALstatus(var, err) \ | |
263 | sv_setnv(var, (double)err) ; \ | |
264 | sv_setpv(var, ((err) ? GetErrorString(err) : "")) ; \ | |
265 | SvNOK_on(var); | |
266 | ||
267 | ||
268 | #if defined(__SYMBIAN32__) | |
269 | # define NO_WRITEABLE_DATA | |
270 | #endif | |
271 | ||
272 | #define TRACE_DEFAULT 0 | |
273 | ||
274 | #ifdef NO_WRITEABLE_DATA | |
275 | # define trace TRACE_DEFAULT | |
276 | #else | |
277 | static int trace = TRACE_DEFAULT ; | |
278 | #endif | |
279 | ||
280 | /* Dodge PerlIO hiding of these functions. */ | |
281 | #undef printf | |
282 | ||
283 | static char * | |
284 | #ifdef CAN_PROTOTYPE | |
285 | GetErrorString(int error_no) | |
286 | #else | |
287 | GetErrorString(error_no) | |
288 | int error_no ; | |
289 | #endif | |
290 | { | |
291 | dTHX; | |
292 | char * errstr ; | |
293 | ||
294 | if (error_no == Z_ERRNO) { | |
295 | errstr = Strerror(errno) ; | |
296 | } | |
297 | else | |
298 | /* errstr = gzerror(fil, &error_no) ; */ | |
299 | errstr = (char*) my_z_errmsg[2 - error_no]; | |
300 | ||
301 | return errstr ; | |
302 | } | |
303 | ||
25f0751f PM |
304 | |
305 | #ifdef MAGIC_APPEND | |
306 | ||
307 | /* | |
308 | The following two functions are taken almost directly from | |
309 | examples/gzappend.c. Only cosmetic changes have been made to conform to | |
310 | the coding style of the rest of the code in this file. | |
311 | */ | |
312 | ||
313 | ||
314 | /* return the greatest common divisor of a and b using Euclid's algorithm, | |
315 | modified to be fast when one argument much greater than the other, and | |
316 | coded to avoid unnecessary swapping */ | |
317 | static unsigned | |
318 | #ifdef CAN_PROTOTYPE | |
319 | gcd(unsigned a, unsigned b) | |
320 | #else | |
321 | gcd(a, b) | |
322 | unsigned a; | |
323 | unsigned b; | |
324 | #endif | |
325 | { | |
326 | unsigned c; | |
327 | ||
328 | while (a && b) | |
329 | if (a > b) { | |
330 | c = b; | |
331 | while (a - c >= c) | |
332 | c <<= 1; | |
333 | a -= c; | |
334 | } | |
335 | else { | |
336 | c = a; | |
337 | while (b - c >= c) | |
338 | c <<= 1; | |
339 | b -= c; | |
340 | } | |
341 | return a + b; | |
342 | } | |
343 | ||
344 | /* rotate list[0..len-1] left by rot positions, in place */ | |
345 | static void | |
346 | #ifdef CAN_PROTOTYPE | |
347 | rotate(unsigned char *list, unsigned len, unsigned rot) | |
348 | #else | |
349 | rotate(list, len, rot) | |
350 | unsigned char *list; | |
351 | unsigned len ; | |
352 | unsigned rot; | |
353 | #endif | |
354 | { | |
355 | unsigned char tmp; | |
356 | unsigned cycles; | |
357 | unsigned char *start, *last, *to, *from; | |
358 | ||
359 | /* normalize rot and handle degenerate cases */ | |
360 | if (len < 2) return; | |
361 | if (rot >= len) rot %= len; | |
362 | if (rot == 0) return; | |
363 | ||
364 | /* pointer to last entry in list */ | |
365 | last = list + (len - 1); | |
366 | ||
367 | /* do simple left shift by one */ | |
368 | if (rot == 1) { | |
369 | tmp = *list; | |
370 | memcpy(list, list + 1, len - 1); | |
371 | *last = tmp; | |
372 | return; | |
373 | } | |
374 | ||
375 | /* do simple right shift by one */ | |
376 | if (rot == len - 1) { | |
377 | tmp = *last; | |
378 | memmove(list + 1, list, len - 1); | |
379 | *list = tmp; | |
380 | return; | |
381 | } | |
382 | ||
383 | /* otherwise do rotate as a set of cycles in place */ | |
384 | cycles = gcd(len, rot); /* number of cycles */ | |
385 | do { | |
386 | start = from = list + cycles; /* start index is arbitrary */ | |
387 | tmp = *from; /* save entry to be overwritten */ | |
388 | for (;;) { | |
389 | to = from; /* next step in cycle */ | |
390 | from += rot; /* go right rot positions */ | |
391 | if (from > last) from -= len; /* (pointer better not wrap) */ | |
392 | if (from == start) break; /* all but one shifted */ | |
393 | *to = *from; /* shift left */ | |
394 | } | |
395 | *to = tmp; /* complete the circle */ | |
396 | } while (--cycles); | |
397 | } | |
398 | ||
399 | #endif /* MAGIC_APPEND */ | |
400 | ||
401 | static void | |
402 | #ifdef CAN_PROTOTYPE | |
403 | DispHex(void * ptr, int length) | |
404 | #else | |
405 | DispHex(ptr, length) | |
406 | void * ptr; | |
407 | int length; | |
408 | #endif | |
409 | { | |
410 | char * p = (char*)ptr; | |
411 | int i; | |
412 | for (i = 0; i < length; ++i) { | |
413 | printf(" %02x", 0xFF & *(p+i)); | |
414 | } | |
415 | } | |
416 | ||
417 | ||
418 | static void | |
419 | #ifdef CAN_PROTOTYPE | |
420 | DispStream(di_stream * s, char * message) | |
421 | #else | |
422 | DispStream(s, message) | |
423 | di_stream * s; | |
424 | char * message; | |
425 | #endif | |
426 | { | |
427 | ||
428 | #if 0 | |
429 | if (! trace) | |
430 | return ; | |
431 | #endif | |
432 | ||
433 | #define EnDis(f) (s->flags & f ? "Enabled" : "Disabled") | |
434 | ||
435 | printf("DispStream 0x%p", s) ; | |
436 | if (message) | |
437 | printf("- %s \n", message) ; | |
438 | printf("\n") ; | |
439 | ||
440 | if (!s) { | |
441 | printf(" stream pointer is NULL\n"); | |
442 | } | |
443 | else { | |
444 | printf(" stream 0x%p\n", &(s->stream)); | |
445 | printf(" zalloc 0x%p\n", s->stream.zalloc); | |
446 | printf(" zfree 0x%p\n", s->stream.zfree); | |
447 | printf(" opaque 0x%p\n", s->stream.opaque); | |
448 | if (s->stream.msg) | |
449 | printf(" msg %s\n", s->stream.msg); | |
450 | else | |
451 | printf(" msg \n"); | |
452 | printf(" next_in 0x%p", s->stream.next_in); | |
453 | if (s->stream.next_in){ | |
454 | printf(" =>"); | |
455 | DispHex(s->stream.next_in, 4); | |
456 | } | |
457 | printf("\n"); | |
458 | ||
459 | printf(" next_out 0x%p", s->stream.next_out); | |
460 | if (s->stream.next_out){ | |
461 | printf(" =>"); | |
462 | DispHex(s->stream.next_out, 4); | |
463 | } | |
464 | printf("\n"); | |
465 | ||
466 | printf(" avail_in %lu\n", (unsigned long)s->stream.avail_in); | |
467 | printf(" avail_out %lu\n", (unsigned long)s->stream.avail_out); | |
468 | printf(" total_in %ld\n", s->stream.total_in); | |
469 | printf(" total_out %ld\n", s->stream.total_out); | |
470 | printf(" adler %ld\n", s->stream.adler ); | |
471 | printf(" bufsize %ld\n", s->bufsize); | |
472 | printf(" dictionary 0x%p\n", s->dictionary); | |
473 | printf(" dict_adler 0x%ld\n",s->dict_adler); | |
474 | printf(" zip_mode %d\n", s->zip_mode); | |
475 | printf(" crc32 0x%x\n", (unsigned)s->crc32); | |
476 | printf(" adler32 0x%x\n", (unsigned)s->adler32); | |
477 | printf(" flags 0x%x\n", s->flags); | |
478 | printf(" APPEND %s\n", EnDis(FLAG_APPEND)); | |
479 | printf(" CRC32 %s\n", EnDis(FLAG_CRC32)); | |
480 | printf(" ADLER32 %s\n", EnDis(FLAG_ADLER32)); | |
481 | printf(" CONSUME %s\n", EnDis(FLAG_CONSUME_INPUT)); | |
9253672d SH |
482 | printf(" LIMIT %s\n", EnDis(FLAG_LIMIT_OUTPUT)); |
483 | ||
25f0751f PM |
484 | |
485 | #ifdef MAGIC_APPEND | |
486 | printf(" window 0x%p\n", s->window); | |
487 | #endif | |
488 | printf("\n"); | |
489 | ||
490 | } | |
491 | } | |
492 | ||
589c1691 CBW |
493 | #ifdef AT_LEAST_ZLIB_1_2_5_2 |
494 | voidpf my_zcalloc (voidpf opaque, unsigned items, unsigned size) | |
495 | { | |
496 | return safemalloc(items * size); | |
497 | } | |
498 | ||
499 | ||
500 | void my_zcfree (voidpf opaque, voidpf ptr) | |
501 | { | |
14c55418 A |
502 | safefree(ptr); |
503 | return; | |
589c1691 CBW |
504 | } |
505 | ||
506 | #endif | |
507 | ||
25f0751f PM |
508 | static di_stream * |
509 | #ifdef CAN_PROTOTYPE | |
510 | InitStream(void) | |
511 | #else | |
512 | InitStream() | |
513 | #endif | |
514 | { | |
515 | di_stream *s ; | |
516 | ||
517 | ZMALLOC(s, di_stream) ; | |
518 | ||
589c1691 CBW |
519 | #ifdef AT_LEAST_ZLIB_1_2_5_2 |
520 | s->stream.zalloc = my_zcalloc; | |
521 | s->stream.zfree = my_zcfree; | |
522 | #endif | |
523 | ||
25f0751f | 524 | return s ; |
25f0751f PM |
525 | } |
526 | ||
527 | static void | |
528 | #ifdef CAN_PROTOTYPE | |
529 | PostInitStream(di_stream * s, int flags, int bufsize, int windowBits) | |
530 | #else | |
531 | PostInitStream(s, flags, bufsize, windowBits) | |
532 | di_stream *s ; | |
533 | int flags ; | |
534 | int bufsize ; | |
535 | int windowBits ; | |
536 | #endif | |
537 | { | |
538 | s->bufsize = bufsize ; | |
25f0751f PM |
539 | s->compressedBytes = |
540 | s->uncompressedBytes = | |
541 | s->last_error = 0 ; | |
542 | s->flags = flags ; | |
543 | s->zip_mode = (windowBits < 0) ; | |
544 | if (flags & FLAG_CRC32) | |
545 | s->crc32 = crcInitial ; | |
546 | if (flags & FLAG_ADLER32) | |
547 | s->adler32 = adlerInitial ; | |
548 | } | |
549 | ||
550 | ||
551 | static SV* | |
552 | #ifdef CAN_PROTOTYPE | |
92905b42 | 553 | deRef(SV * sv, const char * string) |
25f0751f PM |
554 | #else |
555 | deRef(sv, string) | |
556 | SV * sv ; | |
557 | char * string; | |
558 | #endif | |
559 | { | |
560 | dTHX; | |
561 | SvGETMAGIC(sv); | |
562 | ||
563 | if (SvROK(sv)) { | |
564 | sv = SvRV(sv) ; | |
565 | SvGETMAGIC(sv); | |
566 | switch(SvTYPE(sv)) { | |
567 | case SVt_PVAV: | |
568 | case SVt_PVHV: | |
569 | case SVt_PVCV: | |
570 | croak("%s: buffer parameter is not a SCALAR reference", string); | |
776304fb PM |
571 | default: |
572 | break; | |
25f0751f PM |
573 | } |
574 | if (SvROK(sv)) | |
575 | croak("%s: buffer parameter is a reference to a reference", string) ; | |
576 | } | |
577 | ||
578 | if (!SvOK(sv)) { | |
579 | sv = newSVpv("", 0); | |
580 | } | |
581 | ||
582 | return sv ; | |
583 | } | |
584 | ||
585 | static SV* | |
586 | #ifdef CAN_PROTOTYPE | |
92905b42 | 587 | deRef_l(SV * sv, const char * string) |
25f0751f PM |
588 | #else |
589 | deRef_l(sv, string) | |
590 | SV * sv ; | |
591 | char * string ; | |
592 | #endif | |
593 | { | |
594 | dTHX; | |
595 | bool wipe = 0 ; | |
596 | ||
597 | SvGETMAGIC(sv); | |
598 | wipe = ! SvOK(sv) ; | |
599 | ||
600 | if (SvROK(sv)) { | |
601 | sv = SvRV(sv) ; | |
602 | SvGETMAGIC(sv); | |
603 | wipe = ! SvOK(sv) ; | |
604 | ||
605 | switch(SvTYPE(sv)) { | |
606 | case SVt_PVAV: | |
607 | case SVt_PVHV: | |
608 | case SVt_PVCV: | |
609 | croak("%s: buffer parameter is not a SCALAR reference", string); | |
776304fb PM |
610 | default: |
611 | break; | |
25f0751f PM |
612 | } |
613 | if (SvROK(sv)) | |
614 | croak("%s: buffer parameter is a reference to a reference", string) ; | |
615 | } | |
616 | ||
617 | if (SvREADONLY(sv) && PL_curcop != &PL_compiling) | |
618 | croak("%s: buffer parameter is read-only", string); | |
619 | ||
620 | SvUPGRADE(sv, SVt_PV); | |
621 | ||
622 | if (wipe) | |
623 | SvCUR_set(sv, 0); | |
624 | ||
625 | SvOOK_off(sv); | |
626 | SvPOK_only(sv); | |
627 | ||
628 | return sv ; | |
629 | } | |
630 | ||
631 | ||
632 | #include "constants.h" | |
633 | ||
634 | MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib PREFIX = Zip_ | |
635 | ||
636 | REQUIRE: 1.924 | |
637 | PROTOTYPES: DISABLE | |
638 | ||
639 | INCLUDE: constants.xs | |
640 | ||
641 | BOOT: | |
642 | /* Check this version of zlib is == 1 */ | |
643 | if (zlibVersion()[0] != '1') | |
644 | croak("Compress::Raw::Zlib needs zlib version 1.x\n") ; | |
645 | ||
646 | { | |
647 | /* Create the $os_code scalar */ | |
648 | SV * os_code_sv = perl_get_sv("Compress::Raw::Zlib::gzip_os_code", GV_ADDMULTI) ; | |
649 | sv_setiv(os_code_sv, GZIP_OS_CODE) ; | |
650 | } | |
651 | ||
652 | ||
d56f7e4c PM |
653 | #define Zip_zlib_version() (const char*)zlib_version |
654 | const char* | |
25f0751f PM |
655 | Zip_zlib_version() |
656 | ||
657 | unsigned | |
658 | ZLIB_VERNUM() | |
659 | CODE: | |
660 | #ifdef ZLIB_VERNUM | |
661 | RETVAL = ZLIB_VERNUM ; | |
662 | #else | |
663 | /* 1.1.4 => 0x1140 */ | |
664 | RETVAL = (ZLIB_VERSION[0] - '0') << 12 ; | |
665 | RETVAL += (ZLIB_VERSION[2] - '0') << 8 ; | |
666 | RETVAL += (ZLIB_VERSION[4] - '0') << 4 ; | |
589c1691 CBW |
667 | if (strlen(ZLIB_VERSION) > 5) |
668 | RETVAL += (ZLIB_VERSION[6] - '0') ; | |
25f0751f PM |
669 | #endif |
670 | OUTPUT: | |
671 | RETVAL | |
672 | ||
589c1691 CBW |
673 | |
674 | #ifndef AT_LEAST_ZLIB_1_2_1 | |
675 | #define zlibCompileFlags() 0 | |
676 | #endif | |
677 | uLong | |
678 | zlibCompileFlags() | |
679 | ||
25f0751f PM |
680 | MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib PREFIX = Zip_ |
681 | ||
682 | #define Zip_adler32(buf, adler) adler32(adler, buf, (uInt)len) | |
683 | ||
684 | uLong | |
685 | Zip_adler32(buf, adler=adlerInitial) | |
686 | uLong adler = NO_INIT | |
687 | STRLEN len = NO_INIT | |
688 | Bytef * buf = NO_INIT | |
689 | SV * sv = ST(0) ; | |
690 | INIT: | |
691 | /* If the buffer is a reference, dereference it */ | |
692 | sv = deRef(sv, "adler32") ; | |
693 | #ifdef UTF8_AVAILABLE | |
694 | if (DO_UTF8(sv) && !sv_utf8_downgrade(sv, 1)) | |
695 | croak("Wide character in Compress::Raw::Zlib::adler32"); | |
696 | #endif | |
697 | buf = (Byte*)SvPVbyte(sv, len) ; | |
698 | ||
699 | if (items < 2) | |
700 | adler = adlerInitial; | |
701 | else if (SvOK(ST(1))) | |
702 | adler = SvUV(ST(1)) ; | |
703 | else | |
704 | adler = adlerInitial; | |
d56f7e4c PM |
705 | OUTPUT: |
706 | RETVAL | |
25f0751f | 707 | |
bc771c2e | 708 | #define Zip_crc32(buf, crc, offset) crc32(crc, buf+offset, (uInt)len-offset) |
25f0751f PM |
709 | |
710 | uLong | |
bc771c2e | 711 | Zip_crc32(buf, crc=crcInitial, offset=0) |
25f0751f PM |
712 | uLong crc = NO_INIT |
713 | STRLEN len = NO_INIT | |
714 | Bytef * buf = NO_INIT | |
bc771c2e | 715 | int offset |
25f0751f PM |
716 | SV * sv = ST(0) ; |
717 | INIT: | |
718 | /* If the buffer is a reference, dereference it */ | |
719 | sv = deRef(sv, "crc32") ; | |
720 | #ifdef UTF8_AVAILABLE | |
721 | if (DO_UTF8(sv) && !sv_utf8_downgrade(sv, 1)) | |
722 | croak("Wide character in Compress::Raw::Zlib::crc32"); | |
723 | #endif | |
724 | buf = (Byte*)SvPVbyte(sv, len) ; | |
725 | ||
726 | if (items < 2) | |
727 | crc = crcInitial; | |
728 | else if (SvOK(ST(1))) | |
729 | crc = SvUV(ST(1)) ; | |
730 | else | |
731 | crc = crcInitial; | |
bc771c2e | 732 | |
25f0751f PM |
733 | uLong |
734 | crc32_combine(crc1, crc2, len2) | |
735 | uLong crc1 | |
736 | uLong crc2 | |
737 | z_off_t len2 | |
738 | CODE: | |
739 | #ifndef AT_LEAST_ZLIB_1_2_2_1 | |
740 | crc1 = crc1; crc2 = crc2 ; len2 = len2; /* Silence -Wall */ | |
741 | croak("crc32_combine needs zlib 1.2.3 or better"); | |
742 | #else | |
743 | RETVAL = crc32_combine(crc1, crc2, len2); | |
744 | #endif | |
745 | OUTPUT: | |
746 | RETVAL | |
747 | ||
748 | ||
749 | uLong | |
750 | adler32_combine(adler1, adler2, len2) | |
751 | uLong adler1 | |
752 | uLong adler2 | |
753 | z_off_t len2 | |
754 | CODE: | |
755 | #ifndef AT_LEAST_ZLIB_1_2_2_1 | |
756 | adler1 = adler1; adler2 = adler2 ; len2 = len2; /* Silence -Wall */ | |
757 | croak("adler32_combine needs zlib 1.2.3 or better"); | |
758 | #else | |
759 | RETVAL = adler32_combine(adler1, adler2, len2); | |
760 | #endif | |
761 | OUTPUT: | |
762 | RETVAL | |
763 | ||
764 | ||
765 | MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib | |
766 | ||
767 | void | |
768 | _deflateInit(flags,level, method, windowBits, memLevel, strategy, bufsize, dictionary) | |
769 | int flags | |
770 | int level | |
771 | int method | |
772 | int windowBits | |
773 | int memLevel | |
774 | int strategy | |
775 | uLong bufsize | |
776 | SV* dictionary | |
777 | PPCODE: | |
778 | int err ; | |
779 | deflateStream s ; | |
780 | ||
d56f7e4c PM |
781 | if (trace) |
782 | warn("in _deflateInit(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%ld dictionary=%p)\n", | |
783 | level, method, windowBits, memLevel, strategy, bufsize, dictionary) ; | |
25f0751f PM |
784 | if ((s = InitStream() )) { |
785 | ||
786 | s->Level = level; | |
787 | s->Method = method; | |
788 | s->WindowBits = windowBits; | |
789 | s->MemLevel = memLevel; | |
790 | s->Strategy = strategy; | |
791 | ||
792 | err = deflateInit2(&(s->stream), level, | |
793 | method, windowBits, memLevel, strategy); | |
794 | ||
589c1691 CBW |
795 | if (trace) |
796 | warn(" _deflateInit2 returned %d\n", err); | |
797 | ||
25f0751f PM |
798 | /* Check if a dictionary has been specified */ |
799 | ||
800 | if (err == Z_OK && SvCUR(dictionary)) { | |
801 | #ifdef UTF8_AVAILABLE | |
802 | if (DO_UTF8(dictionary) && !sv_utf8_downgrade(dictionary, 1)) | |
803 | croak("Wide character in Compress::Raw::Zlib::Deflate::new dicrionary parameter"); | |
804 | #endif | |
805 | err = deflateSetDictionary(&(s->stream), (const Bytef*) SvPVbyte_nolen(dictionary), | |
806 | SvCUR(dictionary)) ; | |
807 | s->dict_adler = s->stream.adler ; | |
808 | } | |
809 | ||
810 | if (err != Z_OK) { | |
811 | Safefree(s) ; | |
812 | s = NULL ; | |
813 | } | |
814 | else | |
815 | PostInitStream(s, flags, bufsize, windowBits) ; | |
816 | ||
817 | } | |
818 | else | |
819 | err = Z_MEM_ERROR ; | |
820 | ||
d56f7e4c PM |
821 | { |
822 | SV* obj = sv_setref_pv(sv_newmortal(), | |
823 | "Compress::Raw::Zlib::deflateStream", (void*)s); | |
824 | XPUSHs(obj); | |
825 | } | |
25f0751f PM |
826 | if (GIMME == G_ARRAY) { |
827 | SV * sv = sv_2mortal(newSViv(err)) ; | |
828 | setDUALstatus(sv, err); | |
829 | XPUSHs(sv) ; | |
830 | } | |
831 | ||
832 | void | |
833 | _inflateInit(flags, windowBits, bufsize, dictionary) | |
834 | int flags | |
835 | int windowBits | |
836 | uLong bufsize | |
837 | SV * dictionary | |
838 | ALIAS: | |
839 | _inflateScanInit = 1 | |
840 | PPCODE: | |
841 | ||
842 | int err = Z_OK ; | |
843 | inflateStream s ; | |
844 | #ifndef MAGIC_APPEND | |
845 | if (ix == 1) | |
846 | croak("inflateScanInit needs zlib 1.2.1 or better"); | |
847 | #endif | |
848 | if (trace) | |
849 | warn("in _inflateInit(windowBits=%d, bufsize=%lu, dictionary=%lu\n", | |
850 | windowBits, bufsize, (unsigned long)SvCUR(dictionary)) ; | |
851 | if ((s = InitStream() )) { | |
852 | ||
853 | s->WindowBits = windowBits; | |
854 | ||
855 | err = inflateInit2(&(s->stream), windowBits); | |
856 | if (err != Z_OK) { | |
857 | Safefree(s) ; | |
858 | s = NULL ; | |
859 | } | |
860 | else if (SvCUR(dictionary)) { | |
e11a3f9e PM |
861 | #ifdef AT_LEAST_ZLIB_1_2_2_1 |
862 | /* Zlib 1.2.2.1 or better allows a dictionary with raw inflate */ | |
863 | if (s->WindowBits < 0) { | |
864 | err = inflateSetDictionary(&(s->stream), | |
865 | (const Bytef*)SvPVbyte_nolen(dictionary), | |
866 | SvCUR(dictionary)); | |
867 | if (err != Z_OK) { | |
868 | Safefree(s) ; | |
869 | s = NULL ; | |
870 | } | |
871 | } | |
872 | else | |
873 | #endif | |
25f0751f PM |
874 | /* Dictionary specified - take a copy for use in inflate */ |
875 | s->dictionary = newSVsv(dictionary) ; | |
876 | } | |
877 | if (s) { | |
878 | PostInitStream(s, flags, bufsize, windowBits) ; | |
879 | #ifdef MAGIC_APPEND | |
880 | if (ix == 1) | |
881 | { | |
882 | s->window = (unsigned char *)safemalloc(WINDOW_SIZE); | |
883 | } | |
884 | #endif | |
885 | } | |
886 | } | |
887 | else | |
888 | err = Z_MEM_ERROR ; | |
889 | ||
d56f7e4c PM |
890 | { |
891 | SV* obj = sv_setref_pv(sv_newmortal(), | |
25f0751f PM |
892 | ix == 1 |
893 | ? "Compress::Raw::Zlib::inflateScanStream" | |
894 | : "Compress::Raw::Zlib::inflateStream", | |
d56f7e4c PM |
895 | (void*)s); |
896 | XPUSHs(obj); | |
897 | } | |
25f0751f PM |
898 | if (GIMME == G_ARRAY) { |
899 | SV * sv = sv_2mortal(newSViv(err)) ; | |
900 | setDUALstatus(sv, err); | |
901 | XPUSHs(sv) ; | |
902 | } | |
903 | ||
904 | ||
905 | ||
906 | MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib::deflateStream | |
907 | ||
908 | void | |
909 | DispStream(s, message=NULL) | |
910 | Compress::Raw::Zlib::deflateStream s | |
911 | char * message | |
912 | ||
913 | DualType | |
914 | deflateReset(s) | |
915 | Compress::Raw::Zlib::deflateStream s | |
916 | CODE: | |
917 | RETVAL = deflateReset(&(s->stream)) ; | |
918 | if (RETVAL == Z_OK) { | |
919 | PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ; | |
920 | } | |
921 | OUTPUT: | |
922 | RETVAL | |
923 | ||
924 | DualType | |
925 | deflate (s, buf, output) | |
926 | Compress::Raw::Zlib::deflateStream s | |
927 | SV * buf | |
928 | SV * output | |
929 | uInt cur_length = NO_INIT | |
930 | uInt increment = NO_INIT | |
931 | uInt prefix = NO_INIT | |
932 | int RETVAL = 0; | |
258133d1 | 933 | uLong bufinc = NO_INIT |
25f0751f | 934 | CODE: |
258133d1 | 935 | bufinc = s->bufsize; |
25f0751f PM |
936 | |
937 | /* If the input buffer is a reference, dereference it */ | |
938 | buf = deRef(buf, "deflate") ; | |
939 | ||
940 | /* initialise the input buffer */ | |
941 | #ifdef UTF8_AVAILABLE | |
942 | if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1)) | |
943 | croak("Wide character in Compress::Raw::Zlib::Deflate::deflate input parameter"); | |
944 | #endif | |
945 | s->stream.next_in = (Bytef*)SvPVbyte_nolen(buf) ; | |
946 | s->stream.avail_in = SvCUR(buf) ; | |
947 | ||
948 | if (s->flags & FLAG_CRC32) | |
949 | s->crc32 = crc32(s->crc32, s->stream.next_in, s->stream.avail_in) ; | |
950 | ||
951 | if (s->flags & FLAG_ADLER32) | |
952 | s->adler32 = adler32(s->adler32, s->stream.next_in, s->stream.avail_in) ; | |
953 | ||
954 | /* and retrieve the output buffer */ | |
955 | output = deRef_l(output, "deflate") ; | |
956 | #ifdef UTF8_AVAILABLE | |
957 | if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1)) | |
958 | croak("Wide character in Compress::Raw::Zlib::Deflate::deflate output parameter"); | |
959 | #endif | |
960 | ||
961 | if((s->flags & FLAG_APPEND) != FLAG_APPEND) { | |
962 | SvCUR_set(output, 0); | |
963 | /* sv_setpvn(output, "", 0); */ | |
964 | } | |
965 | prefix = cur_length = SvCUR(output) ; | |
966 | s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length; | |
967 | increment = SvLEN(output) - cur_length; | |
968 | s->stream.avail_out = increment; | |
969 | #ifdef SETP_BYTE | |
970 | /* Check for saved output from deflateParams */ | |
971 | if (s->deflateParams_out_valid) { | |
972 | *(s->stream.next_out) = s->deflateParams_out_byte; | |
973 | ++ s->stream.next_out; | |
974 | -- s->stream.avail_out ; | |
975 | s->deflateParams_out_valid = FALSE; | |
976 | } | |
977 | #else | |
978 | /* Check for saved output from deflateParams */ | |
979 | if (s->deflateParams_out_length) { | |
980 | uLong plen = s->deflateParams_out_length ; | |
981 | /* printf("Copy %d bytes saved data\n", plen);*/ | |
982 | if (s->stream.avail_out < plen) { | |
983 | /*printf("GROW from %d to %d\n", s->stream.avail_out, | |
984 | SvLEN(output) + plen - s->stream.avail_out); */ | |
985 | Sv_Grow(output, SvLEN(output) + plen - s->stream.avail_out) ; | |
986 | } | |
987 | ||
988 | Copy(s->stream.next_out, s->deflateParams_out_buffer, plen, Bytef) ; | |
989 | cur_length = cur_length + plen; | |
990 | SvCUR_set(output, cur_length); | |
991 | s->stream.next_out += plen ; | |
992 | s->stream.avail_out = SvLEN(output) - cur_length ; | |
993 | increment = s->stream.avail_out; | |
994 | s->deflateParams_out_length = 0; | |
995 | } | |
996 | #endif | |
997 | while (s->stream.avail_in != 0) { | |
998 | ||
999 | if (s->stream.avail_out == 0) { | |
1000 | /* out of space in the output buffer so make it bigger */ | |
258133d1 | 1001 | Sv_Grow(output, SvLEN(output) + bufinc) ; |
25f0751f PM |
1002 | cur_length += increment ; |
1003 | s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ; | |
258133d1 | 1004 | increment = bufinc ; |
25f0751f | 1005 | s->stream.avail_out = increment; |
258133d1 | 1006 | bufinc *= 2 ; |
25f0751f PM |
1007 | } |
1008 | ||
1009 | RETVAL = deflate(&(s->stream), Z_NO_FLUSH); | |
1010 | if (RETVAL != Z_OK) | |
1011 | break; | |
1012 | } | |
1013 | ||
1014 | s->compressedBytes += cur_length + increment - prefix - s->stream.avail_out ; | |
1015 | s->uncompressedBytes += SvCUR(buf) - s->stream.avail_in ; | |
1016 | ||
1017 | s->last_error = RETVAL ; | |
1018 | if (RETVAL == Z_OK) { | |
1019 | SvPOK_only(output); | |
1020 | SvCUR_set(output, cur_length + increment - s->stream.avail_out) ; | |
4e7676c7 | 1021 | SvSETMAGIC(output); |
25f0751f PM |
1022 | } |
1023 | OUTPUT: | |
1024 | RETVAL | |
25f0751f PM |
1025 | |
1026 | ||
1027 | void | |
1028 | DESTROY(s) | |
1029 | Compress::Raw::Zlib::deflateStream s | |
1030 | CODE: | |
1031 | deflateEnd(&s->stream) ; | |
1032 | if (s->dictionary) | |
1033 | SvREFCNT_dec(s->dictionary) ; | |
1034 | #ifndef SETP_BYTE | |
1035 | if (s->deflateParams_out_buffer) | |
1036 | Safefree(s->deflateParams_out_buffer); | |
1037 | #endif | |
1038 | Safefree(s) ; | |
1039 | ||
1040 | ||
1041 | DualType | |
1042 | flush(s, output, f=Z_FINISH) | |
1043 | Compress::Raw::Zlib::deflateStream s | |
1044 | SV * output | |
1045 | int f | |
1046 | uInt cur_length = NO_INIT | |
1047 | uInt increment = NO_INIT | |
1048 | uInt prefix = NO_INIT | |
258133d1 | 1049 | uLong bufinc = NO_INIT |
589c1691 | 1050 | uLong availableout = NO_INIT |
25f0751f | 1051 | CODE: |
258133d1 | 1052 | bufinc = s->bufsize; |
25f0751f PM |
1053 | |
1054 | s->stream.avail_in = 0; /* should be zero already anyway */ | |
1055 | ||
1056 | /* retrieve the output buffer */ | |
1057 | output = deRef_l(output, "flush") ; | |
1058 | #ifdef UTF8_AVAILABLE | |
1059 | if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1)) | |
1060 | croak("Wide character in Compress::Raw::Zlib::Deflate::flush input parameter"); | |
1061 | #endif | |
1062 | if(! s->flags & FLAG_APPEND) { | |
1063 | SvCUR_set(output, 0); | |
1064 | /* sv_setpvn(output, "", 0); */ | |
1065 | } | |
1066 | prefix = cur_length = SvCUR(output) ; | |
1067 | s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length; | |
1068 | increment = SvLEN(output) - cur_length; | |
1069 | s->stream.avail_out = increment; | |
1070 | #ifdef SETP_BYTE | |
1071 | /* Check for saved output from deflateParams */ | |
1072 | if (s->deflateParams_out_valid) { | |
1073 | *(s->stream.next_out) = s->deflateParams_out_byte; | |
1074 | ++ s->stream.next_out; | |
1075 | -- s->stream.avail_out ; | |
1076 | s->deflateParams_out_valid = FALSE; | |
1077 | } | |
1078 | #else | |
1079 | /* Check for saved output from deflateParams */ | |
1080 | if (s->deflateParams_out_length) { | |
1081 | uLong plen = s->deflateParams_out_length ; | |
1082 | /* printf("Copy %d bytes saved data\n", plen); */ | |
1083 | if (s->stream.avail_out < plen) { | |
1084 | /* printf("GROW from %d to %d\n", s->stream.avail_out, | |
1085 | SvLEN(output) + plen - s->stream.avail_out); */ | |
1086 | Sv_Grow(output, SvLEN(output) + plen - s->stream.avail_out) ; | |
1087 | } | |
1088 | ||
1089 | Copy(s->stream.next_out, s->deflateParams_out_buffer, plen, Bytef) ; | |
1090 | cur_length = cur_length + plen; | |
1091 | SvCUR_set(output, cur_length); | |
1092 | s->stream.next_out += plen ; | |
1093 | s->stream.avail_out = SvLEN(output) - cur_length ; | |
1094 | increment = s->stream.avail_out; | |
1095 | s->deflateParams_out_length = 0; | |
1096 | } | |
1097 | #endif | |
1098 | ||
1099 | for (;;) { | |
589c1691 CBW |
1100 | if (s->stream.avail_out == 0) { |
1101 | /* consumed all the available output, so extend it */ | |
258133d1 | 1102 | Sv_Grow(output, SvLEN(output) + bufinc) ; |
25f0751f PM |
1103 | cur_length += increment ; |
1104 | s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ; | |
258133d1 | 1105 | increment = bufinc ; |
25f0751f | 1106 | s->stream.avail_out = increment; |
258133d1 | 1107 | bufinc *= 2 ; |
25f0751f | 1108 | } |
589c1691 CBW |
1109 | |
1110 | availableout = s->stream.avail_out ; | |
1111 | ||
25f0751f PM |
1112 | RETVAL = deflate(&(s->stream), f); |
1113 | ||
589c1691 CBW |
1114 | /* Ignore the second of two consecutive flushes: */ |
1115 | if (availableout == s->stream.avail_out && RETVAL == Z_BUF_ERROR) | |
1116 | RETVAL = Z_OK; | |
1117 | ||
25f0751f PM |
1118 | /* deflate has finished flushing only when it hasn't used up |
1119 | * all the available space in the output buffer: | |
1120 | */ | |
1121 | if (s->stream.avail_out != 0 || RETVAL != Z_OK ) | |
1122 | break; | |
1123 | } | |
1124 | ||
1125 | RETVAL = (RETVAL == Z_STREAM_END ? Z_OK : RETVAL) ; | |
1126 | s->last_error = RETVAL ; | |
1127 | ||
1128 | s->compressedBytes += cur_length + increment - prefix - s->stream.avail_out ; | |
1129 | ||
1130 | if (RETVAL == Z_OK) { | |
1131 | SvPOK_only(output); | |
1132 | SvCUR_set(output, cur_length + increment - s->stream.avail_out) ; | |
4e7676c7 | 1133 | SvSETMAGIC(output); |
25f0751f PM |
1134 | } |
1135 | OUTPUT: | |
1136 | RETVAL | |
25f0751f PM |
1137 | |
1138 | ||
1139 | DualType | |
1140 | _deflateParams(s, flags, level, strategy, bufsize) | |
1141 | Compress::Raw::Zlib::deflateStream s | |
1142 | int flags | |
1143 | int level | |
1144 | int strategy | |
1145 | uLong bufsize | |
1146 | CODE: | |
1147 | /* printf("_deflateParams(Flags %d Level %d Strategy %d Bufsize %d)\n", flags, level, strategy, bufsize); | |
1148 | printf("Before -- Level %d, Strategy %d, Bufsize %d\n", s->Level, s->Strategy, s->bufsize); */ | |
1149 | if (flags & 1) | |
1150 | s->Level = level ; | |
1151 | if (flags & 2) | |
1152 | s->Strategy = strategy ; | |
1153 | if (flags & 4) { | |
1154 | s->bufsize = bufsize; | |
25f0751f PM |
1155 | } |
1156 | /* printf("After -- Level %d, Strategy %d, Bufsize %d\n", s->Level, s->Strategy, s->bufsize);*/ | |
1157 | #ifdef SETP_BYTE | |
1158 | s->stream.avail_in = 0; | |
1159 | s->stream.next_out = &(s->deflateParams_out_byte) ; | |
1160 | s->stream.avail_out = 1; | |
1161 | RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy); | |
1162 | s->deflateParams_out_valid = | |
1163 | (RETVAL == Z_OK && s->stream.avail_out == 0) ; | |
1164 | /* printf("RETVAL %d, avail out %d, byte %c\n", RETVAL, s->stream.avail_out, s->deflateParams_out_byte); */ | |
1165 | #else | |
1166 | /* printf("Level %d Strategy %d, Prev Len %d\n", | |
1167 | s->Level, s->Strategy, s->deflateParams_out_length); */ | |
1168 | s->stream.avail_in = 0; | |
1169 | if (s->deflateParams_out_buffer == NULL) | |
1170 | s->deflateParams_out_buffer = safemalloc(deflateParams_BUFFER_SIZE); | |
1171 | s->stream.next_out = s->deflateParams_out_buffer ; | |
1172 | s->stream.avail_out = deflateParams_BUFFER_SIZE; | |
1173 | ||
1174 | RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy); | |
1175 | s->deflateParams_out_length = deflateParams_BUFFER_SIZE - s->stream.avail_out; | |
1176 | /* printf("RETVAL %d, length out %d, avail %d\n", | |
1177 | RETVAL, s->deflateParams_out_length, s->stream.avail_out ); */ | |
1178 | #endif | |
1179 | OUTPUT: | |
1180 | RETVAL | |
1181 | ||
1182 | ||
1183 | int | |
1184 | get_Level(s) | |
1185 | Compress::Raw::Zlib::deflateStream s | |
1186 | CODE: | |
1187 | RETVAL = s->Level ; | |
1188 | OUTPUT: | |
1189 | RETVAL | |
1190 | ||
1191 | int | |
1192 | get_Strategy(s) | |
1193 | Compress::Raw::Zlib::deflateStream s | |
1194 | CODE: | |
1195 | RETVAL = s->Strategy ; | |
1196 | OUTPUT: | |
1197 | RETVAL | |
1198 | ||
1199 | ||
1200 | uLong | |
1201 | get_Bufsize(s) | |
1202 | Compress::Raw::Zlib::deflateStream s | |
1203 | CODE: | |
1204 | RETVAL = s->bufsize ; | |
1205 | OUTPUT: | |
1206 | RETVAL | |
1207 | ||
1208 | ||
1209 | int | |
1210 | status(s) | |
1211 | Compress::Raw::Zlib::deflateStream s | |
1212 | CODE: | |
1213 | RETVAL = s->last_error ; | |
1214 | OUTPUT: | |
1215 | RETVAL | |
1216 | ||
1217 | uLong | |
1218 | crc32(s) | |
1219 | Compress::Raw::Zlib::deflateStream s | |
1220 | CODE: | |
1221 | RETVAL = s->crc32 ; | |
1222 | OUTPUT: | |
1223 | RETVAL | |
1224 | ||
1225 | uLong | |
1226 | dict_adler(s) | |
1227 | Compress::Raw::Zlib::deflateStream s | |
1228 | CODE: | |
1229 | RETVAL = s->dict_adler ; | |
1230 | OUTPUT: | |
1231 | RETVAL | |
1232 | ||
1233 | uLong | |
1234 | adler32(s) | |
1235 | Compress::Raw::Zlib::deflateStream s | |
1236 | CODE: | |
1237 | RETVAL = s->adler32 ; | |
1238 | OUTPUT: | |
1239 | RETVAL | |
1240 | ||
1241 | uLong | |
1242 | compressedBytes(s) | |
1243 | Compress::Raw::Zlib::deflateStream s | |
1244 | CODE: | |
1245 | RETVAL = s->compressedBytes; | |
1246 | OUTPUT: | |
1247 | RETVAL | |
1248 | ||
1249 | uLong | |
1250 | uncompressedBytes(s) | |
1251 | Compress::Raw::Zlib::deflateStream s | |
1252 | CODE: | |
1253 | RETVAL = s->uncompressedBytes; | |
1254 | OUTPUT: | |
1255 | RETVAL | |
1256 | ||
1257 | uLong | |
1258 | total_in(s) | |
1259 | Compress::Raw::Zlib::deflateStream s | |
1260 | CODE: | |
1261 | RETVAL = s->stream.total_in ; | |
1262 | OUTPUT: | |
1263 | RETVAL | |
1264 | ||
1265 | uLong | |
1266 | total_out(s) | |
1267 | Compress::Raw::Zlib::deflateStream s | |
1268 | CODE: | |
1269 | RETVAL = s->stream.total_out ; | |
1270 | OUTPUT: | |
1271 | RETVAL | |
1272 | ||
1273 | char* | |
1274 | msg(s) | |
1275 | Compress::Raw::Zlib::deflateStream s | |
1276 | CODE: | |
1277 | RETVAL = s->stream.msg; | |
1278 | OUTPUT: | |
1279 | RETVAL | |
1280 | ||
1281 | int | |
1282 | deflateTune(s, good_length, max_lazy, nice_length, max_chain) | |
1283 | Compress::Raw::Zlib::deflateStream s | |
1284 | int good_length | |
1285 | int max_lazy | |
1286 | int nice_length | |
1287 | int max_chain | |
1288 | CODE: | |
1289 | #ifndef AT_LEAST_ZLIB_1_2_2_3 | |
1290 | good_length = good_length; max_lazy = max_lazy ; /* Silence -Wall */ | |
1291 | nice_length = nice_length; max_chain = max_chain; /* Silence -Wall */ | |
1292 | croak("deflateTune needs zlib 1.2.2.3 or better"); | |
1293 | #else | |
1294 | RETVAL = deflateTune(&(s->stream), good_length, max_lazy, nice_length, max_chain); | |
1295 | #endif | |
1296 | OUTPUT: | |
1297 | RETVAL | |
1298 | ||
1299 | ||
1300 | MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib::inflateStream | |
1301 | ||
1302 | void | |
1303 | DispStream(s, message=NULL) | |
1304 | Compress::Raw::Zlib::inflateStream s | |
1305 | char * message | |
1306 | ||
1307 | DualType | |
1308 | inflateReset(s) | |
1309 | Compress::Raw::Zlib::inflateStream s | |
1310 | CODE: | |
1311 | RETVAL = inflateReset(&(s->stream)) ; | |
1312 | if (RETVAL == Z_OK) { | |
1313 | PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ; | |
1314 | } | |
1315 | OUTPUT: | |
1316 | RETVAL | |
1317 | ||
1318 | DualType | |
1319 | inflate (s, buf, output, eof=FALSE) | |
1320 | Compress::Raw::Zlib::inflateStream s | |
1321 | SV * buf | |
1322 | SV * output | |
1323 | bool eof | |
1324 | uInt cur_length = 0; | |
1325 | uInt prefix_length = 0; | |
319fab50 | 1326 | int increment = 0; |
25f0751f | 1327 | STRLEN stmp = NO_INIT |
258133d1 | 1328 | uLong bufinc = NO_INIT |
25f0751f PM |
1329 | PREINIT: |
1330 | #ifdef UTF8_AVAILABLE | |
1331 | bool out_utf8 = FALSE; | |
1332 | #endif | |
1333 | CODE: | |
258133d1 | 1334 | bufinc = s->bufsize; |
25f0751f PM |
1335 | /* If the buffer is a reference, dereference it */ |
1336 | buf = deRef(buf, "inflate") ; | |
1337 | ||
1338 | if (s->flags & FLAG_CONSUME_INPUT && SvREADONLY(buf)) | |
1339 | croak("Compress::Raw::Zlib::Inflate::inflate input parameter cannot be read-only when ConsumeInput is specified"); | |
1340 | #ifdef UTF8_AVAILABLE | |
1341 | if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1)) | |
1342 | croak("Wide character in Compress::Raw::Zlib::Inflate::inflate input parameter"); | |
1343 | #endif | |
1344 | ||
1345 | /* initialise the input buffer */ | |
1346 | s->stream.next_in = (Bytef*)SvPVbyte_force(buf, stmp) ; | |
1347 | s->stream.avail_in = SvCUR(buf) ; | |
1348 | ||
1349 | /* and retrieve the output buffer */ | |
1350 | output = deRef_l(output, "inflate") ; | |
1351 | #ifdef UTF8_AVAILABLE | |
1352 | if (DO_UTF8(output)) | |
1353 | out_utf8 = TRUE ; | |
1354 | if (DO_UTF8(output) && !sv_utf8_downgrade(output, 1)) | |
1355 | croak("Wide character in Compress::Raw::Zlib::Inflate::inflate output parameter"); | |
1356 | #endif | |
1357 | if((s->flags & FLAG_APPEND) != FLAG_APPEND) { | |
1358 | SvCUR_set(output, 0); | |
1359 | } | |
319fab50 PM |
1360 | |
1361 | /* Assume no output buffer - the code below will update if there is any available */ | |
1362 | s->stream.avail_out = 0; | |
1363 | ||
1364 | ||
25f0751f PM |
1365 | if (SvLEN(output)) { |
1366 | prefix_length = cur_length = SvCUR(output) ; | |
319fab50 PM |
1367 | |
1368 | if (s->flags & FLAG_LIMIT_OUTPUT && SvLEN(output) - cur_length - 1 < bufinc) | |
1369 | { | |
1370 | Sv_Grow(output, bufinc + cur_length + 1) ; | |
1371 | } | |
1372 | ||
1373 | /* Only setup the stream output pointers if there is spare | |
1374 | capacity in the outout SV | |
1375 | */ | |
1376 | if (SvLEN(output) > cur_length + 1) | |
1377 | { | |
1378 | s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length; | |
1379 | increment = SvLEN(output) - cur_length - 1; | |
1380 | s->stream.avail_out = increment; | |
1381 | } | |
25f0751f | 1382 | } |
319fab50 PM |
1383 | |
1384 | ||
25f0751f PM |
1385 | s->bytesInflated = 0; |
1386 | ||
e11a3f9e | 1387 | RETVAL = Z_OK; |
25f0751f | 1388 | |
e11a3f9e | 1389 | while (RETVAL == Z_OK) { |
319fab50 | 1390 | if (s->stream.avail_out == 0) { |
25f0751f | 1391 | /* out of space in the output buffer so make it bigger */ |
7efcbeef | 1392 | Sv_Grow(output, SvLEN(output) + bufinc +1) ; |
25f0751f PM |
1393 | cur_length += increment ; |
1394 | s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ; | |
258133d1 | 1395 | increment = bufinc ; |
25f0751f | 1396 | s->stream.avail_out = increment; |
258133d1 | 1397 | bufinc *= 2 ; |
25f0751f PM |
1398 | } |
1399 | ||
319fab50 PM |
1400 | /* printf("INFLATE Availl In %d, Out %d\n", s->stream.avail_in, |
1401 | s->stream.avail_out); | |
1402 | DispStream(s, "BEFORE"); | |
1403 | Perl_sv_dump(output); */ | |
25f0751f | 1404 | RETVAL = inflate(&(s->stream), Z_SYNC_FLUSH); |
319fab50 PM |
1405 | /* printf("INFLATE returned %d %s, avail in %d, out %d\n", RETVAL, |
1406 | GetErrorString(RETVAL), s->stream.avail_in, s->stream.avail_out); */ | |
25f0751f | 1407 | |
9253672d SH |
1408 | |
1409 | if (RETVAL == Z_NEED_DICT && s->dictionary) { | |
1410 | s->dict_adler = s->stream.adler ; | |
1411 | RETVAL = inflateSetDictionary(&(s->stream), | |
1412 | (const Bytef*)SvPVbyte_nolen(s->dictionary), | |
1413 | SvCUR(s->dictionary)); | |
319fab50 PM |
1414 | if (RETVAL == Z_OK) |
1415 | continue; | |
9253672d SH |
1416 | } |
1417 | ||
319fab50 PM |
1418 | if (s->flags & FLAG_LIMIT_OUTPUT && |
1419 | (RETVAL == Z_OK || RETVAL == Z_BUF_ERROR )) | |
1420 | break; | |
1421 | ||
1422 | if (RETVAL == Z_STREAM_ERROR || RETVAL == Z_MEM_ERROR || | |
1423 | RETVAL == Z_DATA_ERROR || RETVAL == Z_STREAM_END ) | |
25f0751f PM |
1424 | break ; |
1425 | ||
1426 | if (RETVAL == Z_BUF_ERROR) { | |
1427 | if (s->stream.avail_out == 0) | |
1428 | continue ; | |
1429 | if (s->stream.avail_in == 0) { | |
1430 | RETVAL = Z_OK ; | |
1431 | break ; | |
1432 | } | |
1433 | } | |
25f0751f PM |
1434 | } |
1435 | #ifdef NEED_DUMMY_BYTE_AT_END | |
9253672d | 1436 | if (eof && RETVAL == Z_OK && s->flags & FLAG_LIMIT_OUTPUT == 0) { |
25f0751f PM |
1437 | Bytef* nextIn = s->stream.next_in; |
1438 | uInt availIn = s->stream.avail_in; | |
1439 | s->stream.next_in = (Bytef*) " "; | |
1440 | s->stream.avail_in = 1; | |
1441 | if (s->stream.avail_out == 0) { | |
1442 | /* out of space in the output buffer so make it bigger */ | |
258133d1 | 1443 | Sv_Grow(output, SvLEN(output) + bufinc) ; |
25f0751f PM |
1444 | cur_length += increment ; |
1445 | s->stream.next_out = (Bytef*) SvPVbyte_nolen(output) + cur_length ; | |
258133d1 | 1446 | increment = bufinc ; |
25f0751f | 1447 | s->stream.avail_out = increment; |
258133d1 | 1448 | bufinc *= 2 ; |
25f0751f PM |
1449 | } |
1450 | RETVAL = inflate(&(s->stream), Z_SYNC_FLUSH); | |
1451 | s->stream.next_in = nextIn ; | |
1452 | s->stream.avail_in = availIn ; | |
1453 | } | |
1454 | #endif | |
1455 | ||
1456 | s->last_error = RETVAL ; | |
319fab50 PM |
1457 | if (RETVAL == Z_OK || RETVAL == Z_STREAM_END || RETVAL == Z_BUF_ERROR || RETVAL == Z_DATA_ERROR) { |
1458 | unsigned in ; | |
25f0751f PM |
1459 | |
1460 | s->bytesInflated = cur_length + increment - s->stream.avail_out - prefix_length; | |
1461 | s->uncompressedBytes += s->bytesInflated ; | |
1462 | s->compressedBytes += SvCUR(buf) - s->stream.avail_in ; | |
1463 | ||
1464 | SvPOK_only(output); | |
1465 | SvCUR_set(output, prefix_length + s->bytesInflated) ; | |
1466 | *SvEND(output) = '\0'; | |
1467 | #ifdef UTF8_AVAILABLE | |
1468 | if (out_utf8) | |
1469 | sv_utf8_upgrade(output); | |
1470 | #endif | |
4e7676c7 | 1471 | SvSETMAGIC(output); |
25f0751f PM |
1472 | |
1473 | if (s->flags & FLAG_CRC32 ) | |
1474 | s->crc32 = crc32(s->crc32, | |
1475 | (const Bytef*)SvPVbyte_nolen(output)+prefix_length, | |
1476 | SvCUR(output)-prefix_length) ; | |
1477 | ||
1478 | if (s->flags & FLAG_ADLER32) | |
1479 | s->adler32 = adler32(s->adler32, | |
1480 | (const Bytef*)SvPVbyte_nolen(output)+prefix_length, | |
1481 | SvCUR(output)-prefix_length) ; | |
1482 | ||
1483 | /* fix the input buffer */ | |
9253672d | 1484 | if (s->flags & FLAG_CONSUME_INPUT || s->flags & FLAG_LIMIT_OUTPUT) { |
25f0751f PM |
1485 | in = s->stream.avail_in ; |
1486 | SvCUR_set(buf, in) ; | |
1487 | if (in) | |
1488 | Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ; | |
1489 | *SvEND(buf) = '\0'; | |
1490 | SvSETMAGIC(buf); | |
1491 | } | |
319fab50 | 1492 | |
25f0751f PM |
1493 | } |
1494 | OUTPUT: | |
1495 | RETVAL | |
25f0751f PM |
1496 | |
1497 | uLong | |
1498 | inflateCount(s) | |
1499 | Compress::Raw::Zlib::inflateStream s | |
1500 | CODE: | |
1501 | RETVAL = s->bytesInflated; | |
1502 | OUTPUT: | |
1503 | RETVAL | |
1504 | ||
1505 | uLong | |
1506 | compressedBytes(s) | |
1507 | Compress::Raw::Zlib::inflateStream s | |
1508 | CODE: | |
1509 | RETVAL = s->compressedBytes; | |
1510 | OUTPUT: | |
1511 | RETVAL | |
1512 | ||
1513 | uLong | |
1514 | uncompressedBytes(s) | |
1515 | Compress::Raw::Zlib::inflateStream s | |
1516 | CODE: | |
1517 | RETVAL = s->uncompressedBytes; | |
1518 | OUTPUT: | |
1519 | RETVAL | |
1520 | ||
1521 | ||
1522 | DualType | |
1523 | inflateSync (s, buf) | |
1524 | Compress::Raw::Zlib::inflateStream s | |
1525 | SV * buf | |
1526 | CODE: | |
1527 | ||
1528 | /* If the buffer is a reference, dereference it */ | |
1529 | buf = deRef(buf, "inflateSync") ; | |
1530 | #ifdef UTF8_AVAILABLE | |
1531 | if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1)) | |
1532 | croak("Wide character in Compress::Raw::Zlib::Inflate::inflateSync"); | |
1533 | #endif | |
1534 | ||
1535 | /* initialise the input buffer */ | |
1536 | s->stream.next_in = (Bytef*)SvPVbyte_nolen(buf) ; | |
1537 | s->stream.avail_in = SvCUR(buf) ; | |
1538 | ||
1539 | /* inflateSync doesn't create any output */ | |
1540 | s->stream.next_out = (Bytef*) NULL; | |
1541 | s->stream.avail_out = 0; | |
1542 | ||
1543 | RETVAL = inflateSync(&(s->stream)); | |
1544 | s->last_error = RETVAL ; | |
1545 | ||
1546 | /* fix the input buffer */ | |
1547 | { | |
1548 | unsigned in = s->stream.avail_in ; | |
1549 | SvCUR_set(buf, in) ; | |
1550 | if (in) | |
1551 | Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ; | |
1552 | *SvEND(buf) = '\0'; | |
1553 | SvSETMAGIC(buf); | |
1554 | } | |
1555 | OUTPUT: | |
1556 | RETVAL | |
25f0751f PM |
1557 | |
1558 | void | |
1559 | DESTROY(s) | |
1560 | Compress::Raw::Zlib::inflateStream s | |
1561 | CODE: | |
1562 | inflateEnd(&s->stream) ; | |
1563 | if (s->dictionary) | |
1564 | SvREFCNT_dec(s->dictionary) ; | |
1565 | #ifndef SETP_BYTE | |
1566 | if (s->deflateParams_out_buffer) | |
1567 | Safefree(s->deflateParams_out_buffer); | |
1568 | #endif | |
1569 | #ifdef MAGIC_APPEND | |
1570 | if (s->window) | |
1571 | Safefree(s->window); | |
1572 | #endif | |
1573 | Safefree(s) ; | |
1574 | ||
1575 | ||
1576 | uLong | |
1577 | status(s) | |
1578 | Compress::Raw::Zlib::inflateStream s | |
1579 | CODE: | |
1580 | RETVAL = s->last_error ; | |
1581 | OUTPUT: | |
1582 | RETVAL | |
1583 | ||
1584 | uLong | |
1585 | crc32(s) | |
1586 | Compress::Raw::Zlib::inflateStream s | |
1587 | CODE: | |
1588 | RETVAL = s->crc32 ; | |
1589 | OUTPUT: | |
1590 | RETVAL | |
1591 | ||
1592 | uLong | |
1593 | dict_adler(s) | |
1594 | Compress::Raw::Zlib::inflateStream s | |
1595 | CODE: | |
1596 | RETVAL = s->dict_adler ; | |
1597 | OUTPUT: | |
1598 | RETVAL | |
1599 | ||
1600 | uLong | |
1601 | total_in(s) | |
1602 | Compress::Raw::Zlib::inflateStream s | |
1603 | CODE: | |
1604 | RETVAL = s->stream.total_in ; | |
1605 | OUTPUT: | |
1606 | RETVAL | |
1607 | ||
1608 | uLong | |
1609 | adler32(s) | |
1610 | Compress::Raw::Zlib::inflateStream s | |
1611 | CODE: | |
1612 | RETVAL = s->adler32 ; | |
1613 | OUTPUT: | |
1614 | RETVAL | |
1615 | ||
1616 | uLong | |
1617 | total_out(s) | |
1618 | Compress::Raw::Zlib::inflateStream s | |
1619 | CODE: | |
1620 | RETVAL = s->stream.total_out ; | |
1621 | OUTPUT: | |
1622 | RETVAL | |
1623 | ||
1624 | char* | |
1625 | msg(s) | |
1626 | Compress::Raw::Zlib::inflateStream s | |
1627 | CODE: | |
1628 | RETVAL = s->stream.msg; | |
1629 | OUTPUT: | |
1630 | RETVAL | |
1631 | ||
1632 | ||
1633 | uLong | |
1634 | get_Bufsize(s) | |
1635 | Compress::Raw::Zlib::inflateStream s | |
1636 | CODE: | |
1637 | RETVAL = s->bufsize ; | |
1638 | OUTPUT: | |
1639 | RETVAL | |
1640 | ||
1641 | bool | |
1642 | set_Append(s, mode) | |
1643 | Compress::Raw::Zlib::inflateStream s | |
1644 | bool mode | |
1645 | CODE: | |
1646 | RETVAL = ((s->flags & FLAG_APPEND) == FLAG_APPEND); | |
1647 | if (mode) | |
1648 | s->flags |= FLAG_APPEND ; | |
1649 | else | |
1650 | s->flags &= ~FLAG_APPEND ; | |
1651 | OUTPUT: | |
1652 | RETVAL | |
1653 | ||
1654 | MODULE = Compress::Raw::Zlib PACKAGE = Compress::Raw::Zlib::inflateScanStream | |
1655 | ||
1656 | void | |
1657 | DESTROY(s) | |
1658 | Compress::Raw::Zlib::inflateScanStream s | |
1659 | CODE: | |
1660 | inflateEnd(&s->stream) ; | |
1661 | if (s->dictionary) | |
1662 | SvREFCNT_dec(s->dictionary) ; | |
1663 | #ifndef SETP_BYTE | |
1664 | if (s->deflateParams_out_buffer) | |
1665 | Safefree(s->deflateParams_out_buffer); | |
1666 | #endif | |
1667 | #ifdef MAGIC_APPEND | |
1668 | if (s->window) | |
1669 | Safefree(s->window); | |
1670 | #endif | |
1671 | Safefree(s) ; | |
1672 | ||
1673 | void | |
1674 | DispStream(s, message=NULL) | |
1675 | Compress::Raw::Zlib::inflateScanStream s | |
1676 | char * message | |
1677 | ||
1678 | DualType | |
1679 | inflateReset(s) | |
1680 | Compress::Raw::Zlib::inflateScanStream s | |
1681 | CODE: | |
1682 | RETVAL = inflateReset(&(s->stream)) ; | |
1683 | if (RETVAL == Z_OK) { | |
1684 | PostInitStream(s, s->flags, s->bufsize, s->WindowBits) ; | |
1685 | } | |
1686 | OUTPUT: | |
1687 | RETVAL | |
1688 | ||
1689 | DualType | |
1690 | scan(s, buf, out=NULL, eof=FALSE) | |
1691 | Compress::Raw::Zlib::inflateScanStream s | |
1692 | SV * buf | |
1693 | SV * out | |
1694 | bool eof | |
1695 | bool eof_mode = FALSE; | |
1696 | int start_len = NO_INIT | |
1697 | STRLEN stmp = NO_INIT | |
1698 | CODE: | |
1699 | /* If the input buffer is a reference, dereference it */ | |
1700 | #ifndef MAGIC_APPEND | |
1701 | buf = buf; | |
1702 | croak("scan needs zlib 1.2.1 or better"); | |
1703 | #else | |
1704 | buf = deRef(buf, "inflateScan") ; | |
1705 | #ifdef UTF8_AVAILABLE | |
1706 | if (DO_UTF8(buf) && !sv_utf8_downgrade(buf, 1)) | |
1707 | croak("Wide character in Compress::Raw::Zlib::InflateScan::scan input parameter"); | |
1708 | #endif | |
1709 | /* initialise the input buffer */ | |
1710 | s->stream.next_in = (Bytef*)SvPVbyte_force(buf, stmp) ; | |
1711 | s->stream.avail_in = SvCUR(buf) ; | |
1712 | start_len = s->stream.avail_in ; | |
1713 | s->bytesInflated = 0 ; | |
1714 | do | |
1715 | { | |
1716 | if (s->stream.avail_in == 0) { | |
1717 | RETVAL = Z_OK ; | |
1718 | break ; | |
1719 | } | |
1720 | ||
1721 | /* set up output to next available section of sliding window */ | |
1722 | s->stream.avail_out = WINDOW_SIZE - s->window_have; | |
1723 | s->stream.next_out = s->window + s->window_have; | |
1724 | ||
1725 | /* DispStream(s, "before inflate\n"); */ | |
1726 | ||
1727 | /* inflate and check for errors */ | |
1728 | RETVAL = inflate(&(s->stream), Z_BLOCK); | |
1729 | ||
1730 | if (start_len > 1 && ! eof_mode) | |
1731 | s->window_lastByte = *(s->stream.next_in - 1 ) ; | |
1732 | ||
1733 | if (RETVAL == Z_STREAM_ERROR || RETVAL == Z_MEM_ERROR || | |
1734 | RETVAL == Z_DATA_ERROR ) | |
1735 | break ; | |
1736 | ||
1737 | if (s->flags & FLAG_CRC32 ) | |
1738 | s->crc32 = crc32(s->crc32, s->window + s->window_have, | |
1739 | WINDOW_SIZE - s->window_have - s->stream.avail_out); | |
1740 | ||
1741 | if (s->flags & FLAG_ADLER32) | |
1742 | s->adler32 = adler32(s->adler32, s->window + s->window_have, | |
1743 | WINDOW_SIZE - s->window_have - s->stream.avail_out); | |
1744 | ||
1745 | s->uncompressedBytes = | |
1746 | s->bytesInflated += WINDOW_SIZE - s->window_have - s->stream.avail_out; | |
1747 | ||
1748 | if (s->stream.avail_out) | |
1749 | s->window_have = WINDOW_SIZE - s->stream.avail_out; | |
1750 | else { | |
1751 | s->window_have = 0; | |
1752 | s->window_full = 1; | |
1753 | } | |
1754 | ||
1755 | /* process end of block */ | |
1756 | if (s->stream.data_type & 128) { | |
1757 | if (s->stream.data_type & 64) { | |
1758 | s->window_left = s->stream.data_type & 0x1f; | |
1759 | } | |
1760 | else { | |
1761 | s->window_lastbit = s->stream.data_type & 0x1f; | |
1762 | s->lastBlockOffset = s->stream.total_in; | |
1763 | } | |
1764 | } | |
1765 | ||
1766 | } while (RETVAL != Z_STREAM_END); | |
1767 | ||
1768 | s->last_error = RETVAL ; | |
1769 | s->window_lastoff = s->stream.total_in ; | |
1770 | s->compressedBytes += SvCUR(buf) - s->stream.avail_in ; | |
1771 | ||
1772 | if (RETVAL == Z_STREAM_END) | |
1773 | { | |
1774 | s->matchedEndBlock = 1 ; | |
1775 | ||
1776 | /* save the location of the end of the compressed data */ | |
1777 | s->window_end = SvCUR(buf) - s->stream.avail_in - 1 ; | |
1778 | s->window_endOffset = s->stream.total_in ; | |
1779 | if (s->window_left) | |
1780 | { | |
1781 | -- s->window_endOffset ; | |
1782 | } | |
1783 | ||
1784 | /* if window wrapped, build dictionary from window by rotating */ | |
1785 | if (s->window_full) { | |
1786 | rotate(s->window, WINDOW_SIZE, s->window_have); | |
1787 | s->window_have = WINDOW_SIZE; | |
1788 | } | |
1789 | ||
1790 | /* if (s->flags & FLAG_CONSUME_INPUT) { */ | |
1791 | if (1) { | |
1792 | unsigned in = s->stream.avail_in ; | |
1793 | SvCUR_set(buf, in) ; | |
1794 | if (in) | |
1795 | Move(s->stream.next_in, SvPVbyte_nolen(buf), in, char) ; | |
1796 | *SvEND(buf) = '\0'; | |
1797 | SvSETMAGIC(buf); | |
1798 | } | |
1799 | } | |
1800 | #endif | |
1801 | OUTPUT: | |
1802 | RETVAL | |
1803 | ||
1804 | ||
1805 | uLong | |
1806 | getEndOffset(s) | |
1807 | Compress::Raw::Zlib::inflateScanStream s | |
1808 | CODE: | |
1809 | #ifndef MAGIC_APPEND | |
1810 | croak("getEndOffset needs zlib 1.2.1 or better"); | |
1811 | #else | |
1812 | RETVAL = s->window_endOffset; | |
1813 | #endif | |
1814 | OUTPUT: | |
1815 | RETVAL | |
1816 | ||
1817 | uLong | |
1818 | inflateCount(s) | |
1819 | Compress::Raw::Zlib::inflateScanStream s | |
1820 | CODE: | |
1821 | #ifndef MAGIC_APPEND | |
1822 | croak("inflateCount needs zlib 1.2.1 or better"); | |
1823 | #else | |
1824 | RETVAL = s->bytesInflated; | |
1825 | #endif | |
1826 | OUTPUT: | |
1827 | RETVAL | |
1828 | ||
1829 | uLong | |
1830 | compressedBytes(s) | |
1831 | Compress::Raw::Zlib::inflateScanStream s | |
1832 | CODE: | |
1833 | RETVAL = s->compressedBytes; | |
1834 | OUTPUT: | |
1835 | RETVAL | |
1836 | ||
1837 | uLong | |
1838 | uncompressedBytes(s) | |
1839 | Compress::Raw::Zlib::inflateScanStream s | |
1840 | CODE: | |
1841 | RETVAL = s->uncompressedBytes; | |
1842 | OUTPUT: | |
1843 | RETVAL | |
1844 | ||
1845 | ||
1846 | uLong | |
1847 | getLastBlockOffset(s) | |
1848 | Compress::Raw::Zlib::inflateScanStream s | |
1849 | CODE: | |
1850 | #ifndef MAGIC_APPEND | |
1851 | croak("getLastBlockOffset needs zlib 1.2.1 or better"); | |
1852 | #else | |
1853 | RETVAL = s->lastBlockOffset - (s->window_lastbit != 0); | |
1854 | #endif | |
1855 | OUTPUT: | |
1856 | RETVAL | |
1857 | ||
1858 | uLong | |
1859 | getLastBufferOffset(s) | |
1860 | Compress::Raw::Zlib::inflateScanStream s | |
1861 | CODE: | |
1862 | #ifndef MAGIC_APPEND | |
1863 | croak("getLastBufferOffset needs zlib 1.2.1 or better"); | |
1864 | #else | |
1865 | RETVAL = s->window_lastoff; | |
1866 | #endif | |
1867 | OUTPUT: | |
1868 | RETVAL | |
1869 | ||
1870 | void | |
1871 | resetLastBlockByte(s, byte) | |
1872 | Compress::Raw::Zlib::inflateScanStream s | |
1873 | unsigned char* byte | |
1874 | CODE: | |
1875 | #ifndef MAGIC_APPEND | |
1876 | croak("resetLastBlockByte needs zlib 1.2.1 or better"); | |
1877 | #else | |
cb7abd7f PM |
1878 | if (byte != NULL) |
1879 | *byte = *byte ^ (1 << ((8 - s->window_lastbit) & 7)); | |
25f0751f PM |
1880 | #endif |
1881 | ||
1882 | ||
1883 | void | |
1884 | _createDeflateStream(inf_s, flags,level, method, windowBits, memLevel, strategy, bufsize) | |
1885 | Compress::Raw::Zlib::inflateScanStream inf_s | |
1886 | int flags | |
1887 | int level | |
1888 | int method | |
1889 | int windowBits | |
1890 | int memLevel | |
1891 | int strategy | |
1892 | uLong bufsize | |
1893 | PPCODE: | |
1894 | { | |
1895 | #ifndef MAGIC_APPEND | |
1896 | flags = flags; | |
1897 | level = level ; | |
1898 | method = method; | |
1899 | windowBits = windowBits; | |
1900 | memLevel = memLevel; | |
1901 | strategy = strategy; | |
1902 | bufsize= bufsize; | |
1903 | croak("_createDeflateStream needs zlib 1.2.1 or better"); | |
1904 | #else | |
1905 | int err ; | |
1906 | deflateStream s ; | |
1907 | ||
1908 | if (trace) | |
1909 | warn("in _createDeflateStream(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%lu\n", | |
1910 | level, method, windowBits, memLevel, strategy, bufsize) ; | |
1911 | if ((s = InitStream() )) { | |
1912 | ||
1913 | s->Level = level; | |
1914 | s->Method = method; | |
1915 | s->WindowBits = windowBits; | |
1916 | s->MemLevel = memLevel; | |
1917 | s->Strategy = strategy; | |
1918 | ||
1919 | err = deflateInit2(&(s->stream), level, | |
1920 | method, windowBits, memLevel, strategy); | |
1921 | ||
1922 | if (err == Z_OK) { | |
1923 | err = deflateSetDictionary(&(s->stream), inf_s->window, inf_s->window_have); | |
1924 | s->dict_adler = s->stream.adler ; | |
1925 | } | |
1926 | ||
1927 | if (err != Z_OK) { | |
1928 | Safefree(s) ; | |
1929 | s = NULL ; | |
1930 | } | |
1931 | else { | |
1932 | PostInitStream(s, flags, bufsize, windowBits) ; | |
1933 | s->crc32 = inf_s->crc32; | |
1934 | s->adler32 = inf_s->adler32; | |
1935 | s->stream.adler = inf_s->stream.adler ; | |
1936 | /* s->stream.total_out = inf_s->bytesInflated ; */ | |
1937 | s->stream.total_in = inf_s->stream.total_out ; | |
1938 | if (inf_s->window_left) { | |
1939 | /* printf("** window_left %d, window_lastByte %d\n", inf_s->window_left, inf_s->window_lastByte); */ | |
1940 | deflatePrime(&(s->stream), 8 - inf_s->window_left, inf_s->window_lastByte); | |
1941 | } | |
1942 | } | |
1943 | } | |
1944 | else | |
1945 | err = Z_MEM_ERROR ; | |
1946 | ||
1947 | XPUSHs(sv_setref_pv(sv_newmortal(), | |
1948 | "Compress::Raw::Zlib::deflateStream", (void*)s)); | |
1949 | if (GIMME == G_ARRAY) { | |
1950 | SV * sv = sv_2mortal(newSViv(err)) ; | |
1951 | setDUALstatus(sv, err); | |
1952 | XPUSHs(sv) ; | |
1953 | } | |
1954 | #endif | |
1955 | } | |
1956 | ||
1957 | DualType | |
1958 | status(s) | |
1959 | Compress::Raw::Zlib::inflateScanStream s | |
1960 | CODE: | |
1961 | RETVAL = s->last_error ; | |
1962 | OUTPUT: | |
1963 | RETVAL | |
1964 | ||
1965 | uLong | |
1966 | crc32(s) | |
1967 | Compress::Raw::Zlib::inflateScanStream s | |
1968 | CODE: | |
1969 | RETVAL = s->crc32 ; | |
1970 | OUTPUT: | |
1971 | RETVAL | |
1972 | ||
1973 | ||
1974 | uLong | |
1975 | adler32(s) | |
1976 | Compress::Raw::Zlib::inflateScanStream s | |
1977 | CODE: | |
1978 | RETVAL = s->adler32 ; | |
1979 | OUTPUT: | |
1980 | RETVAL | |
1981 |