File Coverage

blib/lib/Data/Transform/Zlib.pm
Criterion Covered Total %
statement 63 66 95.4
branch 16 26 61.5
condition 5 10 50.0
subroutine 11 11 100.0
pod 2 2 100.0
total 97 115 84.3


line stmt bran cond sub pod time code
1             package Data::Transform::Zlib;
2 1     1   30458 use strict;
  1         2  
  1         36  
3 1     1   6 use warnings;
  1         2  
  1         30  
4              
5 1     1   5 use Carp qw(croak);
  1         7  
  1         91  
6 1     1   5 use Scalar::Util qw(blessed);
  1         1  
  1         132  
7 1     1   3725 use Compress::Raw::Zlib qw(Z_OK Z_STREAM_END Z_FINISH Z_SYNC_FLUSH);
  1         7046  
  1         166  
8              
9 1     1   10 use base qw(Data::Transform);
  1         2  
  1         1010  
10              
11             our $VERSION = '0.02';
12              
13             =head1 NAME
14              
15             Data::Transform::Zlib - A Filter for RFC195[0-2]
16              
17             =head1 DESCRIPTION
18              
19             Data::Transform::Zlib provides a filter for performing (de-)compression
20             using L. Since it is just a wrapper around that
21             module, it supports the same features.
22              
23             =head1 METHODS
24              
25             Data::Transform::Zlib implements the standard Data::Transform API. Only
26             additions and differences are documented here.
27              
28             =cut
29              
30             sub BUFFER () { 0 }
31             sub DEFLATER () { 1 }
32             sub DEFLATE_OPTIONS () { 2 }
33             sub INFLATER () { 3 }
34             sub INFLATE_OPTIONS () { 4 }
35              
36             =head2 new
37              
38             new() creates a new object. It accepts the following named parameters:
39              
40             =over 2
41              
42             =item inflate
43              
44             A hashref containing parameters suitable to pass to Compress::Raw::Zlib::Inflate().
45              
46             =item deflate
47              
48             A hashref containing parameters suitable to pass to Compress::Raw::Zlib::Deflate().
49              
50             =back
51              
52             The only really interesting thing to set here is -WindowBits. If you
53             set it to WANT_GZIP (symbol exported by Compress::Raw::Zlib), it will
54             use gzip compression instead of zlib.
55              
56             See the L documentation for more details.
57              
58             =cut
59              
60             sub new {
61 2     2 1 1053 my $type = shift;
62              
63 2         6 my $self = [
64             [],
65             ];
66              
67 2 50       9 croak "$type requires an even number of parameters" if @_ % 2;
68 2         5 my %param = @_;
69              
70 2   50     16 my $deflate_options = $self->[DEFLATE_OPTIONS] = $param{deflate} || {};
71 2 50       19 $self->[DEFLATER] = Compress::Raw::Zlib::Deflate->new(%$deflate_options)
72             or croak "Couldn't create deflater object";
73 2   50     1529 my $inflate_options = $self->[INFLATE_OPTIONS] = $param{inflate} || {};
74 2 50       21 $self->[INFLATER] = Compress::Raw::Zlib::Inflate->new(%$inflate_options)
75             or croak "Couldn't create inflater object";
76              
77 2         597 return bless $self, $type;
78             }
79              
80             sub clone {
81 1     1 1 6 my $self = shift;
82 1         8 my $deflate_options = $self->[DEFLATE_OPTIONS];
83 1         5 my $deflater = Compress::Raw::Zlib::Deflate->new( %$deflate_options );
84 1         607 my $inflate_options = $self->[INFLATE_OPTIONS];
85 1         7 my $inflater = Compress::Raw::Zlib::Inflate->new( %$inflate_options );
86 1         326 my $nself = [
87             [],
88             $deflater,
89             $deflate_options,
90             $inflater,
91             $inflate_options,
92             ];
93 1         7 return bless $nself, ref $self;
94             }
95              
96             sub _handle_get_data {
97 17     17   1593 my ($self, $data) = @_;
98              
99 17 100       51 return unless $data;
100              
101 6         6 my $out;
102 6         83 my $status = $self->[INFLATER]->inflate($data, $out);
103 6 50 66     21 unless ($status == Z_OK or $status == Z_STREAM_END) {
104 0         0 return Data::Transform::Meta::Error->new(
105             "Couldn\'t inflate buffer ($status)"
106             );
107             }
108 6 100       52 if ($status == Z_STREAM_END) {
109 3         12 $self->[INFLATER] = Compress::Raw::Zlib::Inflate->new(%{ $self->[INFLATE_OPTIONS]});
  3         14  
110             }
111 6 100       830 return $out if $out;
112 3         7 return;
113             }
114              
115             sub _handle_put_meta {
116 3     3   38 my ($self, $meta) = @_;
117 3         4 my ($type, @ret);
118 3 50       20 $type = Z_FINISH if ($meta->isa('Data::Transform::Meta::EOF'));
119 3 50 33     34 $type = Z_SYNC_FLUSH if (defined $meta->data and $meta->data eq 'sync');
120 3 50       33 if (defined $type) {
121 3         5 my ($fout,$fstat);
122 3         125 $fstat = $self->[DEFLATER]->flush($fout, $type);
123 3         6 push (@ret, $fout);
124 3 50       10 unless ( $fstat == Z_OK ) {
125 0         0 warn "Error flushing data ($fstat)";
126             }
127 3 50       16 if ($type == Z_FINISH) {
128 3         13 $self->[DEFLATER] = Compress::Raw::Zlib::Deflate->new(
129 3         13 %{$self->[DEFLATE_OPTIONS]}
130             );
131             }
132             }
133 3         1903 push @ret, $meta;
134 3         17 return @ret;
135             }
136              
137             sub _handle_put_data {
138 5     5   2593 my ($self, $data) = @_;
139              
140 5         8 my ($dstat, $dout);
141 5         45 $dstat = $self->[DEFLATER]->deflate($data, $dout);
142 5 50       21 unless ($dstat == Z_OK) {
143 0         0 warn "Error deflating data ($dstat)";
144             }
145 5         60 return $dout;
146             }
147              
148             1;
149              
150             =head1 METADATA
151              
152             Due to how the zlib protocol works, it is important that you don't forget
153             to close the stream by sending a L packet when
154             you're writing data. Otherwise the filter might be holding back data while
155             waiting to see if additional data may help compression.
156              
157             In case you're using this in a request/response protocol like XMPP (with
158             stream compression enabled), you will also have to send a
159             L packet with the string "sync" as the content after
160             each request/response. This makes the filter flush what is in its buffer,
161             so you can be sure your request or response gets sent out. Otherwise,
162             the filter might be waiting for more input to see whether it can compress
163             the data even better, while you need the packet sent so you can get an
164             answer from the remote side.
165              
166             =head1 AUTHOR
167              
168             Data::Transform::Zlib was adapted from the POE::Filter::Zlib filter
169             which was written by Chris Williams
170              
171             Martijn van Beers did the adapting and maintains it.
172              
173             =head1 LICENSE
174              
175             Copyright C<(c)> Chris Williams and Martijn van Beers.
176              
177             This program is free software; you can redistribute it and/or modify it under the terms of the GNU GPL, version 3.0 or higher.
178              
179             =head1 SEE ALSO
180              
181             L
182              
183             L
184              
185             =cut
186