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