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