File Coverage

blib/lib/Storage/Abstract/Handle.pm
Criterion Covered Total %
statement 77 85 90.5
branch 14 22 63.6
condition 7 15 46.6
subroutine 20 25 80.0
pod 3 3 100.0
total 121 150 80.6


line stmt bran cond sub pod time code
1             package Storage::Abstract::Handle;
2             $Storage::Abstract::Handle::VERSION = '0.008';
3 11     11   159 use v5.14;
  11         42  
4 11     11   70 use warnings;
  11         20  
  11         851  
5              
6             # 5.14 does not allow bypassing CORE function prototype, so we have a bunch of
7             # uninitialized warnings which need to be silenced.
8 11     11   65 no warnings 'uninitialized';
  11         22  
  11         487  
9              
10 11     11   59 use Carp qw();
  11         20  
  11         169  
11 11     11   42 use Scalar::Util qw();
  11         20  
  11         210  
12 11     11   5637 use Storage::Abstract::X;
  11         49  
  11         504  
13              
14 11     11   98 use parent 'Tie::Handle';
  11         24  
  11         223  
15              
16             sub copy
17             {
18 29     29 1 59 my ($self, $handle_to) = @_;
19              
20             # no extra behavior of print
21 29         86 local $\;
22              
23 29     47   94 my $read = sub { $self->READ($_[0], 8 * 1024) };
  47         111  
24 29     20   86 my $write = sub { print {$handle_to} $_[0] };
  20         35  
  20         236  
25              
26             # can use sysread / syswrite?
27 29 100 100     138 if (fileno $self->{handle} != -1 && fileno $handle_to != -1) {
28 2     4   11 $read = sub { sysread $self->{handle}, $_[0], 128 * 1024 };
  4         69  
29             $write = sub {
30 2     2   2 my $written = 0;
31 2         5 while ($written < $_[1]) {
32 2         78 my $res = syswrite $handle_to, $_[0], $_[1], $written;
33 2 50       5 return undef unless defined $res;
34 2         4 $written += $res;
35             }
36              
37 2         6 return 1;
38 2         8 };
39             }
40              
41 29         36 my $buffer;
42 29         33 while ('copying') {
43 51         108 my $bytes = $read->($buffer);
44              
45 51 50       157 Storage::Abstract::X::HandleError->raise("error reading from handle: $!")
46             unless defined $bytes;
47 51 100       223 last if $bytes == 0;
48 22 50       51 $write->($buffer, $bytes)
49             or Storage::Abstract::X::StorageError->raise("error during file copying: $!");
50             }
51             }
52              
53             sub size
54             {
55 21     21 1 37 my ($self) = @_;
56              
57 21         84 my $handle = $self->{handle};
58 21         28 my $size;
59              
60 21 100       64 if (fileno $handle == -1) {
61 15         30 my $success = (my $pos = tell $handle) >= 0;
62 15   33     69 $success &&= seek $handle, 0, 2;
63 15   33     61 $success &&= ($size = tell $handle) >= 0;
64 15   33     49 $success &&= seek $handle, $pos, 0;
65              
66 15 50       30 $success or Storage::Abstract::X::HandleError->raise($!);
67             }
68             else {
69 6         90 $size = -s $handle;
70             }
71              
72 21         146 return $size;
73             }
74              
75             sub adapt
76             {
77 40     40 1 70 my ($class, $arg) = @_;
78              
79 40 50 33     123 return $arg if defined tied($arg) && tied($arg)->isa($class);
80              
81 40         54 my $fh = \do { local *HANDLE };
  40         168  
82 40         269 tie *$fh, $class, $arg;
83              
84 40         608 return $fh;
85             }
86              
87             sub TIEHANDLE
88             {
89 40     40   73 my ($class, $handle) = @_;
90              
91 40 100       105 if (ref $handle ne 'GLOB') {
92 33         48 my $arg = $handle;
93 33         46 undef $handle;
94              
95 33 0       443 open $handle, '<:raw', $arg
    50          
96             or Storage::Abstract::X::HandleError->raise((ref $arg ? '' : "$arg: ") . $!);
97             }
98              
99 40         192 return bless {
100             handle => $handle,
101             }, $class;
102             }
103              
104             sub WRITE
105             {
106 0     0   0 Carp::croak 'Handle is readonly';
107             }
108              
109             sub EOF
110             {
111 0     0   0 my $self = shift;
112              
113 0         0 return eof $self->{handle};
114             }
115              
116             sub FILENO
117             {
118              
119             # the main handle cannot have real fileno, since only the underlying
120             # handle can be a real file handle
121 0     0   0 return -1;
122             }
123              
124             sub BINMODE
125             {
126 1     1   9415 my $self = shift;
127              
128 1     1   51 return binmode $self->{handle}, $_[0];
  1         921  
  1         19  
  1         8  
129             }
130              
131             sub TELL
132             {
133 0     0   0 my $self = shift;
134              
135 0         0 return tell $self->{handle};
136             }
137              
138             sub SEEK
139             {
140 9     9   7404 my $self = shift;
141              
142 9         56 return seek $self->{handle}, $_[0], $_[1];
143             }
144              
145             sub READLINE
146             {
147 9     9   90 my $self = shift;
148              
149 9         265 return readline $self->{handle};
150             }
151              
152             sub READ
153             {
154 47     47   66 my $self = shift;
155              
156 47         468 return read $self->{handle}, $_[0], $_[1], $_[2];
157             }
158              
159             sub CLOSE
160             {
161 0     0   0 my $self = shift;
162              
163 0         0 return close $self->{handle};
164             }
165              
166             1;
167              
168             __END__