File Coverage

blib/lib/Tie/Handle/Base.pm
Criterion Covered Total %
statement 78 79 98.7
branch 39 40 97.5
condition 2 3 66.6
subroutine 25 26 96.1
pod 4 5 80.0
total 148 153 96.7


line stmt bran cond sub pod time code
1             #!perl
2             package Tie::Handle::Base;
3 4     4   216620 use warnings;
  4         17  
  4         138  
4 4     4   19 use strict;
  4         7  
  4         73  
5 4     4   14 use Carp;
  4         6  
  4         199  
6 4     4   21 use warnings::register;
  4         8  
  4         433  
7 4     4   21 use Scalar::Util qw/blessed/;
  4         13  
  4         4391  
8              
9             # For AUTHOR, COPYRIGHT, AND LICENSE see Base.pod
10              
11             our $VERSION = '0.18';
12              
13             ## no critic (RequireFinalReturn, RequireArgUnpacking)
14              
15             our @IO_METHODS = qw/ BINMODE CLOSE EOF FILENO GETC OPEN PRINT PRINTF
16             READ READLINE SEEK TELL WRITE /;
17             our @ALL_METHODS = (qw/ TIEHANDLE UNTIE DESTROY /, @IO_METHODS);
18              
19             sub new {
20 6     6 1 5521 my $class = shift;
21 6         10 my $fh = \do{local*HANDLE;*HANDLE}; ## no critic (RequireInitializationForLocalVars)
  6         12  
  6         22  
22 6         41 tie *$fh, $class, @_;
23 6         26 return $fh;
24             }
25              
26             sub TIEHANDLE {
27 7     7   1254 my $class = shift;
28 7         11 my $innerhandle = shift;
29 7 100       23 $innerhandle = \do{local*HANDLE;*HANDLE} ## no critic (RequireInitializationForLocalVars)
  3         6  
  3         7  
30             unless defined $innerhandle;
31 7 100       213 @_ and warnings::warnif("too many arguments to $class->TIEHANDLE");
32 7         34 return bless { __innerhandle=>$innerhandle }, $class;
33             }
34 1     1   582 sub UNTIE { delete shift->{__innerhandle}; return }
  1         5  
35 6     6   6963 sub DESTROY { delete shift->{__innerhandle}; return }
  6         149  
36              
37 1     1 1 9 sub innerhandle { shift->{__innerhandle} }
38 0     0 0 0 sub set_inner_handle { $_[0]->{__innerhandle} = $_[1] }
39              
40             sub BINMODE {
41 3     3   1316 my $fh = shift->{__innerhandle};
42             # note binmode is prototyped, so the conditional is needed here:
43 3 100       11 if (@_) { return binmode($fh,$_[0]) }
  2         22  
44 1         7 else { return binmode($fh) }
45             }
46 4 100   4   444 sub READ { read($_[0]->{__innerhandle}, $_[1], $_[2], defined $_[3] ? $_[3] : 0 ) }
47             # The following would work in Perl >=5.16, when CORE:: was added
48             #sub BINMODE { &CORE::binmode (shift->{__innerhandle}, @_) }
49             #sub READ { &CORE::read (shift->{__innerhandle}, \shift, @_) }
50              
51 10     10   1997 sub CLOSE { close shift->{__innerhandle} }
52 3     3   2230 sub EOF { eof shift->{__innerhandle} }
53 8     8   32 sub FILENO { fileno shift->{__innerhandle} }
54 1     1   11 sub GETC { getc shift->{__innerhandle} }
55 3     3   42 sub READLINE { readline shift->{__innerhandle} }
56 2     2   44 sub SEEK { seek shift->{__innerhandle}, $_[0], $_[1] }
57 2     2   11 sub TELL { tell shift->{__innerhandle} }
58              
59             sub OPEN {
60 7     7   1587 my $self = shift;
61 7 100       15 $self->CLOSE if defined $self->FILENO;
62             # note open is prototyped, so the conditional is needed here:
63 7 100       21 if (@_) { return open $self->{__innerhandle}, shift, @_ }
  6         153  
64 1         33 else { return open $self->{__innerhandle} }
65             }
66              
67             # The following work too, but I chose to implement them in terms of
68             # WRITE so that overriding output behavior is easier.
69             #sub PRINT { print {shift->{__innerhandle}} @_ }
70             #sub PRINTF { printf {shift->{__innerhandle}} shift, @_ }
71              
72             # tests show that print, printf, and syswrite always return undef on fail,
73             # even in list context, so we'll do an explicit "return undef"
74              
75             sub PRINT {
76 10     10   1116 my $self = shift;
77 10 100       36 my $str = join defined $, ? $, : '', @_;
78 10 100       33 $str .= $\ if defined $\;
79 10 100       25 return defined( $self->WRITE($str) ) ? 1 : undef;
80             }
81             sub PRINTF {
82 4     4   1089 my $self = shift;
83 4 100       17 return defined( $self->WRITE(sprintf shift, @_) ) ? 1 : undef;
84             }
85 17     17   769 sub WRITE { inner_write(shift->{__innerhandle}, @_) }
86              
87             # the docs tell us not to intermix syswrite with other calls like print,
88             # and since our tied sysread uses read internally, we should avoid the
89             # sysread/-write functions in general,
90             # so we emulate syswrite similarly to Tie::StdHandle, with substr+print
91             sub inner_write { # can be called as function or method
92 18 50 66 18 1 91 shift if blessed($_[0]) && $_[0]->isa(__PACKAGE__);
93             # WRITE this, scalar, length, offset
94             # substr EXPR, OFFSET, LENGTH
95 18 100       44 my $len = defined $_[2] ? $_[2] : length($_[1]);
96 18 100       30 my $off = defined $_[3] ? $_[3] : 0;
97 18         37 my $data = substr($_[1], $off, $len);
98 18         47 local $\=undef;
99 18 100       25 print {$_[0]} $data and return length($data);
  18         210  
100 4         56 return undef; ## no critic (ProhibitExplicitReturnUndef)
101             }
102              
103             sub open_parse {
104 14 100   14 1 19841 croak "not enough arguments to open_parse" unless @_;
105 13         21 my $fnwm = shift;
106 13 100       208 carp "too many arguments to open_parse" if @_>1;
107 13 100       28 return ($fnwm, shift) if @_; # passthru
108 12 100       79 if ( $fnwm =~ s{^\s* ( \| | \+? (?: < | >>? ) (?:&=?)? ) | ( \| ) \s*$}{}x ) {
109 11         34 my ($x,$y) = ($1,$2); $fnwm =~ s/^\s+|\s+$//g;
  11         38  
110 11 100       26 if ( defined $y ) { return ('-|', $fnwm) }
  3 100       15  
111 1         6 elsif ( $x eq '|' ) { return ('|-', $fnwm) }
112 7         34 else { return ($x, $fnwm) }
113             } else
114 1         7 { $fnwm=~s/^\s+|\s+$//g; return ('<', $fnwm) }
  1         5  
115             }
116              
117             1;