File Coverage

blib/lib/Tie/Handle/Base.pm
Criterion Covered Total %
statement 79 79 100.0
branch 40 40 100.0
condition 3 3 100.0
subroutine 26 26 100.0
pod 4 5 80.0
total 152 153 99.3


line stmt bran cond sub pod time code
1             #!perl
2             package Tie::Handle::Base;
3 12     12   560947 use warnings;
  12         69  
  12         452  
4 12     12   71 use strict;
  12         25  
  12         233  
5 12     12   55 use Carp;
  12         20  
  12         623  
6 12     12   75 use warnings::register;
  12         32  
  12         1530  
7 12     12   86 use Scalar::Util qw/blessed/;
  12         19  
  12         13330  
8              
9             # For AUTHOR, COPYRIGHT, AND LICENSE see the bottom of this file
10              
11             our $VERSION = '0.14';
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 82     82 1 13053 my $class = shift;
21 82         131 my $fh = \do{local*HANDLE;*HANDLE}; ## no critic (RequireInitializationForLocalVars)
  82         196  
  82         240  
22 82         562 tie *$fh, $class, @_;
23 75         297 return $fh;
24             }
25              
26             sub TIEHANDLE {
27 114     114   1714 my $class = shift;
28 114         170 my $innerhandle = shift;
29 114 100       263 $innerhandle = \do{local*HANDLE;*HANDLE} ## no critic (RequireInitializationForLocalVars)
  42         102  
  42         166  
30             unless defined $innerhandle;
31 114 100       475 @_ and warnings::warnif("too many arguments to $class->TIEHANDLE");
32 114         400 return bless { __innerhandle=>$innerhandle }, $class;
33             }
34 41     41   829 sub UNTIE { delete shift->{__innerhandle}; return }
  41         157  
35 113     113   1709 sub DESTROY { delete shift->{__innerhandle}; return }
  113         799  
36              
37 27     27 1 231 sub innerhandle { shift->{__innerhandle} }
38 56     56 0 198 sub set_inner_handle { $_[0]->{__innerhandle} = $_[1] }
39              
40             sub BINMODE {
41 3     3   1553 my $fh = shift->{__innerhandle};
42             # note binmode is prototyped, so the conditional is needed here:
43 3 100       12 if (@_) { return binmode($fh,$_[0]) }
  2         26  
44 1         7 else { return binmode($fh) }
45             }
46 6 100   6   550 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 74     74   2992 sub CLOSE { close shift->{__innerhandle} }
52 258     258   4542 sub EOF { eof shift->{__innerhandle} }
53 239     239   111691 sub FILENO { fileno shift->{__innerhandle} }
54 2     2   17 sub GETC { getc shift->{__innerhandle} }
55 147     147   2294 sub READLINE { readline shift->{__innerhandle} }
56 3     3   66 sub SEEK { seek shift->{__innerhandle}, $_[0], $_[1] }
57 3     3   25 sub TELL { tell shift->{__innerhandle} }
58              
59             sub OPEN {
60 43     43   2107 my $self = shift;
61 43 100       88 $self->CLOSE if defined $self->FILENO;
62             # note open is prototyped, so the conditional is needed here:
63 43 100       108 if (@_) { return open $self->{__innerhandle}, shift, @_ }
  42         1332  
64 1         41 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 32     32   2430 my $self = shift;
77 32 100       132 my $str = join defined $, ? $, : '', @_;
78 32 100       109 $str .= $\ if defined $\;
79 32 100       116 return defined( $self->WRITE($str) ) ? 1 : undef;
80             }
81             sub PRINTF {
82 5     5   1255 my $self = shift;
83 5 100       36 return defined( $self->WRITE(sprintf shift, @_) ) ? 1 : undef;
84             }
85 28     28   928 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 42 100 100 42 1 268 shift if blessed($_[0]) && $_[0]->isa(__PACKAGE__);
93             # WRITE this, scalar, length, offset
94             # substr EXPR, OFFSET, LENGTH
95 42 100       112 my $len = defined $_[2] ? $_[2] : length($_[1]);
96 42 100       85 my $off = defined $_[3] ? $_[3] : 0;
97 42         92 my $data = substr($_[1], $off, $len);
98 42         118 local $\=undef;
99 42 100       63 print {$_[0]} $data and return length($data);
  42         538  
100 4         62 return undef; ## no critic (ProhibitExplicitReturnUndef)
101             }
102              
103             sub open_parse {
104 14 100   14 1 14616 croak "not enough arguments to open_parse" unless @_;
105 13         22 my $fnwm = shift;
106 13 100       244 carp "too many arguments to open_parse" if @_>1;
107 13 100       39 return ($fnwm, shift) if @_; # passthru
108 12 100       93 if ( $fnwm =~ s{^\s* ( \| | \+? (?: < | >>? ) (?:&=?)? ) | ( \| ) \s*$}{}x ) {
109 11         39 my ($x,$y) = ($1,$2); $fnwm =~ s/^\s+|\s+$//g;
  11         52  
110 11 100       33 if ( defined $y ) { return ('-|', $fnwm) }
  3 100       17  
111 1         12 elsif ( $x eq '|' ) { return ('|-', $fnwm) }
112 7         41 else { return ($x, $fnwm) }
113             } else
114 1         8 { $fnwm=~s/^\s+|\s+$//g; return ('<', $fnwm) }
  1         6  
115             }
116              
117             1;
118             __END__