File Coverage

blib/lib/IO/Handle/Rewind.pm
Criterion Covered Total %
statement 45 50 90.0
branch 10 16 62.5
condition 1 3 33.3
subroutine 10 11 90.9
pod 5 5 100.0
total 71 85 83.5


line stmt bran cond sub pod time code
1             package IO::Handle::Rewind;
2              
3 2     2   23214 use strict;
  2         4  
  2         76  
4 2     2   12 use Carp qw(croak);
  2         4  
  2         124  
5 2     2   118 use base qw(Class::Accessor);
  2         8  
  2         2003  
6              
7             =head1 NAME
8              
9             IO::Handle::Rewind - pretend to rewind filehandles
10              
11             =head1 VERSION
12              
13             0.06
14              
15             =cut
16              
17             our $VERSION = '0.06';
18              
19             =head1 DESCRIPTION
20              
21             IO::Handle::Rewind wraps any IO::Handle object in a soft,
22             fluffy coat.
23              
24             =head1 METHODS
25              
26             Delegates most methods to the wrapped object.
27              
28             =head3 C<< IO::Handle::Rewind->new($obj) >>
29              
30             Return an IO::Handle::Rewind object wrapping the passed-in
31             IO::Handle.
32              
33             =head3 C<< $re->rewind(@lines, $lines) >>
34              
35             Further calls to C<< readline >>, C<< getline >>, or C<<
36             getlines >> will read from the passed-in array/arrayrefs
37             before actually reading further from the filehandle.
38              
39             Despite the name, this does not seek the filehandle.
40              
41             =head3 C<< $re->getline >>
42              
43             =head3 C<< $re->getlines >>
44              
45             =head3 C<< $re->readline >>
46              
47             See documentation for C<< rewind >>.
48              
49             =head1 SEE ALSO
50              
51             L
52              
53             =head1 AUTHOR
54              
55             Hans Dieter Pearcey
56              
57             =head1 LICENSE
58              
59             Copyright (C) 2005, Hans Dieter Pearcey.
60              
61             Available under the same terms as Perl itself.
62              
63             =cut
64              
65             __PACKAGE__->mk_accessors(qw(rewound obj));
66              
67             sub _delegate {
68 2     2   15 my ($class, @meths) = @_;
69 2         4 for my $meth (@meths) {
70 2     2   4769 no strict 'refs';
  2         4  
  2         1019  
71 54         242 *{$class . "::" . $meth} = sub {
72 0     0   0 my $self = shift;
73 0         0 return $self->obj->$meth(@_);
74             }
75 54         178 }
76             }
77              
78             # XXX I'm not sure all of these make sense to delegate
79              
80             my @meths = qw(fdopen close opened fileno getc eof print
81             printf truncate read sysread write syswrite
82             stat autoflush input_line_number
83             format_page_number format_lines_per_page
84             format_lines_left format_name format_top_name
85             formline format_write fcntl ioctl constant
86             printflush);
87              
88             __PACKAGE__->_delegate(@meths);
89              
90             sub new {
91 1     1 1 2013 my ($class, $obj, $opt) = @_;
92            
93 1 50       13 $obj->isa('IO::Handle') or croak "Can't wrap non-IO::Handle object: $obj";
94              
95 1         3 my $self = bless {} => $class;
96              
97 1         4 $self->obj($obj);
98            
99 1         21 return $self;
100             }
101              
102             sub rewind {
103 2     2 1 455 my ($self, @lines) = @_;
104 2         8 $self->rewound([@lines]);
105             }
106              
107             sub getline {
108 2     2 1 12 my $self = shift;
109 2         6 return scalar $self->readline(@_);
110             }
111              
112             sub getlines {
113 1     1 1 2 my $self = shift;
114 1 50       4 croak "Don't call getlines in scalar context" unless wantarray;
115 1         1 my @lines;
116 1         3 while (defined(my $line = $self->readline)) {
117 3         80 push @lines, $line
118             }
119 1         72 return @lines;
120             }
121              
122             sub readline {
123 7     7 1 7 my $self = shift;
124 7         17 my $re = $self->rewound;
125            
126 7         55 while (1) {
127             # simple case -- no rewound entries
128 8 100 33     36 if (not $re or not @$re) {
129             #warn "real readline\n";
130 3         7 return $self->obj->getline
131             }
132              
133             # >>> past here, @$re is non-empty
134 5         6 my $next = $re->[0];
135              
136             # simple case -- next rewound entry is plain scalar
137 5 100       14 if (not ref($next)) {
138             #warn "plain scalar: $next\n";
139 1         5 return shift @$re;
140             }
141              
142             # simple case -- next rewound entry is something we don't know
143 4 50       10 if (ref($next) ne "ARRAY") {
144 0         0 die "can't handle rewind entry $next";
145             }
146            
147             # >>> complex case -- next rewound entry is arrayref
148            
149             # simple subcase -- it's empty
150 4 100       10 if (not @$next) {
151             #warn "ditching empty inner array\n";
152 1         2 shift @$re;
153 1         2 next;
154             }
155              
156             # simple subcase -- its entry is plain scalar
157 3 50       7 if (not ref($next->[0])) {
158             #warn "inner scalar: $next->[0]\n";
159 3         12 return shift @$next;
160             }
161              
162             # simple subcase -- its next entry is something we don't know
163 0 0         if (ref($next->[0])) {
164 0           die "can't handle nested rewind entry $next";
165             }
166             }
167             }
168              
169             "false";