File Coverage

blib/lib/IO/Compress/Zlib/Extra.pm
Criterion Covered Total %
statement 74 89 83.1
branch 44 52 84.6
condition 6 9 66.6
subroutine 9 10 90.0
pod 0 6 0.0
total 133 166 80.1


line stmt bran cond sub pod time code
1             package IO::Compress::Zlib::Extra;
2              
3             require 5.006 ;
4              
5 84     84   511 use strict ;
  84         141  
  84         2368  
6 84     84   377 use warnings;
  84         147  
  84         1810  
7 84     84   365 use bytes;
  84         150  
  84         362  
8              
9             our ($VERSION, @ISA, @EXPORT_OK, %EXPORT_TAGS);
10              
11             $VERSION = '2.204';
12              
13 84     84   8924 use IO::Compress::Gzip::Constants 2.204 ;
  84         1381  
  84         81229  
14              
15             sub ExtraFieldError
16             {
17 24     24 0 68 return $_[0];
18 0         0 return "Error with ExtraField Parameter: $_[0]" ;
19             }
20              
21             sub validateExtraFieldPair
22             {
23 910     910 0 1191 my $pair = shift ;
24 910         1183 my $strict = shift;
25 910         1045 my $gzipMode = shift ;
26              
27 910 50 33     3062 return ExtraFieldError("Not an array ref")
28             unless ref $pair && ref $pair eq 'ARRAY';
29              
30 910 100       1712 return ExtraFieldError("SubField must have two parts")
31             unless @$pair == 2 ;
32              
33 908 100       1690 return ExtraFieldError("SubField ID is a reference")
34             if ref $pair->[0] ;
35              
36 907 100       1440 return ExtraFieldError("SubField Data is a reference")
37             if ref $pair->[1] ;
38              
39             # ID is exactly two chars
40 905 100       1567 return ExtraFieldError("SubField ID not two chars long")
41             unless length $pair->[0] == GZIP_FEXTRA_SUBFIELD_ID_SIZE ;
42              
43             # Check that the 2nd byte of the ID isn't 0
44 901 100 66     3204 return ExtraFieldError("SubField ID 2nd byte is 0x00")
      100        
45             if $strict && $gzipMode && substr($pair->[0], 1, 1) eq "\x00" ;
46              
47 898 100       1620 return ExtraFieldError("SubField Data too long")
48             if length $pair->[1] > GZIP_FEXTRA_SUBFIELD_MAX_SIZE ;
49              
50              
51 897         1348 return undef ;
52             }
53              
54             sub parseRawExtra
55             {
56 673     673 0 1100 my $data = shift ;
57 673         915 my $extraRef = shift;
58 673         864 my $strict = shift;
59 673         828 my $gzipMode = shift ;
60              
61             #my $lax = shift ;
62              
63             #return undef
64             # if $lax ;
65              
66 673         879 my $XLEN = length $data ;
67              
68 673 100       1336 return ExtraFieldError("Too Large")
69             if $XLEN > GZIP_FEXTRA_MAX_SIZE;
70              
71 672         1256 my $offset = 0 ;
72 672         1235 while ($offset < $XLEN) {
73              
74 877 100       1547 return ExtraFieldError("Truncated in FEXTRA Body Section")
75             if $offset + GZIP_FEXTRA_SUBFIELD_HEADER_SIZE > $XLEN ;
76              
77 875         1435 my $id = substr($data, $offset, GZIP_FEXTRA_SUBFIELD_ID_SIZE);
78 875         1056 $offset += GZIP_FEXTRA_SUBFIELD_ID_SIZE;
79              
80 875         1563 my $subLen = unpack("v", substr($data, $offset,
81             GZIP_FEXTRA_SUBFIELD_LEN_SIZE));
82 875         1093 $offset += GZIP_FEXTRA_SUBFIELD_LEN_SIZE ;
83              
84 875 100       1604 return ExtraFieldError("Truncated in FEXTRA Body Section")
85             if $offset + $subLen > $XLEN ;
86              
87 871         2473 my $bad = validateExtraFieldPair( [$id,
88             substr($data, $offset, $subLen)],
89             $strict, $gzipMode );
90 871 100       1808 return $bad if $bad ;
91 869 100       2431 push @$extraRef, [$id => substr($data, $offset, $subLen)]
92             if defined $extraRef;;
93              
94 869         1728 $offset += $subLen ;
95             }
96              
97              
98 664         1250 return undef ;
99             }
100              
101             sub findID
102             {
103 0     0 0 0 my $id_want = shift ;
104 0         0 my $data = shift;
105              
106 0         0 my $XLEN = length $data ;
107              
108 0         0 my $offset = 0 ;
109 0         0 while ($offset < $XLEN) {
110              
111             return undef
112 0 0       0 if $offset + GZIP_FEXTRA_SUBFIELD_HEADER_SIZE > $XLEN ;
113              
114 0         0 my $id = substr($data, $offset, GZIP_FEXTRA_SUBFIELD_ID_SIZE);
115 0         0 $offset += GZIP_FEXTRA_SUBFIELD_ID_SIZE;
116              
117 0         0 my $subLen = unpack("v", substr($data, $offset,
118             GZIP_FEXTRA_SUBFIELD_LEN_SIZE));
119 0         0 $offset += GZIP_FEXTRA_SUBFIELD_LEN_SIZE ;
120              
121             return undef
122 0 0       0 if $offset + $subLen > $XLEN ;
123              
124 0 0       0 return substr($data, $offset, $subLen)
125             if $id eq $id_want ;
126              
127 0         0 $offset += $subLen ;
128             }
129              
130 0         0 return undef ;
131             }
132              
133              
134             sub mkSubField
135             {
136 393     393 0 581 my $id = shift ;
137 393         516 my $data = shift ;
138              
139 393         1327 return $id . pack("v", length $data) . $data ;
140             }
141              
142             sub parseExtraField
143             {
144 82     82 0 140 my $dataRef = $_[0];
145 82         124 my $strict = $_[1];
146 82         115 my $gzipMode = $_[2];
147             #my $lax = @_ == 2 ? $_[1] : 1;
148              
149              
150             # ExtraField can be any of
151             #
152             # -ExtraField => $data
153             #
154             # -ExtraField => [$id1, $data1,
155             # $id2, $data2]
156             # ...
157             # ]
158             #
159             # -ExtraField => [ [$id1 => $data1],
160             # [$id2 => $data2],
161             # ...
162             # ]
163             #
164             # -ExtraField => { $id1 => $data1,
165             # $id2 => $data2,
166             # ...
167             # }
168              
169 82 100       190 if ( ! ref $dataRef ) {
170              
171             return undef
172 48 100       131 if ! $strict;
173              
174 30         77 return parseRawExtra($dataRef, undef, 1, $gzipMode);
175             }
176              
177 34         55 my $data = $dataRef;
178 34         57 my $out = '' ;
179              
180 34 100       128 if (ref $data eq 'ARRAY') {
    100          
181 27 100       79 if (ref $data->[0]) {
182              
183 8         17 foreach my $pair (@$data) {
184 10 100       35 return ExtraFieldError("Not list of lists")
185             unless ref $pair eq 'ARRAY' ;
186              
187 8         20 my $bad = validateExtraFieldPair($pair, $strict, $gzipMode) ;
188 8 100       25 return $bad if $bad ;
189              
190 3         9 $out .= mkSubField(@$pair);
191             }
192             }
193             else {
194 19 100       71 return ExtraFieldError("Not even number of elements")
195             unless @$data % 2 == 0;
196              
197 18         95 for (my $ix = 0; $ix <= @$data -1 ; $ix += 2) {
198 23         101 my $bad = validateExtraFieldPair([$data->[$ix],
199             $data->[$ix+1]],
200             $strict, $gzipMode) ;
201 23 100       70 return $bad if $bad ;
202              
203 20         77 $out .= mkSubField($data->[$ix], $data->[$ix+1]);
204             }
205             }
206             }
207             elsif (ref $data eq 'HASH') {
208 6         31 while (my ($id, $info) = each %$data) {
209 8         26 my $bad = validateExtraFieldPair([$id, $info], $strict, $gzipMode);
210 8 100       33 return $bad if $bad ;
211              
212 5         13 $out .= mkSubField($id, $info);
213             }
214             }
215             else {
216 1         5 return ExtraFieldError("Not a scalar, array ref or hash ref") ;
217             }
218              
219 19 50       55 return ExtraFieldError("Too Large")
220             if length $out > GZIP_FEXTRA_MAX_SIZE;
221              
222 19         37 $_[0] = $out ;
223              
224 19         45 return undef;
225             }
226              
227             1;
228              
229             __END__