Commit | Line | Data |
f4c6fd49 |
1 | /* Filename: Zlib.xs |
2 | * Author : Paul Marquess, <pmqs@cpan.org> |
3 | * Created : 30 January 2005 |
76e6f389 |
4 | * Version : 1.38 |
f4c6fd49 |
5 | * |
6 | * Copyright (c) 1995-2005 Paul Marquess. All rights reserved. |
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 | /* Part of this code is based on the file gzio.c */ |
13 | |
14 | /* gzio.c -- IO on .gz files |
15 | * Copyright (C) 1995 Jean-loup Gailly. |
16 | * For conditions of distribution and use, see copyright notice in zlib.h |
17 | */ |
18 | |
19 | |
20 | |
21 | #include "EXTERN.h" |
22 | #include "perl.h" |
23 | #include "XSUB.h" |
24 | |
25 | #include <zlib.h> |
26 | |
27 | #ifndef PERL_VERSION |
28 | #include "patchlevel.h" |
29 | #define PERL_REVISION 5 |
30 | #define PERL_VERSION PATCHLEVEL |
31 | #define PERL_SUBVERSION SUBVERSION |
32 | #endif |
33 | |
34 | #if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 )) |
35 | |
36 | # define PL_sv_undef sv_undef |
37 | # define PL_na na |
38 | # define PL_curcop curcop |
39 | # define PL_compiling compiling |
40 | |
41 | #endif |
42 | |
43 | #ifndef newSVuv |
44 | # define newSVuv newSViv |
45 | #endif |
46 | |
76e6f389 |
47 | #ifndef dTHX |
48 | # define dTHX |
49 | #endif |
50 | |
f4c6fd49 |
51 | typedef struct di_stream { |
52 | z_stream stream; |
53 | uLong bufsize; |
54 | uLong bufinc; |
55 | SV * dictionary ; |
56 | uLong dict_adler ; |
57 | bool deflateParams_out_valid ; |
58 | Bytef deflateParams_out_byte; |
59 | int Level; |
60 | int Method; |
61 | int WindowBits; |
62 | int MemLevel; |
63 | int Strategy; |
64 | } di_stream; |
65 | |
66 | typedef di_stream * deflateStream ; |
67 | typedef di_stream * Compress__Zlib__deflateStream ; |
68 | typedef di_stream * inflateStream ; |
69 | typedef di_stream * Compress__Zlib__inflateStream ; |
70 | |
71 | /* typedef gzFile Compress__Zlib__gzFile ; */ |
72 | typedef struct gzType { |
73 | gzFile gz ; |
74 | SV * buffer ; |
75 | uLong offset ; |
76 | bool closed ; |
77 | } gzType ; |
78 | |
79 | typedef gzType* Compress__Zlib__gzFile ; |
80 | |
81 | |
82 | |
83 | #define GZERRNO "Compress::Zlib::gzerrno" |
84 | |
85 | #define ZMALLOC(to, typ) ((to = (typ *)safemalloc(sizeof(typ))), \ |
86 | Zero(to,1,typ)) |
87 | |
88 | #define adlerInitial adler32(0L, Z_NULL, 0) |
89 | #define crcInitial crc32(0L, Z_NULL, 0) |
90 | |
91 | #if 1 |
c042ae3a |
92 | static const char * const my_z_errmsg[] = { |
f4c6fd49 |
93 | "need dictionary", /* Z_NEED_DICT 2 */ |
94 | "stream end", /* Z_STREAM_END 1 */ |
95 | "", /* Z_OK 0 */ |
96 | "file error", /* Z_ERRNO (-1) */ |
97 | "stream error", /* Z_STREAM_ERROR (-2) */ |
98 | "data error", /* Z_DATA_ERROR (-3) */ |
99 | "insufficient memory", /* Z_MEM_ERROR (-4) */ |
100 | "buffer error", /* Z_BUF_ERROR (-5) */ |
101 | "incompatible version",/* Z_VERSION_ERROR(-6) */ |
102 | ""}; |
103 | #endif |
104 | |
c042ae3a |
105 | #if defined(__SYMBIAN32__) |
106 | # define NO_WRITEABLE_DATA |
107 | #endif |
108 | |
109 | #define TRACE_DEFAULT 0 |
110 | |
111 | #ifdef NO_WRITEABLE_DATA |
112 | #define trace TRACE_DEFAULT |
113 | #else |
114 | static int trace = TRACE_DEFAULT ; |
115 | #endif |
f4c6fd49 |
116 | |
c042ae3a |
117 | /* Dodge PerlIO hiding of these functions. */ |
118 | #undef printf |
f4c6fd49 |
119 | |
120 | static void |
121 | #ifdef CAN_PROTOTYPE |
122 | SetGzErrorNo(int error_no) |
123 | #else |
124 | SetGzErrorNo(error_no) |
125 | int error_no ; |
126 | #endif |
127 | { |
c042ae3a |
128 | dTHX; |
f4c6fd49 |
129 | char * errstr ; |
130 | SV * gzerror_sv = perl_get_sv(GZERRNO, FALSE) ; |
131 | |
132 | if (error_no == Z_ERRNO) { |
133 | error_no = errno ; |
134 | errstr = Strerror(errno) ; |
135 | } |
136 | else |
137 | /* errstr = gzerror(fil, &error_no) ; */ |
138 | errstr = (char*) my_z_errmsg[2 - error_no]; |
139 | |
140 | if (SvIV(gzerror_sv) != error_no) { |
141 | sv_setiv(gzerror_sv, error_no) ; |
142 | sv_setpv(gzerror_sv, errstr) ; |
143 | SvIOK_on(gzerror_sv) ; |
144 | } |
145 | |
146 | } |
147 | |
148 | static void |
149 | #ifdef CAN_PROTOTYPE |
150 | SetGzError(gzFile file) |
151 | #else |
152 | SetGzError(file) |
153 | gzFile file ; |
154 | #endif |
155 | { |
156 | int error_no ; |
157 | |
158 | (void)gzerror(file, &error_no) ; |
159 | SetGzErrorNo(error_no) ; |
160 | } |
161 | |
162 | static void |
163 | #ifdef CAN_PROTOTYPE |
164 | DispHex(void * ptr, int length) |
165 | #else |
166 | DispHex(ptr, length) |
167 | void * ptr; |
168 | int length; |
169 | #endif |
170 | { |
171 | char * p = (char*)ptr; |
172 | int i; |
173 | for (i = 0; i < length; ++i) { |
174 | printf(" %02x", 0xFF & *(p+i)); |
175 | } |
176 | } |
177 | |
178 | |
179 | static void |
180 | #ifdef CAN_PROTOTYPE |
181 | DispStream(di_stream * s, char * message) |
182 | #else |
183 | DispStream(s, message) |
184 | di_stream * s; |
185 | char * message; |
186 | #endif |
187 | { |
188 | |
189 | #if 0 |
190 | if (! trace) |
191 | return ; |
192 | #endif |
193 | |
194 | printf("DispStream 0x%p - %s \n", s, message) ; |
195 | |
196 | if (!s) { |
197 | printf(" stream pointer is NULL\n"); |
198 | } |
199 | else { |
200 | printf(" stream 0x%p\n", &(s->stream)); |
201 | printf(" zalloc 0x%p\n", s->stream.zalloc); |
202 | printf(" zfree 0x%p\n", s->stream.zfree); |
203 | printf(" opaque 0x%p\n", s->stream.opaque); |
204 | if (s->stream.msg) |
205 | printf(" msg %s\n", s->stream.msg); |
206 | else |
207 | printf(" msg \n"); |
208 | printf(" next_in 0x%p", s->stream.next_in); |
209 | if (s->stream.next_in) { |
210 | printf(" =>"); |
211 | DispHex(s->stream.next_in, 4); |
212 | } |
213 | printf("\n"); |
214 | |
215 | printf(" next_out 0x%p", s->stream.next_out); |
216 | if (s->stream.next_out){ |
217 | printf(" =>"); |
218 | DispHex(s->stream.next_out, 4); |
219 | } |
220 | printf("\n"); |
221 | |
222 | printf(" avail_in %ld\n", s->stream.avail_in); |
223 | printf(" avail_out %ld\n", s->stream.avail_out); |
224 | printf(" total_in %ld\n", s->stream.total_in); |
225 | printf(" total_out %ld\n", s->stream.total_out); |
226 | printf(" adler 0x%lx\n", s->stream.adler); |
227 | printf(" reserved 0x%lx\n", s->stream.reserved); |
228 | printf(" bufsize %ld\n", s->bufsize); |
229 | printf(" dictionary 0x%p\n", s->dictionary); |
230 | printf(" dict_adler 0x%ld\n", s->dict_adler); |
231 | printf("\n"); |
232 | |
233 | } |
234 | } |
235 | |
236 | |
237 | static di_stream * |
238 | #ifdef CAN_PROTOTYPE |
239 | InitStream(uLong bufsize) |
240 | #else |
241 | InitStream(bufsize) |
242 | uLong bufsize ; |
243 | #endif |
244 | { |
245 | di_stream *s ; |
246 | |
247 | ZMALLOC(s, di_stream) ; |
248 | |
249 | if (s) { |
250 | s->bufsize = bufsize ; |
251 | s->bufinc = bufsize ; |
252 | } |
253 | |
254 | return s ; |
255 | |
256 | } |
257 | |
258 | #define SIZE 4096 |
259 | |
260 | static int |
261 | #ifdef CAN_PROTOTYPE |
262 | gzreadline(Compress__Zlib__gzFile file, SV * output) |
263 | #else |
264 | gzreadline(file, output) |
265 | Compress__Zlib__gzFile file ; |
266 | SV * output ; |
267 | #endif |
268 | { |
c042ae3a |
269 | dTHX; |
f4c6fd49 |
270 | SV * store = file->buffer ; |
271 | char *nl = "\n"; |
272 | char *p; |
273 | char *out_ptr = SvPVX(store) ; |
274 | int n; |
275 | |
276 | while (1) { |
277 | |
278 | /* anything left from last time */ |
279 | if ((n = SvCUR(store))) { |
280 | |
281 | out_ptr = SvPVX(store) + file->offset ; |
282 | if ((p = ninstr(out_ptr, out_ptr + n - 1, nl, nl))) { |
283 | /* if (rschar != 0777 && */ |
284 | /* p = ninstr(out_ptr, out_ptr + n - 1, rs, rs+rslen-1)) { */ |
285 | |
286 | sv_catpvn(output, out_ptr, p - out_ptr + 1); |
287 | |
288 | file->offset += (p - out_ptr + 1) ; |
289 | n = n - (p - out_ptr + 1); |
290 | SvCUR_set(store, n) ; |
291 | return SvCUR(output); |
292 | } |
293 | else /* no EOL, so append the complete buffer */ |
294 | sv_catpvn(output, out_ptr, n); |
295 | |
296 | } |
297 | |
298 | |
299 | SvCUR_set(store, 0) ; |
300 | file->offset = 0 ; |
301 | out_ptr = SvPVX(store) ; |
302 | |
303 | n = gzread(file->gz, out_ptr, SIZE) ; |
304 | |
305 | if (n <= 0) |
306 | /* Either EOF or an error */ |
307 | /* so return what we have so far else signal eof */ |
308 | return (SvCUR(output)>0) ? SvCUR(output) : n ; |
309 | |
310 | SvCUR_set(store, n) ; |
311 | } |
312 | } |
313 | |
314 | static SV* |
315 | #ifdef CAN_PROTOTYPE |
316 | deRef(SV * sv, char * string) |
317 | #else |
318 | deRef(sv, string) |
319 | SV * sv ; |
320 | char * string; |
321 | #endif |
322 | { |
c042ae3a |
323 | dTHX; |
f4c6fd49 |
324 | if (SvROK(sv)) { |
325 | sv = SvRV(sv) ; |
326 | switch(SvTYPE(sv)) { |
327 | case SVt_PVAV: |
328 | case SVt_PVHV: |
329 | case SVt_PVCV: |
330 | croak("%s: buffer parameter is not a SCALAR reference", string); |
331 | } |
332 | if (SvROK(sv)) |
333 | croak("%s: buffer parameter is a reference to a reference", string) ; |
334 | } |
335 | |
336 | if (!SvOK(sv)) { |
337 | sv = newSVpv("", 0); |
338 | } |
339 | return sv ; |
340 | } |
341 | |
342 | #include "constants.h" |
343 | |
344 | MODULE = Compress::Zlib PACKAGE = Compress::Zlib PREFIX = Zip_ |
345 | |
346 | REQUIRE: 1.924 |
347 | PROTOTYPES: DISABLE |
348 | |
349 | INCLUDE: constants.xs |
350 | |
351 | BOOT: |
352 | /* Check this version of zlib is == 1 */ |
353 | if (zlibVersion()[0] != '1') |
354 | croak("Compress::Zlib needs zlib version 1.x\n") ; |
355 | |
356 | { |
357 | /* Create the $gzerror scalar */ |
358 | SV * gzerror_sv = perl_get_sv(GZERRNO, GV_ADDMULTI) ; |
359 | sv_setiv(gzerror_sv, 0) ; |
360 | sv_setpv(gzerror_sv, "") ; |
361 | SvIOK_on(gzerror_sv) ; |
362 | } |
363 | |
364 | |
365 | #define Zip_zlib_version() (char*)zlib_version |
366 | char* |
367 | Zip_zlib_version() |
368 | |
06edba15 |
369 | unsigned |
370 | ZLIB_VERNUM() |
371 | CODE: |
372 | #ifdef ZLIB_VERNUM |
373 | RETVAL = ZLIB_VERNUM ; |
374 | #else |
375 | /* 1.1.4 => 0x1140 */ |
376 | RETVAL = (ZLIB_VERSION[0] - '0') << 12 ; |
377 | RETVAL += (ZLIB_VERSION[2] - '0') << 8 ; |
378 | RETVAL += (ZLIB_VERSION[4] - '0') << 4 ; |
379 | #endif |
380 | OUTPUT: |
381 | RETVAL |
382 | |
383 | |
f4c6fd49 |
384 | |
385 | void |
386 | DispStream(s, message=NULL) |
387 | Compress::Zlib::inflateStream s |
388 | char * message |
389 | |
390 | Compress::Zlib::gzFile |
391 | gzopen_(path, mode) |
392 | char * path |
393 | char * mode |
394 | CODE: |
395 | gzFile gz ; |
396 | gz = gzopen(path, mode) ; |
397 | if (gz) { |
398 | ZMALLOC(RETVAL, gzType) ; |
399 | RETVAL->buffer = newSV(SIZE) ; |
400 | SvPOK_only(RETVAL->buffer) ; |
401 | SvCUR_set(RETVAL->buffer, 0) ; |
402 | RETVAL->offset = 0 ; |
403 | RETVAL->gz = gz ; |
404 | RETVAL->closed = FALSE ; |
405 | SetGzErrorNo(0) ; |
406 | } |
407 | else { |
408 | RETVAL = NULL ; |
409 | SetGzErrorNo(errno ? Z_ERRNO : Z_MEM_ERROR) ; |
410 | } |
411 | OUTPUT: |
412 | RETVAL |
413 | |
414 | |
415 | Compress::Zlib::gzFile |
416 | gzdopen_(fh, mode, offset) |
417 | int fh |
418 | char * mode |
419 | long offset |
420 | CODE: |
421 | gzFile gz ; |
422 | if (offset != -1) |
423 | lseek(fh, offset, 0) ; |
424 | gz = gzdopen(fh, mode) ; |
425 | if (gz) { |
426 | ZMALLOC(RETVAL, gzType) ; |
427 | RETVAL->buffer = newSV(SIZE) ; |
428 | SvPOK_only(RETVAL->buffer) ; |
429 | SvCUR_set(RETVAL->buffer, 0) ; |
430 | RETVAL->offset = 0 ; |
431 | RETVAL->gz = gz ; |
432 | RETVAL->closed = FALSE ; |
433 | SetGzErrorNo(0) ; |
434 | } |
435 | else { |
436 | RETVAL = NULL ; |
437 | SetGzErrorNo(errno ? Z_ERRNO : Z_MEM_ERROR) ; |
438 | } |
439 | OUTPUT: |
440 | RETVAL |
441 | |
442 | |
443 | MODULE = Compress::Zlib PACKAGE = Compress::Zlib::gzFile PREFIX = Zip_ |
444 | |
445 | #define Zip_gzread(file, buf, len) gzread(file->gz, bufp, len) |
446 | |
447 | int |
448 | Zip_gzread(file, buf, len=4096) |
449 | Compress::Zlib::gzFile file |
450 | unsigned len |
451 | SV * buf |
452 | voidp bufp = NO_INIT |
453 | uLong bufsize = 0 ; |
454 | int RETVAL = 0 ; |
455 | CODE: |
456 | if (SvREADONLY(buf) && PL_curcop != &PL_compiling) |
457 | croak("gzread: buffer parameter is read-only"); |
f2e5e569 |
458 | SvUPGRADE(buf, SVt_PV); |
f4c6fd49 |
459 | SvPOK_only(buf); |
460 | SvCUR_set(buf, 0); |
461 | /* any left over from gzreadline ? */ |
462 | if ((bufsize = SvCUR(file->buffer)) > 0) { |
463 | uLong movesize ; |
464 | |
465 | if (bufsize < len) { |
466 | movesize = bufsize ; |
467 | len -= movesize ; |
468 | } |
469 | else { |
470 | movesize = len ; |
471 | len = 0 ; |
472 | } |
473 | RETVAL = movesize ; |
474 | |
475 | sv_catpvn(buf, SvPVX(file->buffer) + file->offset, movesize); |
476 | |
477 | file->offset += movesize ; |
478 | SvCUR_set(file->buffer, bufsize - movesize) ; |
479 | } |
480 | |
481 | if (len) { |
482 | bufp = (Byte*)SvGROW(buf, bufsize+len+1); |
483 | RETVAL = gzread(file->gz, ((Bytef*)bufp)+bufsize, len) ; |
484 | SetGzError(file->gz) ; |
485 | if (RETVAL >= 0) { |
486 | RETVAL += bufsize ; |
487 | SvCUR_set(buf, RETVAL) ; |
488 | *SvEND(buf) = '\0'; |
489 | } |
490 | } |
491 | OUTPUT: |
492 | RETVAL |
493 | buf |
494 | |
495 | int |
496 | gzreadline(file, buf) |
497 | Compress::Zlib::gzFile file |
498 | SV * buf |
499 | int RETVAL = 0; |
500 | CODE: |
501 | if (SvREADONLY(buf) && PL_curcop != &PL_compiling) |
502 | croak("gzreadline: buffer parameter is read-only"); |
f2e5e569 |
503 | SvUPGRADE(buf, SVt_PV); |
f4c6fd49 |
504 | SvPOK_only(buf); |
505 | /* sv_setpvn(buf, "", SIZE) ; */ |
506 | SvGROW(buf, SIZE) ; |
507 | SvCUR_set(buf, 0); |
508 | RETVAL = gzreadline(file, buf) ; |
509 | SetGzError(file->gz) ; |
510 | OUTPUT: |
511 | RETVAL |
512 | buf |
513 | CLEANUP: |
514 | if (RETVAL >= 0) { |
515 | /* SvCUR(buf) = RETVAL; */ |
516 | /* Don't need to explicitly terminate with '\0', because |
517 | sv_catpvn aready has */ |
518 | } |
519 | |
520 | #define Zip_gzwrite(file, buf) gzwrite(file->gz, buf, (unsigned)len) |
521 | int |
522 | Zip_gzwrite(file, buf) |
523 | Compress::Zlib::gzFile file |
524 | STRLEN len = NO_INIT |
525 | voidp buf = (voidp)SvPV(ST(1), len) ; |
526 | CLEANUP: |
527 | SetGzError(file->gz) ; |
528 | |
529 | #define Zip_gzflush(file, flush) gzflush(file->gz, flush) |
530 | int |
531 | Zip_gzflush(file, flush) |
532 | Compress::Zlib::gzFile file |
533 | int flush |
534 | CLEANUP: |
535 | SetGzError(file->gz) ; |
536 | |
06edba15 |
537 | #define Zip_gzclose(file) file->closed ? 0 : gzclose(file->gz) |
f4c6fd49 |
538 | int |
539 | Zip_gzclose(file) |
540 | Compress::Zlib::gzFile file |
541 | CLEANUP: |
542 | file->closed = TRUE ; |
543 | SetGzErrorNo(RETVAL) ; |
544 | |
545 | |
546 | #define Zip_gzeof(file) gzeof(file->gz) |
547 | int |
548 | Zip_gzeof(file) |
549 | Compress::Zlib::gzFile file |
550 | CODE: |
551 | #ifdef OLD_ZLIB |
552 | croak("gzeof needs zlib 1.0.6 or better") ; |
553 | #else |
554 | RETVAL = gzeof(file->gz); |
555 | #endif |
556 | OUTPUT: |
557 | RETVAL |
558 | |
559 | |
560 | #define Zip_gzsetparams(file,l,s) gzsetparams(file->gz,l,s) |
561 | int |
562 | Zip_gzsetparams(file, level, strategy) |
563 | Compress::Zlib::gzFile file |
564 | int level |
565 | int strategy |
566 | CODE: |
567 | #ifdef OLD_ZLIB |
568 | croak("gzsetparams needs zlib 1.0.6 or better") ; |
569 | #else |
570 | RETVAL = gzsetparams(file->gz, level, strategy); |
571 | #endif |
572 | OUTPUT: |
573 | RETVAL |
574 | |
575 | void |
576 | DESTROY(file) |
577 | Compress::Zlib::gzFile file |
578 | CODE: |
579 | if (! file->closed) |
580 | Zip_gzclose(file) ; |
581 | SvREFCNT_dec(file->buffer) ; |
582 | safefree((char*)file) ; |
583 | |
584 | #define Zip_gzerror(file) (char*)gzerror(file->gz, &errnum) |
585 | |
586 | char * |
587 | Zip_gzerror(file) |
588 | Compress::Zlib::gzFile file |
589 | int errnum = NO_INIT |
590 | CLEANUP: |
591 | sv_setiv(ST(0), errnum) ; |
592 | SvPOK_on(ST(0)) ; |
593 | |
594 | |
595 | |
596 | MODULE = Compress::Zlib PACKAGE = Compress::Zlib PREFIX = Zip_ |
597 | |
598 | |
599 | #define Zip_adler32(buf, adler) adler32(adler, buf, (uInt)len) |
600 | |
601 | uLong |
602 | Zip_adler32(buf, adler=adlerInitial) |
603 | uLong adler = NO_INIT |
604 | STRLEN len = NO_INIT |
605 | Bytef * buf = NO_INIT |
606 | SV * sv = ST(0) ; |
607 | INIT: |
608 | /* If the buffer is a reference, dereference it */ |
609 | sv = deRef(sv, "adler32") ; |
610 | buf = (Byte*)SvPV(sv, len) ; |
611 | |
612 | if (items < 2) |
613 | adler = adlerInitial; |
614 | else if (SvOK(ST(1))) |
615 | adler = SvUV(ST(1)) ; |
616 | else |
617 | adler = adlerInitial; |
618 | |
619 | #define Zip_crc32(buf, crc) crc32(crc, buf, (uInt)len) |
620 | |
621 | uLong |
622 | Zip_crc32(buf, crc=crcInitial) |
623 | uLong crc = NO_INIT |
624 | STRLEN len = NO_INIT |
625 | Bytef * buf = NO_INIT |
626 | SV * sv = ST(0) ; |
627 | INIT: |
628 | /* If the buffer is a reference, dereference it */ |
629 | sv = deRef(sv, "crc32") ; |
630 | buf = (Byte*)SvPV(sv, len) ; |
631 | |
632 | if (items < 2) |
633 | crc = crcInitial; |
634 | else if (SvOK(ST(1))) |
635 | crc = SvUV(ST(1)) ; |
636 | else |
637 | crc = crcInitial; |
638 | |
639 | MODULE = Compress::Zlib PACKAGE = Compress::Zlib |
640 | |
641 | void |
642 | _deflateInit(level, method, windowBits, memLevel, strategy, bufsize, dictionary) |
643 | int level |
644 | int method |
645 | int windowBits |
646 | int memLevel |
647 | int strategy |
648 | uLong bufsize |
649 | SV * dictionary |
650 | PPCODE: |
651 | |
652 | int err ; |
653 | deflateStream s ; |
654 | |
655 | if (trace) |
656 | warn("in _deflateInit(level=%d, method=%d, windowBits=%d, memLevel=%d, strategy=%d, bufsize=%d\n", |
657 | level, method, windowBits, memLevel, strategy, bufsize) ; |
658 | if ((s = InitStream(bufsize)) ) { |
659 | |
660 | s->Level = level; |
661 | s->Method = method; |
662 | s->WindowBits = windowBits; |
663 | s->MemLevel = memLevel; |
664 | s->Strategy = strategy; |
665 | |
666 | err = deflateInit2(&(s->stream), level, |
667 | method, windowBits, memLevel, strategy); |
668 | |
669 | /* Check if a dictionary has been specified */ |
670 | if (err == Z_OK && SvCUR(dictionary)) { |
671 | err = deflateSetDictionary(&(s->stream), (const Bytef*) SvPVX(dictionary), |
672 | SvCUR(dictionary)) ; |
673 | s->dict_adler = s->stream.adler ; |
674 | } |
675 | |
676 | if (err != Z_OK) { |
677 | Safefree(s) ; |
678 | s = NULL ; |
679 | } |
680 | |
681 | } |
682 | else |
683 | err = Z_MEM_ERROR ; |
684 | |
685 | XPUSHs(sv_setref_pv(sv_newmortal(), |
686 | "Compress::Zlib::deflateStream", (void*)s)); |
687 | if (GIMME == G_ARRAY) |
688 | XPUSHs(sv_2mortal(newSViv(err))) ; |
689 | |
690 | void |
691 | _inflateInit(windowBits, bufsize, dictionary) |
692 | int windowBits |
693 | uLong bufsize |
694 | SV * dictionary |
695 | PPCODE: |
696 | |
697 | int err = Z_OK ; |
698 | inflateStream s ; |
699 | |
700 | if (trace) |
701 | warn("in _inflateInit(windowBits=%d, bufsize=%d, dictionary=%d\n", |
702 | windowBits, bufsize, SvCUR(dictionary)) ; |
703 | if ((s = InitStream(bufsize)) ) { |
704 | |
705 | s->WindowBits = windowBits; |
706 | |
707 | err = inflateInit2(&(s->stream), windowBits); |
708 | |
709 | if (err != Z_OK) { |
710 | Safefree(s) ; |
711 | s = NULL ; |
712 | } |
713 | else if (SvCUR(dictionary)) { |
714 | /* Dictionary specified - take a copy for use in inflate */ |
715 | s->dictionary = newSVsv(dictionary) ; |
716 | } |
717 | } |
718 | else |
719 | err = Z_MEM_ERROR ; |
720 | |
721 | XPUSHs(sv_setref_pv(sv_newmortal(), |
722 | "Compress::Zlib::inflateStream", (void*)s)); |
723 | if (GIMME == G_ARRAY) |
724 | XPUSHs(sv_2mortal(newSViv(err))) ; |
725 | |
726 | |
727 | |
728 | MODULE = Compress::Zlib PACKAGE = Compress::Zlib::deflateStream |
729 | |
730 | void |
731 | DispStream(s, message=NULL) |
732 | Compress::Zlib::deflateStream s |
733 | char * message |
734 | |
735 | void |
736 | deflate (s, buf) |
737 | Compress::Zlib::deflateStream s |
738 | SV * buf |
739 | uLong outsize = NO_INIT |
740 | SV * output = NO_INIT |
741 | int err = 0; |
742 | PPCODE: |
743 | |
744 | /* If the buffer is a reference, dereference it */ |
745 | buf = deRef(buf, "deflate") ; |
746 | |
747 | /* initialise the input buffer */ |
748 | s->stream.next_in = (Bytef*)SvPV(buf, *(STRLEN*)&s->stream.avail_in) ; |
749 | /* s->stream.next_in = (Bytef*)SvPVX(buf); */ |
750 | s->stream.avail_in = SvCUR(buf) ; |
751 | |
752 | /* and the output buffer */ |
753 | /* output = sv_2mortal(newSVpv("", s->bufinc)) ; */ |
754 | output = sv_2mortal(newSV(s->bufinc)) ; |
755 | SvPOK_only(output) ; |
756 | SvCUR_set(output, 0) ; |
757 | outsize = s->bufinc ; |
758 | s->stream.next_out = (Bytef*) SvPVX(output) ; |
759 | s->stream.avail_out = outsize; |
760 | |
761 | /* Check for saved output from deflateParams */ |
762 | if (s->deflateParams_out_valid) { |
763 | *(s->stream.next_out) = s->deflateParams_out_byte; |
764 | ++ s->stream.next_out; |
765 | -- s->stream.avail_out ; |
766 | s->deflateParams_out_valid = FALSE; |
767 | } |
768 | |
769 | while (s->stream.avail_in != 0) { |
770 | |
771 | if (s->stream.avail_out == 0) { |
772 | s->bufinc *= 2 ; |
773 | SvGROW(output, outsize + s->bufinc) ; |
774 | s->stream.next_out = (Bytef*) SvPVX(output) + outsize ; |
775 | outsize += s->bufinc ; |
776 | s->stream.avail_out = s->bufinc ; |
777 | } |
778 | err = deflate(&(s->stream), Z_NO_FLUSH); |
779 | if (err != Z_OK) |
780 | break; |
781 | } |
782 | |
783 | if (err == Z_OK) { |
784 | SvPOK_only(output); |
785 | SvCUR_set(output, outsize - s->stream.avail_out) ; |
786 | } |
787 | else |
788 | output = &PL_sv_undef ; |
789 | XPUSHs(output) ; |
790 | if (GIMME == G_ARRAY) |
791 | XPUSHs(sv_2mortal(newSViv(err))) ; |
792 | |
793 | |
794 | |
795 | void |
796 | flush(s, f=Z_FINISH) |
797 | Compress::Zlib::deflateStream s |
798 | int f |
799 | uLong outsize = NO_INIT |
800 | SV * output = NO_INIT |
801 | int err = Z_OK ; |
802 | PPCODE: |
803 | |
804 | s->stream.avail_in = 0; /* should be zero already anyway */ |
805 | |
806 | /* output = sv_2mortal(newSVpv("", s->bufinc)) ; */ |
807 | output = sv_2mortal(newSV(s->bufinc)) ; |
808 | SvPOK_only(output) ; |
809 | SvCUR_set(output, 0) ; |
810 | outsize = s->bufinc ; |
811 | s->stream.next_out = (Bytef*) SvPVX(output) ; |
812 | s->stream.avail_out = outsize; |
813 | |
814 | /* Check for saved output from deflateParams */ |
815 | if (s->deflateParams_out_valid) { |
816 | *(s->stream.next_out) = s->deflateParams_out_byte; |
817 | ++ s->stream.next_out; |
818 | -- s->stream.avail_out ; |
819 | s->deflateParams_out_valid = FALSE; |
820 | } |
821 | |
822 | for (;;) { |
823 | if (s->stream.avail_out == 0) { |
824 | /* consumed all the available output, so extend it */ |
825 | s->bufinc *= 2 ; |
826 | SvGROW(output, outsize + s->bufinc) ; |
827 | s->stream.next_out = (Bytef*)SvPVX(output) + outsize ; |
828 | outsize += s->bufinc ; |
829 | s->stream.avail_out = s->bufinc ; |
830 | } |
831 | err = deflate(&(s->stream), f); |
832 | |
833 | /* deflate has finished flushing only when it hasn't used up |
834 | * all the available space in the output buffer: |
835 | */ |
836 | if (s->stream.avail_out != 0 || err != Z_OK ) |
837 | break; |
838 | } |
839 | |
840 | err = (err == Z_STREAM_END ? Z_OK : err) ; |
841 | |
842 | if (err == Z_OK) { |
843 | SvPOK_only(output); |
844 | SvCUR_set(output, outsize - s->stream.avail_out) ; |
845 | } |
846 | else |
847 | output = &PL_sv_undef ; |
848 | XPUSHs(output) ; |
849 | if (GIMME == G_ARRAY) |
850 | XPUSHs(sv_2mortal(newSViv(err))) ; |
851 | |
852 | int |
853 | _deflateParams(s, flags, level, strategy, bufsize) |
854 | Compress::Zlib::deflateStream s |
855 | int flags |
856 | int level |
857 | int strategy |
858 | uLong bufsize |
859 | CODE: |
860 | if (flags & 1) |
861 | s->Level = level ; |
862 | if (flags & 2) |
863 | s->Strategy = strategy ; |
864 | if (bufsize) { |
865 | s->bufsize = bufsize; |
866 | s->bufinc = bufsize; |
867 | } |
868 | s->stream.avail_in = 0; |
869 | s->stream.next_out = &(s->deflateParams_out_byte) ; |
870 | s->stream.avail_out = 1; |
871 | RETVAL = deflateParams(&(s->stream), s->Level, s->Strategy); |
872 | s->deflateParams_out_valid = |
873 | (RETVAL == Z_OK && s->stream.avail_out == 0) ; |
874 | OUTPUT: |
875 | RETVAL |
876 | |
877 | |
878 | int |
879 | get_Level(s) |
880 | Compress::Zlib::deflateStream s |
881 | CODE: |
882 | RETVAL = s->Level ; |
883 | OUTPUT: |
884 | RETVAL |
885 | |
886 | int |
887 | get_Strategy(s) |
888 | Compress::Zlib::deflateStream s |
889 | CODE: |
890 | RETVAL = s->Strategy ; |
891 | OUTPUT: |
892 | RETVAL |
893 | |
894 | void |
895 | DESTROY(s) |
896 | Compress::Zlib::deflateStream s |
897 | CODE: |
898 | deflateEnd(&s->stream) ; |
899 | if (s->dictionary) |
900 | SvREFCNT_dec(s->dictionary) ; |
901 | Safefree(s) ; |
902 | |
903 | |
904 | uLong |
905 | dict_adler(s) |
906 | Compress::Zlib::deflateStream s |
907 | CODE: |
908 | RETVAL = s->dict_adler ; |
909 | OUTPUT: |
910 | RETVAL |
911 | |
912 | uLong |
913 | total_in(s) |
914 | Compress::Zlib::deflateStream s |
915 | CODE: |
916 | RETVAL = s->stream.total_in ; |
917 | OUTPUT: |
918 | RETVAL |
919 | |
920 | uLong |
921 | total_out(s) |
922 | Compress::Zlib::deflateStream s |
923 | CODE: |
924 | RETVAL = s->stream.total_out ; |
925 | OUTPUT: |
926 | RETVAL |
927 | |
928 | char* |
929 | msg(s) |
930 | Compress::Zlib::deflateStream s |
931 | CODE: |
932 | RETVAL = s->stream.msg; |
933 | OUTPUT: |
934 | RETVAL |
935 | |
936 | |
937 | MODULE = Compress::Zlib PACKAGE = Compress::Zlib::inflateStream |
938 | |
939 | void |
940 | DispStream(s, message=NULL) |
941 | Compress::Zlib::inflateStream s |
942 | char * message |
943 | |
944 | void |
945 | inflate (s, buf) |
946 | Compress::Zlib::inflateStream s |
947 | SV * buf |
948 | uLong outsize = NO_INIT |
949 | SV * output = NO_INIT |
950 | int err = Z_OK ; |
951 | ALIAS: |
952 | __unc_inflate = 1 |
953 | PPCODE: |
954 | |
955 | /* If the buffer is a reference, dereference it */ |
956 | buf = deRef(buf, "inflate") ; |
957 | |
958 | /* initialise the input buffer */ |
959 | s->stream.next_in = (Bytef*)SvPVX(buf) ; |
960 | s->stream.avail_in = SvCUR(buf) ; |
961 | |
962 | /* and the output buffer */ |
963 | output = sv_2mortal(newSV(s->bufinc+1)) ; |
964 | SvPOK_only(output) ; |
965 | SvCUR_set(output, 0) ; |
966 | outsize = s->bufinc ; |
967 | s->stream.next_out = (Bytef*) SvPVX(output) ; |
968 | s->stream.avail_out = outsize; |
969 | |
970 | while (1) { |
971 | |
972 | if (s->stream.avail_out == 0) { |
973 | s->bufinc *= 2 ; |
974 | SvGROW(output, outsize + s->bufinc+1) ; |
975 | s->stream.next_out = (Bytef*) SvPVX(output) + outsize ; |
976 | outsize += s->bufinc ; |
977 | s->stream.avail_out = s->bufinc ; |
978 | } |
979 | |
980 | err = inflate(&(s->stream), Z_SYNC_FLUSH); |
981 | if (err == Z_BUF_ERROR) { |
982 | if (s->stream.avail_out == 0) |
983 | continue ; |
984 | if (s->stream.avail_in == 0) { |
985 | err = Z_OK ; |
986 | break ; |
987 | } |
988 | } |
989 | |
990 | if (err == Z_NEED_DICT && s->dictionary) { |
991 | s->dict_adler = s->stream.adler ; |
992 | err = inflateSetDictionary(&(s->stream), |
993 | (const Bytef*)SvPVX(s->dictionary), |
994 | SvCUR(s->dictionary)); |
995 | } |
996 | |
997 | if (err != Z_OK) |
998 | break; |
999 | } |
1000 | |
1001 | if (err == Z_OK || err == Z_STREAM_END || err == Z_DATA_ERROR) { |
1002 | unsigned in ; |
1003 | |
1004 | SvPOK_only(output); |
1005 | SvCUR_set(output, outsize - s->stream.avail_out) ; |
1006 | *SvEND(output) = '\0'; |
1007 | |
1008 | /* fix the input buffer */ |
1009 | if (ix == 0) { |
1010 | in = s->stream.avail_in ; |
1011 | SvCUR_set(buf, in) ; |
1012 | if (in) |
1013 | Move(s->stream.next_in, SvPVX(buf), in, char) ; |
1014 | *SvEND(buf) = '\0'; |
1015 | SvSETMAGIC(buf); |
1016 | } |
1017 | } |
1018 | else |
1019 | output = &PL_sv_undef ; |
1020 | XPUSHs(output) ; |
1021 | if (GIMME == G_ARRAY) |
1022 | XPUSHs(sv_2mortal(newSViv(err))) ; |
1023 | |
1024 | int |
1025 | inflateSync (s, buf) |
1026 | Compress::Zlib::inflateStream s |
1027 | SV * buf |
1028 | CODE: |
1029 | |
1030 | /* If the buffer is a reference, dereference it */ |
1031 | buf = deRef(buf, "inflateSync") ; |
1032 | |
1033 | /* initialise the input buffer */ |
1034 | s->stream.next_in = (Bytef*)SvPVX(buf) ; |
1035 | s->stream.avail_in = SvCUR(buf) ; |
1036 | |
1037 | /* inflateSync doesn't create any output */ |
1038 | s->stream.next_out = (Bytef*) NULL; |
1039 | s->stream.avail_out = 0; |
1040 | |
1041 | RETVAL = inflateSync(&(s->stream)); |
1042 | { |
1043 | /* fix the input buffer */ |
1044 | unsigned in = s->stream.avail_in ; |
1045 | |
1046 | SvCUR_set(buf, in) ; |
1047 | if (in) |
1048 | Move(s->stream.next_in, SvPVX(buf), in, char) ; |
1049 | *SvEND(buf) = '\0'; |
1050 | SvSETMAGIC(buf); |
1051 | } |
1052 | OUTPUT: |
1053 | RETVAL |
1054 | |
1055 | void |
1056 | DESTROY(s) |
1057 | Compress::Zlib::inflateStream s |
1058 | CODE: |
1059 | inflateEnd(&s->stream) ; |
1060 | if (s->dictionary) |
1061 | SvREFCNT_dec(s->dictionary) ; |
1062 | Safefree(s) ; |
1063 | |
1064 | |
1065 | uLong |
1066 | dict_adler(s) |
1067 | Compress::Zlib::inflateStream s |
1068 | CODE: |
1069 | RETVAL = s->dict_adler ; |
1070 | OUTPUT: |
1071 | RETVAL |
1072 | |
1073 | uLong |
1074 | total_in(s) |
1075 | Compress::Zlib::inflateStream s |
1076 | CODE: |
1077 | RETVAL = s->stream.total_in ; |
1078 | OUTPUT: |
1079 | RETVAL |
1080 | |
1081 | uLong |
1082 | total_out(s) |
1083 | Compress::Zlib::inflateStream s |
1084 | CODE: |
1085 | RETVAL = s->stream.total_out ; |
1086 | OUTPUT: |
1087 | RETVAL |
1088 | |
1089 | char* |
1090 | msg(s) |
1091 | Compress::Zlib::inflateStream s |
1092 | CODE: |
1093 | RETVAL = s->stream.msg; |
1094 | OUTPUT: |
1095 | RETVAL |
1096 | |
1097 | |