File Coverage

blib/lib/File/Replace/DualHandle.pm
Criterion Covered Total %
statement 51 51 100.0
branch 14 14 100.0
condition 12 12 100.0
subroutine 17 17 100.0
pod 0 3 0.0
total 94 97 96.9


line stmt bran cond sub pod time code
1             #!perl
2             package # hide from pause
3             File::Replace::DualHandle;
4 8     8   90097 use warnings;
  8         16  
  8         259  
5 8     8   42 use strict;
  8         15  
  8         148  
6 8     8   40 use Carp;
  8         16  
  8         454  
7 8     8   51 use warnings::register;
  8         17  
  8         881  
8 8     8   49 use Scalar::Util qw/blessed/;
  8         26  
  8         663  
9              
10             # For AUTHOR, COPYRIGHT, AND LICENSE see the bottom of this file
11              
12             ## no critic (RequireFinalReturn, RequireArgUnpacking)
13              
14             BEGIN {
15 8     8   63 require Tie::Handle::Base;
16 8         5187 our @ISA = qw/ Tie::Handle::Base /; ## no critic (ProhibitExplicitISA)
17             }
18              
19             sub TIEHANDLE {
20 17 100   17   163 @_==2 or croak __PACKAGE__."->TIEHANDLE: bad number of args";
21 16         41 my ($class,$repl) = @_;
22 16 100 100     372 croak "$class->TIEHANDLE: argument must be a File::Replace object"
23             unless blessed($repl) && $repl->isa('File::Replace');
24 14         45 my $self = $class->SUPER::TIEHANDLE($repl->in_fh);
25 14         36 $self->{repl} = $repl;
26 14         41 return $self;
27             }
28              
29 4     4 0 54 sub replace { return shift->{repl} }
30 4     4 0 26 sub in_fh { return shift->{repl}->in_fh }
31 4     4 0 1715 sub out_fh { return shift->{repl}->out_fh }
32              
33             sub OPEN {
34 8     8   4425 my $self = shift;
35 8 100 100     221 croak "this handle only supports 2- or 3-arg open" unless @_==1||@_==2;
36 6 100       241 croak "layers/filename may not contain an open mode (<, >, etc.)"
37             if $_[0]=~/^\s*\+?[<>]/;
38 4         17 my $opts = $self->{repl}->options; # old options to copy over
39 4 100       23 $opts->{layers} = @_==2 ? shift : undef;
40 4         7 my $filename = shift;
41             # just let the previous $self->{repl} get destroyed here
42 4         32 $self->{repl} = File::Replace->new($filename, %$opts);
43 4         15 $self->set_inner_handle($self->{repl}->in_fh);
44 4         18 return 1;
45             }
46              
47             sub CLOSE {
48 11     11   2330 my $self = shift;
49 11         34 return !!$self->{repl}->finish;
50             }
51              
52             sub WRITE {
53 13     13   25 my $self = shift;
54 13         39 $self->inner_write($self->{repl}->out_fh, @_);
55             }
56              
57             sub BINMODE {
58 11     11   2422 my $self = shift;
59 11 100       28 if (@_)
60             { return binmode($self->{repl}->in_fh, $_[0])
61 5   100     21 && binmode($self->{repl}->out_fh, $_[0]) }
62             else
63             { return binmode($self->{repl}->in_fh)
64 6   100     30 && binmode($self->{repl}->out_fh) }
65             }
66             # fileno: "If there is no real file descriptor at the OS level, ... -1 is returned."
67             # since we have two underlying handles, which one the user wants is ambiguous, so just return -1,
68             # this way the check defined(fileno($fh)) for whether the file is open still works
69 2 100   2   10 sub FILENO { return shift->{repl}->is_open ? -1 : undef }
70              
71             sub UNTIE {
72 1     1   4 my $self = shift;
73 1         147 warnings::warnif("Please don't untie ".ref($self)." handles");
74 1         49 $self->{repl} = undef;
75 1         4 $self->SUPER::UNTIE(@_);
76             }
77              
78             sub DESTROY {
79 14     14   7645 my $self = shift;
80             # File::Replace destructor will warn on unclosed file
81 14         43 $self->{repl} = undef;
82 14         59 $self->SUPER::DESTROY(@_);
83             }
84              
85             1;
86             __END__