2
* Author : Paul Marquess, <pmqs@cpan.org>
3
* Created : 30 January 2005
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.
12
/* Part of this code is based on the file gzio.c */
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
28
#include "patchlevel.h"
29
#define PERL_REVISION 5
30
#define PERL_VERSION PATCHLEVEL
31
#define PERL_SUBVERSION SUBVERSION
34
#if PERL_REVISION == 5 && (PERL_VERSION < 4 || (PERL_VERSION == 4 && PERL_SUBVERSION <= 75 ))
36
# define PL_sv_undef sv_undef
38
# define PL_curcop curcop
39
# define PL_compiling compiling
44
# define newSVuv newSViv
47
typedef struct di_stream {
53
bool deflateParams_out_valid ;
54
Bytef deflateParams_out_byte;
62
typedef di_stream * deflateStream ;
63
typedef di_stream * Compress__Zlib__deflateStream ;
64
typedef di_stream * inflateStream ;
65
typedef di_stream * Compress__Zlib__inflateStream ;
67
/* typedef gzFile Compress__Zlib__gzFile ; */
68
typedef struct gzType {
75
typedef gzType* Compress__Zlib__gzFile ;
79
#define GZERRNO "Compress::Zlib::gzerrno"
81
#define ZMALLOC(to, typ) ((to = (typ *)safemalloc(sizeof(typ))), \
84
#define adlerInitial adler32(0L, Z_NULL, 0)
85
#define crcInitial crc32(0L, Z_NULL, 0)
88
static const char * const my_z_errmsg[] = {
89
"need dictionary", /* Z_NEED_DICT 2 */
90
"stream end", /* Z_STREAM_END 1 */
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) */
101
#if defined(__SYMBIAN32__)
102
# define NO_WRITEABLE_DATA
105
#define TRACE_DEFAULT 0
107
#ifdef NO_WRITEABLE_DATA
108
#define trace TRACE_DEFAULT
110
static int trace = TRACE_DEFAULT ;
113
/* Dodge PerlIO hiding of these functions. */
118
SetGzErrorNo(int error_no)
120
SetGzErrorNo(error_no)
128
SV * gzerror_sv = perl_get_sv(GZERRNO, FALSE) ;
130
if (error_no == Z_ERRNO) {
132
errstr = Strerror(errno) ;
135
/* errstr = gzerror(fil, &error_no) ; */
136
errstr = (char*) my_z_errmsg[2 - error_no];
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) ;
148
SetGzError(gzFile file)
156
(void)gzerror(file, &error_no) ;
157
SetGzErrorNo(error_no) ;
162
DispHex(void * ptr, int length)
169
char * p = (char*)ptr;
171
for (i = 0; i < length; ++i) {
172
printf(" %02x", 0xFF & *(p+i));
179
DispStream(di_stream * s, char * message)
181
DispStream(s, message)
192
printf("DispStream 0x%p - %s \n", s, message) ;
195
printf(" stream pointer is NULL\n");
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);
203
printf(" msg %s\n", s->stream.msg);
206
printf(" next_in 0x%p", s->stream.next_in);
207
if (s->stream.next_in) {
209
DispHex(s->stream.next_in, 4);
213
printf(" next_out 0x%p", s->stream.next_out);
214
if (s->stream.next_out){
216
DispHex(s->stream.next_out, 4);
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);
237
InitStream(uLong bufsize)
245
ZMALLOC(s, di_stream) ;
248
s->bufsize = bufsize ;
249
s->bufinc = bufsize ;
260
gzreadline(Compress__Zlib__gzFile file, SV * output)
262
gzreadline(file, output)
263
Compress__Zlib__gzFile file ;
270
SV * store = file->buffer ;
273
char *out_ptr = SvPVX(store) ;
278
/* anything left from last time */
279
if ((n = SvCUR(store))) {
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)) { */
286
sv_catpvn(output, out_ptr, p - out_ptr + 1);
288
file->offset += (p - out_ptr + 1) ;
289
n = n - (p - out_ptr + 1);
290
SvCUR_set(store, n) ;
291
return SvCUR(output);
293
else /* no EOL, so append the complete buffer */
294
sv_catpvn(output, out_ptr, n);
299
SvCUR_set(store, 0) ;
301
out_ptr = SvPVX(store) ;
303
n = gzread(file->gz, out_ptr, SIZE) ;
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 ;
310
SvCUR_set(store, n) ;
316
deRef(SV * sv, char * string)
332
croak("%s: buffer parameter is not a SCALAR reference", string);
335
croak("%s: buffer parameter is a reference to a reference", string) ;
344
#include "constants.h"
346
MODULE = Compress::Zlib PACKAGE = Compress::Zlib PREFIX = Zip_
351
INCLUDE: constants.xs
354
/* Check this version of zlib is == 1 */
355
if (zlibVersion()[0] != '1')
356
croak("Compress::Zlib needs zlib version 1.x\n") ;
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) ;
367
#define Zip_zlib_version() (char*)zlib_version
375
RETVAL = ZLIB_VERNUM ;
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 ;
388
DispStream(s, message=NULL)
389
Compress::Zlib::inflateStream s
392
Compress::Zlib::gzFile
398
gz = gzopen(path, mode) ;
400
ZMALLOC(RETVAL, gzType) ;
401
RETVAL->buffer = newSV(SIZE) ;
402
SvPOK_only(RETVAL->buffer) ;
403
SvCUR_set(RETVAL->buffer, 0) ;
406
RETVAL->closed = FALSE ;
411
SetGzErrorNo(errno ? Z_ERRNO : Z_MEM_ERROR) ;
417
Compress::Zlib::gzFile
418
gzdopen_(fh, mode, offset)
425
lseek(fh, offset, 0) ;
426
gz = gzdopen(fh, mode) ;
428
ZMALLOC(RETVAL, gzType) ;
429
RETVAL->buffer = newSV(SIZE) ;
430
SvPOK_only(RETVAL->buffer) ;
431
SvCUR_set(RETVAL->buffer, 0) ;
434
RETVAL->closed = FALSE ;
439
SetGzErrorNo(errno ? Z_ERRNO : Z_MEM_ERROR) ;
445
MODULE = Compress::Zlib PACKAGE = Compress::Zlib::gzFile PREFIX = Zip_
447
#define Zip_gzread(file, buf, len) gzread(file->gz, bufp, len)
450
Zip_gzread(file, buf, len=4096)
451
Compress::Zlib::gzFile file
458
if (SvREADONLY(buf) && PL_curcop != &PL_compiling)
459
croak("gzread: buffer parameter is read-only");
460
SvUPGRADE(buf, SVt_PV);
463
/* any left over from gzreadline ? */
464
if ((bufsize = SvCUR(file->buffer)) > 0) {
477
sv_catpvn(buf, SvPVX(file->buffer) + file->offset, movesize);
479
file->offset += movesize ;
480
SvCUR_set(file->buffer, bufsize - movesize) ;
484
bufp = (Byte*)SvGROW(buf, bufsize+len+1);
485
RETVAL = gzread(file->gz, ((Bytef*)bufp)+bufsize, len) ;
486
SetGzError(file->gz) ;
489
SvCUR_set(buf, RETVAL) ;
498
gzreadline(file, buf)
499
Compress::Zlib::gzFile file
503
if (SvREADONLY(buf) && PL_curcop != &PL_compiling)
504
croak("gzreadline: buffer parameter is read-only");
505
SvUPGRADE(buf, SVt_PV);
507
/* sv_setpvn(buf, "", SIZE) ; */
510
RETVAL = gzreadline(file, buf) ;
511
SetGzError(file->gz) ;
517
/* SvCUR(buf) = RETVAL; */
518
/* Don't need to explicitly terminate with '\0', because
519
sv_catpvn aready has */
522
#define Zip_gzwrite(file, buf) gzwrite(file->gz, buf, (unsigned)len)
524
Zip_gzwrite(file, buf)
525
Compress::Zlib::gzFile file
527
voidp buf = (voidp)SvPV(ST(1), len) ;
529
SetGzError(file->gz) ;
531
#define Zip_gzflush(file, flush) gzflush(file->gz, flush)
533
Zip_gzflush(file, flush)
534
Compress::Zlib::gzFile file
537
SetGzError(file->gz) ;
539
#define Zip_gzclose(file) file->closed ? 0 : gzclose(file->gz)
542
Compress::Zlib::gzFile file
544
file->closed = TRUE ;
545
SetGzErrorNo(RETVAL) ;
548
#define Zip_gzeof(file) gzeof(file->gz)
551
Compress::Zlib::gzFile file
554
croak("gzeof needs zlib 1.0.6 or better") ;
556
RETVAL = gzeof(file->gz);
562
#define Zip_gzsetparams(file,l,s) gzsetparams(file->gz,l,s)
564
Zip_gzsetparams(file, level, strategy)
565
Compress::Zlib::gzFile file
570
croak("gzsetparams needs zlib 1.0.6 or better") ;
572
RETVAL = gzsetparams(file->gz, level, strategy);
579
Compress::Zlib::gzFile file
583
SvREFCNT_dec(file->buffer) ;
584
safefree((char*)file) ;
586
#define Zip_gzerror(file) (char*)gzerror(file->gz, &errnum)
590
Compress::Zlib::gzFile file
593
sv_setiv(ST(0), errnum) ;
598
MODULE = Compress::Zlib PACKAGE = Compress::Zlib PREFIX = Zip_
601
#define Zip_adler32(buf, adler) adler32(adler, buf, (uInt)len)
604
Zip_adler32(buf, adler=adlerInitial)
605
uLong adler = NO_INIT
607
Bytef * buf = NO_INIT
610
/* If the buffer is a reference, dereference it */
611
sv = deRef(sv, "adler32") ;
612
buf = (Byte*)SvPV(sv, len) ;
615
adler = adlerInitial;
616
else if (SvOK(ST(1)))
617
adler = SvUV(ST(1)) ;
619
adler = adlerInitial;
621
#define Zip_crc32(buf, crc) crc32(crc, buf, (uInt)len)
624
Zip_crc32(buf, crc=crcInitial)
627
Bytef * buf = NO_INIT
630
/* If the buffer is a reference, dereference it */
631
sv = deRef(sv, "crc32") ;
632
buf = (Byte*)SvPV(sv, len) ;
636
else if (SvOK(ST(1)))
641
MODULE = Compress::Zlib PACKAGE = Compress::Zlib
644
_deflateInit(level, method, windowBits, memLevel, strategy, bufsize, dictionary)
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)) ) {
664
s->WindowBits = windowBits;
665
s->MemLevel = memLevel;
666
s->Strategy = strategy;
668
err = deflateInit2(&(s->stream), level,
669
method, windowBits, memLevel, strategy);
671
/* Check if a dictionary has been specified */
672
if (err == Z_OK && SvCUR(dictionary)) {
673
err = deflateSetDictionary(&(s->stream), (const Bytef*) SvPVX(dictionary),
675
s->dict_adler = s->stream.adler ;
687
XPUSHs(sv_setref_pv(sv_newmortal(),
688
"Compress::Zlib::deflateStream", (void*)s));
689
if (GIMME == G_ARRAY)
690
XPUSHs(sv_2mortal(newSViv(err))) ;
693
_inflateInit(windowBits, bufsize, dictionary)
703
warn("in _inflateInit(windowBits=%d, bufsize=%d, dictionary=%d\n",
704
windowBits, bufsize, SvCUR(dictionary)) ;
705
if ((s = InitStream(bufsize)) ) {
707
s->WindowBits = windowBits;
709
err = inflateInit2(&(s->stream), windowBits);
715
else if (SvCUR(dictionary)) {
716
/* Dictionary specified - take a copy for use in inflate */
717
s->dictionary = newSVsv(dictionary) ;
723
XPUSHs(sv_setref_pv(sv_newmortal(),
724
"Compress::Zlib::inflateStream", (void*)s));
725
if (GIMME == G_ARRAY)
726
XPUSHs(sv_2mortal(newSViv(err))) ;
730
MODULE = Compress::Zlib PACKAGE = Compress::Zlib::deflateStream
733
DispStream(s, message=NULL)
734
Compress::Zlib::deflateStream s
739
Compress::Zlib::deflateStream s
741
uLong outsize = NO_INIT
742
SV * output = NO_INIT
746
/* If the buffer is a reference, dereference it */
747
buf = deRef(buf, "deflate") ;
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) ;
754
/* and the output buffer */
755
/* output = sv_2mortal(newSVpv("", s->bufinc)) ; */
756
output = sv_2mortal(newSV(s->bufinc)) ;
758
SvCUR_set(output, 0) ;
759
outsize = s->bufinc ;
760
s->stream.next_out = (Bytef*) SvPVX(output) ;
761
s->stream.avail_out = outsize;
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;
771
while (s->stream.avail_in != 0) {
773
if (s->stream.avail_out == 0) {
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 ;
780
err = deflate(&(s->stream), Z_NO_FLUSH);
787
SvCUR_set(output, outsize - s->stream.avail_out) ;
790
output = &PL_sv_undef ;
792
if (GIMME == G_ARRAY)
793
XPUSHs(sv_2mortal(newSViv(err))) ;
799
Compress::Zlib::deflateStream s
801
uLong outsize = NO_INIT
802
SV * output = NO_INIT
806
s->stream.avail_in = 0; /* should be zero already anyway */
808
/* output = sv_2mortal(newSVpv("", s->bufinc)) ; */
809
output = sv_2mortal(newSV(s->bufinc)) ;
811
SvCUR_set(output, 0) ;
812
outsize = s->bufinc ;
813
s->stream.next_out = (Bytef*) SvPVX(output) ;
814
s->stream.avail_out = outsize;
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;
825
if (s->stream.avail_out == 0) {
826
/* consumed all the available output, so extend it */
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 ;
833
err = deflate(&(s->stream), f);
835
/* deflate has finished flushing only when it hasn't used up
836
* all the available space in the output buffer:
838
if (s->stream.avail_out != 0 || err != Z_OK )
842
err = (err == Z_STREAM_END ? Z_OK : err) ;
846
SvCUR_set(output, outsize - s->stream.avail_out) ;
849
output = &PL_sv_undef ;
851
if (GIMME == G_ARRAY)
852
XPUSHs(sv_2mortal(newSViv(err))) ;
855
_deflateParams(s, flags, level, strategy, bufsize)
856
Compress::Zlib::deflateStream s
865
s->Strategy = strategy ;
867
s->bufsize = bufsize;
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) ;
882
Compress::Zlib::deflateStream s
890
Compress::Zlib::deflateStream s
892
RETVAL = s->Strategy ;
898
Compress::Zlib::deflateStream s
900
deflateEnd(&s->stream) ;
902
SvREFCNT_dec(s->dictionary) ;
908
Compress::Zlib::deflateStream s
910
RETVAL = s->dict_adler ;
916
Compress::Zlib::deflateStream s
918
RETVAL = s->stream.total_in ;
924
Compress::Zlib::deflateStream s
926
RETVAL = s->stream.total_out ;
932
Compress::Zlib::deflateStream s
934
RETVAL = s->stream.msg;
939
MODULE = Compress::Zlib PACKAGE = Compress::Zlib::inflateStream
942
DispStream(s, message=NULL)
943
Compress::Zlib::inflateStream s
948
Compress::Zlib::inflateStream s
950
uLong outsize = NO_INIT
951
SV * output = NO_INIT
957
/* If the buffer is a reference, dereference it */
958
buf = deRef(buf, "inflate") ;
960
/* initialise the input buffer */
961
s->stream.next_in = (Bytef*)SvPVX(buf) ;
962
s->stream.avail_in = SvCUR(buf) ;
964
/* and the output buffer */
965
output = sv_2mortal(newSV(s->bufinc+1)) ;
967
SvCUR_set(output, 0) ;
968
outsize = s->bufinc ;
969
s->stream.next_out = (Bytef*) SvPVX(output) ;
970
s->stream.avail_out = outsize;
974
if (s->stream.avail_out == 0) {
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 ;
982
err = inflate(&(s->stream), Z_SYNC_FLUSH);
983
if (err == Z_BUF_ERROR) {
984
if (s->stream.avail_out == 0)
986
if (s->stream.avail_in == 0) {
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));
1003
if (err == Z_OK || err == Z_STREAM_END || err == Z_DATA_ERROR) {
1007
SvCUR_set(output, outsize - s->stream.avail_out) ;
1008
*SvEND(output) = '\0';
1010
/* fix the input buffer */
1012
in = s->stream.avail_in ;
1013
SvCUR_set(buf, in) ;
1015
Move(s->stream.next_in, SvPVX(buf), in, char) ;
1021
output = &PL_sv_undef ;
1023
if (GIMME == G_ARRAY)
1024
XPUSHs(sv_2mortal(newSViv(err))) ;
1027
inflateSync (s, buf)
1028
Compress::Zlib::inflateStream s
1032
/* If the buffer is a reference, dereference it */
1033
buf = deRef(buf, "inflateSync") ;
1035
/* initialise the input buffer */
1036
s->stream.next_in = (Bytef*)SvPVX(buf) ;
1037
s->stream.avail_in = SvCUR(buf) ;
1039
/* inflateSync doesn't create any output */
1040
s->stream.next_out = (Bytef*) NULL;
1041
s->stream.avail_out = 0;
1043
RETVAL = inflateSync(&(s->stream));
1045
/* fix the input buffer */
1046
unsigned in = s->stream.avail_in ;
1048
SvCUR_set(buf, in) ;
1050
Move(s->stream.next_in, SvPVX(buf), in, char) ;
1059
Compress::Zlib::inflateStream s
1061
inflateEnd(&s->stream) ;
1063
SvREFCNT_dec(s->dictionary) ;
1069
Compress::Zlib::inflateStream s
1071
RETVAL = s->dict_adler ;
1077
Compress::Zlib::inflateStream s
1079
RETVAL = s->stream.total_in ;
1085
Compress::Zlib::inflateStream s
1087
RETVAL = s->stream.total_out ;
1093
Compress::Zlib::inflateStream s
1095
RETVAL = s->stream.msg;