File Coverage

blib/lib/IO/Buffered/Size.pm
Criterion Covered Total %
statement 53 61 86.8
branch 14 20 70.0
condition 10 18 55.5
subroutine 9 12 75.0
pod 7 7 100.0
total 93 118 78.8


line stmt bran cond sub pod time code
1             package IO::Buffered::Size;
2 8     8   38 use strict;
  8         15  
  8         279  
3 8     8   37 use warnings;
  8         11  
  8         178  
4 8     8   36 use Carp;
  8         14  
  8         568  
5              
6 8     8   39 use base ("IO::Buffered");
  8         17  
  8         709  
7              
8             # FIXME: Write documentation
9              
10             our $VERSION = '1.00';
11              
12             =head1 NAME
13              
14             IO::Buffered::Size - Size buffering based on pack templates
15              
16             =head1 DESCRIPTION
17              
18             =head1 SYNOPSIS
19              
20             =head1 METHODS
21              
22             =over
23              
24             =cut
25              
26 8     8   44 use base "Exporter";
  8         14  
  8         6803  
27              
28             our @EXPORT_OK = qw();
29              
30             =item new()
31              
32             =cut
33              
34             sub new {
35 8     8 1 18 my ($class, $args, %opts) = @_;
36            
37 8 100       203 croak "Args should be an array reference" if ref $args ne 'ARRAY';
38              
39 7         12 my ($template, $offset) = (@{$args}, 0); # Offset defaults to 0
  7         15  
40              
41             # Check if $template is a string, has no * and only returns one number
42 7 100 66     565 croak "Template should be a string" if !(defined $template and
      100        
43             ref $template eq '' and $template !~ /^\d+$/);
44 4 50       16 croak "Template should not contain *" if $template =~ /\*/;
45 4 50       23 croak "Template should only return one number: $template"
46             if ref unpack($template, "x" x 30) ne '';
47            
48             # Check if $offset is a number
49 4 100 100     550 croak "Offset should be a number" if !(defined $offset
50             and $offset =~ /^-?\d+$/);
51            
52             # Check that $regexp is a Regexp or a non empty string
53 1 50 0     6 croak "Option MaxSize should be a positiv integer" if $opts{MaxSize} and !(
      33        
54             $opts{MaxSize} =~ /^\d+$/ and $opts{MaxSize} > 0);
55              
56 1         24 my %self = (
57             buffer => '',
58             offset => $offset,
59             minsize => length(pack($template, 0)), # Get minimun size
60             template => $template,
61             maxsize => $opts{MaxSize},
62             );
63            
64 1   33     27 return bless \%self, (ref $class || $class);
65             }
66              
67              
68             =item flush($str, ...)
69              
70             =cut
71              
72             sub flush {
73 0     0 1 0 my $self = shift;
74 0         0 $self->{buffer} = join ('', @_);
75             }
76              
77             =item buffer()
78              
79             =cut
80              
81             sub buffer {
82 0     0 1 0 my $self = shift;
83 0         0 return $self->{buffer};
84             }
85              
86             =item write($str, ...)
87              
88             =cut
89              
90             sub write {
91 2     2 1 1194 my $self = shift;
92 2         7 my $str = join ('', @_);
93            
94 2 50       15 if(my $maxsize = $self->{maxsize}) {
95 0         0 my $length = length($str) + length($self->{buffer});
96 0 0       0 if($length > $maxsize) {
97 0         0 croak "Buffer overrun";
98             }
99             }
100              
101 2         8 $self->{buffer} .= $str;
102             }
103              
104             =item read()
105              
106             =cut
107              
108             sub read {
109 4     4 1 11 my ($self) = (@_);
110 4         8 my $template = $self->{template};
111 4         6 my $offset = $self->{offset};
112 4         6 my $minsize = $self->{minsize};
113 4         5 my @records;
114              
115 4         14 while(length $self->{buffer} > $minsize) {
116 5         15 my $length = (unpack($template, $self->{buffer}))[0]+$offset;
117 5         10 my $datastart = length(pack($template, $length));
118            
119 5 100       14 if(length $self->{buffer} >= $length + $datastart) {
120 3         9 push(@records, substr($self->{buffer}, $datastart, $length));
121 3         12 substr($self->{buffer}, 0, $length+$datastart) = '';
122             } else {
123 2         5 last;
124             }
125             }
126 4         18 return @records;
127             }
128              
129             =item returns_last()
130              
131             =cut
132              
133             sub returns_last {
134 0     0 1 0 return 1;
135             }
136              
137             =item read_last()
138              
139             =cut
140              
141             sub read_last {
142 2     2 1 734 my ($self) = @_;
143 2         6 my @records = $self->read();
144            
145 2         5 my $template = $self->{template};
146 2         4 my $offset = $self->{offset};
147            
148 2 100       56 if($self->{buffer} ne '') {
149 1         4 my $length = (unpack($template, $self->{buffer}))[0]+$offset;
150 1         4 my $datastart = length(pack($template, $length));
151            
152 1         3 push(@records, substr($self->{buffer}, $datastart));
153 1         2 $self->{buffer} = '';
154             }
155              
156 2         12 return @records;
157             }
158              
159             =back
160              
161             =head1 AUTHOR
162              
163             Troels Liebe Bentsen
164              
165             =head1 COPYRIGHT
166              
167             Copyright(C) 2008 Troels Liebe Bentsen
168              
169             This library is free software; you can redistribute it and/or modify
170             it under the same terms as Perl itself.
171              
172             =cut
173              
174             1;
175