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   223730 use warnings;
  4         18  
  4         141  
4 4     4   21 use strict;
  4         8  
  4         80  
5 4     4   53 use Carp;
  4         10  
  4         224  
6 4     4   35 use warnings::register;
  4         7  
  4         435  
7 4     4   27 use Scalar::Util qw/blessed/;
  4         9  
  4         4645  
8              
9             # For AUTHOR, COPYRIGHT, AND LICENSE see the bottom of this file
10              
11             our $VERSION = '0.16';
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 6536 my $class = shift;
21 6         12 my $fh = \do{local*HANDLE;*HANDLE}; ## no critic (RequireInitializationForLocalVars)
  6         15  
  6         18  
22 6         46 tie *$fh, $class, @_;
23 6         32 return $fh;
24             }
25              
26             sub TIEHANDLE {
27 7     7   1459 my $class = shift;
28 7         15 my $innerhandle = shift;
29 7 100       21 $innerhandle = \do{local*HANDLE;*HANDLE} ## no critic (RequireInitializationForLocalVars)
  3         7  
  3         9  
30             unless defined $innerhandle;
31 7 100       219 @_ and warnings::warnif("too many arguments to $class->TIEHANDLE");
32 7         36 return bless { __innerhandle=>$innerhandle }, $class;
33             }
34 1     1   744 sub UNTIE { delete shift->{__innerhandle}; return }
  1         5  
35 6     6   1304 sub DESTROY { delete shift->{__innerhandle}; return }
  6         164  
36              
37 1     1 1 11 sub innerhandle { shift->{__innerhandle} }
38 0     0 0 0 sub set_inner_handle { $_[0]->{__innerhandle} = $_[1] }
39              
40             sub BINMODE {
41 3     3   1462 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         28  
44 1         6 else { return binmode($fh) }
45             }
46 4 100   4   547 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   2328 sub CLOSE { close shift->{__innerhandle} }
52 3     3   2825 sub EOF { eof shift->{__innerhandle} }
53 8     8   40 sub FILENO { fileno shift->{__innerhandle} }
54 1     1   9 sub GETC { getc shift->{__innerhandle} }
55 3     3   57 sub READLINE { readline shift->{__innerhandle} }
56 2     2   47 sub SEEK { seek shift->{__innerhandle}, $_[0], $_[1] }
57 2     2   14 sub TELL { tell shift->{__innerhandle} }
58              
59             sub OPEN {
60 7     7   1932 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         217  
64 1         38 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   1376 my $self = shift;
77 10 100       36 my $str = join defined $, ? $, : '', @_;
78 10 100       37 $str .= $\ if defined $\;
79 10 100       25 return defined( $self->WRITE($str) ) ? 1 : undef;
80             }
81             sub PRINTF {
82 4     4   1303 my $self = shift;
83 4 100       18 return defined( $self->WRITE(sprintf shift, @_) ) ? 1 : undef;
84             }
85 17     17   831 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 104 shift if blessed($_[0]) && $_[0]->isa(__PACKAGE__);
93             # WRITE this, scalar, length, offset
94             # substr EXPR, OFFSET, LENGTH
95 18 100       48 my $len = defined $_[2] ? $_[2] : length($_[1]);
96 18 100       35 my $off = defined $_[3] ? $_[3] : 0;
97 18         41 my $data = substr($_[1], $off, $len);
98 18         52 local $\=undef;
99 18 100       26 print {$_[0]} $data and return length($data);
  18         254  
100 4         67 return undef; ## no critic (ProhibitExplicitReturnUndef)
101             }
102              
103             sub open_parse {
104 14 100   14 1 15100 croak "not enough arguments to open_parse" unless @_;
105 13         24 my $fnwm = shift;
106 13 100       237 carp "too many arguments to open_parse" if @_>1;
107 13 100       37 return ($fnwm, shift) if @_; # passthru
108 12 100       95 if ( $fnwm =~ s{^\s* ( \| | \+? (?: < | >>? ) (?:&=?)? ) | ( \| ) \s*$}{}x ) {
109 11         39 my ($x,$y) = ($1,$2); $fnwm =~ s/^\s+|\s+$//g;
  11         49  
110 11 100       30 if ( defined $y ) { return ('-|', $fnwm) }
  3 100       18  
111 1         6 elsif ( $x eq '|' ) { return ('|-', $fnwm) }
112 7         43 else { return ($x, $fnwm) }
113             } else
114 1         6 { $fnwm=~s/^\s+|\s+$//g; return ('<', $fnwm) }
  1         7  
115             }
116              
117             1;