File Coverage

blib/lib/IO/All.pm
Criterion Covered Total %
statement 393 443 88.7
branch 136 186 73.1
condition 34 72 47.2
subroutine 106 122 86.8
pod 56 57 98.2
total 725 880 82.3


line stmt bran cond sub pod time code
1 58     58   1289199 use strict; use warnings;
  58     58   182  
  58         1890  
  58         370  
  58         164  
  58         4876  
2             package IO::All;
3             our $VERSION = '0.87';
4              
5             require Carp;
6             # So one can use Carp::carp "$message" - without the parenthesis.
7             sub Carp::carp;
8              
9 58     58   23271 use IO::All::Base -base;
  58         204  
  58         379  
10              
11 58     58   434 use File::Spec();
  58         156  
  58         1066  
12 58     58   28967 use Symbol();
  58         42852  
  58         1452  
13 58     58   400 use Fcntl;
  58         237  
  58         12594  
14 58     58   449 use Cwd ();
  58         149  
  58         67902  
15              
16             our @EXPORT = qw(io);
17              
18             #===============================================================================
19             # Object creation and setup methods
20             #===============================================================================
21             my $autoload = {
22             qw(
23             touch file
24              
25             dir_handle dir
26             All dir
27             all_files dir
28             All_Files dir
29             all_dirs dir
30             All_Dirs dir
31             all_links dir
32             All_Links dir
33             mkdir dir
34             mkpath dir
35             next dir
36              
37             stdin stdio
38             stdout stdio
39             stderr stdio
40              
41             socket_handle socket
42             accept socket
43             shutdown socket
44              
45             readlink link
46             symlink link
47             )
48             };
49              
50             # XXX - These should die if the given argument exists but is not a
51             # link, dbm, etc.
52 9     9 1 1437 sub link { require IO::All::Link; goto &IO::All::Link::link; }
  9         52  
53 2     2 1 925 sub dbm { require IO::All::DBM; goto &IO::All::DBM::dbm; }
  2         14  
54 0     0 1 0 sub mldbm { require IO::All::MLDBM; goto &IO::All::MLDBM::mldbm; }
  0         0  
55              
56 584     584 0 1026 sub autoload { my $self = shift; $autoload; }
  584         2994  
57              
58             sub AUTOLOAD {
59 584     584   1473 my $self = shift;
60 584         1384 my $method = $IO::All::AUTOLOAD;
61 584         3444 $method =~ s/.*:://;
62 584   33     2102 my $pkg = ref($self) || $self;
63 584 50       1875 $self->throw(qq{Can't locate object method "$method" via package "$pkg"})
64             if $pkg ne $self->_package;
65 584         1801 my $class = $self->_autoload_class($method);
66 583         5114 my $foo = "$self";
67 583         4232 bless $self, $class;
68 583         2461 $self->$method(@_);
69             }
70              
71             sub _autoload_class {
72 584     584   1054 my $self = shift;
73 584         1104 my $method = shift;
74 584   66     1416 my $class_id = $self->autoload->{$method} || $method;
75 584         1910 my $ucfirst_class_name = 'IO::All::' . ucfirst($class_id);
76 584         1439 my $ucfirst_class_fn = "IO/All/" . ucfirst($class_id) . ".pm";
77 584 100       2342 return $ucfirst_class_name if $INC{$ucfirst_class_fn};
78 65 100       443 return "IO::All::\U$class_id" if $INC{"IO/All/\U$class_id\E.pm"};
79 60         23411 require IO::All::Temp;
80 60 100       3418 if (eval "require $ucfirst_class_name; 1") {
    100          
81 58         190 my $class = $ucfirst_class_name;
82             my $return = $class->can('new')
83             ? $class
84 58 50       977 : do { # (OS X hack)
85 0         0 my $value = $INC{$ucfirst_class_fn};
86 0         0 delete $INC{$ucfirst_class_fn};
87 0         0 $INC{"IO/All/\U$class_id\E.pm"} = $value;
88 0         0 "IO::All::\U$class_id";
89             };
90 58         401 return $return;
91             }
92             elsif (eval "require IO::All::\U$class_id; 1") {
93 1         7 return "IO::All::\U$class_id";
94             }
95 1         11 $self->throw("Can't find a class for method '$method'");
96             }
97              
98             sub new {
99 648     648 1 1443 my $self = shift;
100 648   66     3169 my $package = ref($self) || $self;
101 648         2459 my $new = bless Symbol::gensym(), $package;
102 648         11440 $new->_package($package);
103 648 100       1728 $new->_copy_from($self) if ref($self);
104 648         1479 my $name = shift;
105 648 100       3099 return $name if UNIVERSAL::isa($name, 'IO::All');
106 645 100       2046 return $new->_init unless defined $name;
107 510 50 33     3760 return $new->handle($name)
108             if UNIVERSAL::isa($name, 'GLOB') or ref(\ $name) eq 'GLOB';
109             # WWW - link is first because a link to a dir returns true for
110             # both -l and -d.
111 510 100       8396 return $new->link($name) if -l $name;
112 501 100       5764 return $new->file($name) if -f $name;
113 226 100       2597 return $new->dir($name) if -d $name;
114 54 50       278 return $new->$1($name) if $name =~ /^([a-z]{3,8}):/;
115 54 100       307 return $new->socket($name) if $name =~ /^[\w\-\.]*:\d{1,5}$/;
116 52 100 66     470 return $new->pipe($name) if $name =~ s/^\s*\|\s*// or $name =~ s/\s*\|\s*$//;
117 50 100       193 return $new->string if $name eq '$';
118 49 100       179 return $new->stdio if $name eq '-';
119 47 100       216 return $new->stderr if $name eq '=';
120 46 100       190 return $new->temp if $name eq '?';
121 45         217 $new->name($name);
122 45         247 $new->_init;
123             }
124              
125             sub _copy_from {
126 1     1   2 my $self = shift;
127 1         3 my $other = shift;
128 1         13 for (keys(%{*$other})) {
  1         7  
129             # XXX Need to audit exclusions here
130 5 100       20 next if /^(_handle|io_handle|is_open)$/;
131 3         9 *$self->{$_} = *$other->{$_};
132             }
133             }
134              
135             sub handle {
136 0     0 1 0 my $self = shift;
137 0 0       0 $self->_handle(shift) if @_;
138 0         0 return $self->_init;
139             }
140              
141             #===============================================================================
142             # Overloading support
143             #===============================================================================
144             my $old_warn_handler = $SIG{__WARN__};
145             $SIG{__WARN__} = sub {
146             if ($_[0] !~ /^Useless use of .+ \(.+\) in void context/) {
147             goto &$old_warn_handler if $old_warn_handler;
148             warn(@_);
149             }
150             };
151              
152 58     58   60905 use overload '""' => '_overload_stringify';
  58         97878  
  58         464  
153 58     58   6559 use overload '|' => '_overload_bitwise_or';
  58         163  
  58         267  
154 58     58   4869 use overload '<<' => '_overload_left_bitshift';
  58         1185  
  58         2477  
155 58     58   4987 use overload '>>' => '_overload_right_bitshift';
  58         147  
  58         244  
156 58     58   4224 use overload '<' => '_overload_less_than';
  58         148  
  58         1352  
157 58     58   3676 use overload '>' => '_overload_greater_than';
  58         142  
  58         338  
158 58     58   4002 use overload 'cmp' => '_overload_cmp';
  58         770  
  58         250  
159 58     58   3857 use overload '${}' => '_overload_string_deref';
  58         128  
  58         209  
160 58     58   3742 use overload '@{}' => '_overload_array_deref';
  58         133  
  58         196  
161 58     58   3761 use overload '%{}' => '_overload_hash_deref';
  58         128  
  58         217  
162 58     58   3775 use overload '&{}' => '_overload_code_deref';
  58         130  
  58         200  
163              
164 0     0   0 sub _overload_bitwise_or { shift->_overload_handler(@_, '|' ); }
165 6     6   37 sub _overload_left_bitshift { shift->_overload_handler(@_, '<<'); }
166 4     4   16 sub _overload_right_bitshift { shift->_overload_handler(@_, '>>'); }
167 11     11   51 sub _overload_less_than { shift->_overload_handler(@_, '<' ); }
168 17     17   773 sub _overload_greater_than { shift->_overload_handler(@_, '>' ); }
169 11     11   3930 sub _overload_string_deref { shift->_overload_handler(@_, '${}'); }
170 7     7   17441 sub _overload_array_deref { shift->_overload_handler(@_, '@{}'); }
171 7     7   53 sub _overload_hash_deref { shift->_overload_handler(@_, '%{}'); }
172 0     0   0 sub _overload_code_deref { shift->_overload_handler(@_, '&{}'); }
173              
174             sub _overload_handler {
175 63     63   175 my ($self) = @_;
176 63         261 my $method = $self->_get_overload_method(@_);
177 63         434 $self->$method(@_);
178             }
179              
180             my $op_swap = {
181             '>' => '<', '>>' => '<<',
182             '<' => '>', '<<' => '>>',
183             };
184              
185             sub _overload_table {
186 65     65   131 my $self = shift;
187             (
188 65         858 '* > *' => '_overload_any_to_any',
189             '* < *' => '_overload_any_from_any',
190             '* >> *' => '_overload_any_addto_any',
191             '* << *' => '_overload_any_addfrom_any',
192              
193             '* < scalar' => '_overload_scalar_to_any',
194             '* > scalar' => '_overload_any_to_scalar',
195             '* << scalar' => '_overload_scalar_addto_any',
196             '* >> scalar' => '_overload_any_addto_scalar',
197             )
198             };
199              
200             sub _get_overload_method {
201 63     63   213 my ($self, $arg1, $arg2, $swap, $operator) = @_;
202 63 100       206 if ($swap) {
203 22   33     115 $operator = $op_swap->{$operator} || $operator;
204             }
205 63         247 my $arg1_type = $self->_get_argument_type($arg1);
206 63         285 my $table1 = { $arg1->_overload_table };
207              
208 63 100       363 if ($operator =~ /\{\}$/) {
209 25         100 my $key = "$operator $arg1_type";
210 25   33     194 return $table1->{$key} || $self->_overload_undefined($key);
211             }
212              
213 38         114 my $arg2_type = $self->_get_argument_type($arg2);
214 38 100       244 my @table2 = UNIVERSAL::isa($arg2, "IO::All")
215             ? ($arg2->_overload_table)
216             : ();
217 38         330 my $table = { %$table1, @table2 };
218              
219 38         196 my @keys = (
220             "$arg1_type $operator $arg2_type",
221             "* $operator $arg2_type",
222             );
223 38 100       246 push @keys, "$arg1_type $operator *", "* $operator *"
224             unless $arg2_type =~ /^(scalar|array|hash|code|ref)$/;
225              
226 38         100 for (@keys) {
227             return $table->{$_}
228 76 100       400 if defined $table->{$_};
229             }
230              
231 0         0 return $self->_overload_undefined($keys[0]);
232             }
233              
234             sub _get_argument_type {
235 101     101   207 my $self = shift;
236 101         179 my $argument = shift;
237 101         227 my $ref = ref($argument);
238 101 100       317 return 'scalar' unless $ref;
239 69 50       209 return 'code' if $ref eq 'CODE';
240 69 50       195 return 'array' if $ref eq 'ARRAY';
241 69 50       193 return 'hash' if $ref eq 'HASH';
242 69 50       396 return 'ref' unless $argument->isa('IO::All');
243 69 100 66     311 $argument->file
244             if defined $argument->pathname and not $argument->type;
245 69   50     222 return $argument->type || 'unknown';
246             }
247              
248             sub _overload_cmp {
249 3     3   13 my ($self, $other, $swap) = @_;
250 3 50       14 $self = defined($self) ? $self.'' : $self;
251 3 100       15 ($self, $other) = ($other, $self) if $swap;
252 3         21 $self cmp $other;
253             }
254              
255             sub _overload_stringify {
256 1683     1683   7433 my $self = shift;
257 1683         4532 my $name = $self->pathname;
258 1683 100       7270 return defined($name) ? $name : overload::StrVal($self);
259             }
260              
261             sub _overload_undefined {
262 0     0   0 my $self = shift;
263 0         0 require Carp;
264 0         0 my $key = shift;
265 0 0       0 Carp::carp "Undefined behavior for overloaded IO::All operation: '$key'"
266             if $^W;
267 0         0 return '_overload_noop';
268             }
269              
270             sub _overload_noop {
271 0     0   0 my $self = shift;
272 0         0 return;
273             }
274              
275             sub _overload_any_addfrom_any {
276 1     1   5 $_[1]->append($_[2]->all);
277 1         4 $_[1];
278             }
279              
280             sub _overload_any_addto_any {
281 1     1   6 $_[2]->append($_[1]->all);
282 1         4 $_[2];
283             }
284              
285             sub _overload_any_from_any {
286 0 0 0 0   0 $_[1]->close if $_[1]->is_file and $_[1]->is_open;
287 0         0 $_[1]->print($_[2]->all);
288 0         0 $_[1];
289             }
290              
291             sub _overload_any_to_any {
292 0 0 0 0   0 $_[2]->close if $_[2]->is_file and $_[2]->is_open;
293 0         0 $_[2]->print($_[1]->all);
294 0         0 $_[2];
295             }
296              
297             sub _overload_any_to_scalar {
298 10     10   48 $_[2] = $_[1]->all;
299             }
300              
301             sub _overload_any_addto_scalar {
302 6     6   26 $_[2] .= $_[1]->all;
303 6         33 $_[2];
304             }
305              
306             sub _overload_scalar_addto_any {
307 2     2   10 $_[1]->append($_[2]);
308 2         8 $_[1];
309             }
310              
311             sub _overload_scalar_to_any {
312 14     14   61 local $\;
313 14 50 33     94 $_[1]->close if $_[1]->is_file and $_[1]->is_open;
314 14         92 $_[1]->print($_[2]);
315 14         83 $_[1];
316             }
317              
318             #===============================================================================
319             # Private Accessors
320             #===============================================================================
321             field '_package';
322             field _strict => undef;
323             field _layers => [];
324             field _handle => undef;
325             field _constructor => undef;
326             field _partial_spec_class => undef;
327              
328             #===============================================================================
329             # Public Accessors
330             #===============================================================================
331             chain block_size => 1024;
332             chain errors => undef;
333             field io_handle => undef;
334             field is_open => 0;
335             chain mode => undef;
336             chain name => undef;
337             chain perms => undef;
338             chain separator => $/;
339             field type => '';
340              
341             sub _spec_class {
342 114     114   187 my $self = shift;
343              
344 114         171 my $ret = 'File::Spec';
345 114 100       311 if (my $partial = $self->_partial_spec_class(@_)) {
346 62         156 $ret .= '::' . $partial;
347 62         2275 eval "require $ret";
348             }
349              
350 114         2504 return $ret
351             }
352              
353 624     624 1 1120 sub pathname {my $self = shift; $self->name(@_) }
  624         2102  
354              
355             #===============================================================================
356             # Chainable option methods (write only)
357             #===============================================================================
358             option 'assert';
359             option 'autoclose' => 1;
360             option 'backwards';
361             option 'chomp';
362             option 'confess';
363             option 'lock';
364             option 'rdonly';
365             option 'rdwr';
366             option 'strict';
367              
368             #===============================================================================
369             # IO::Handle proxy methods
370             #===============================================================================
371             proxy 'autoflush';
372             proxy 'eof';
373             proxy 'fileno';
374             proxy 'stat';
375             proxy 'tell';
376             proxy 'truncate';
377              
378             #===============================================================================
379             # IO::Handle proxy methods that open the handle if needed
380             #===============================================================================
381             proxy_open print => '>';
382             proxy_open printf => '>';
383             proxy_open sysread => O_RDONLY;
384             proxy_open syswrite => O_CREAT | O_WRONLY;
385             proxy_open seek => $^O eq 'MSWin32' ? '<' : '+<';
386             proxy_open 'getc';
387              
388             #===============================================================================
389             # Tie Interface
390             #===============================================================================
391 5     5 1 34 sub tie { my $self = shift; tie *$self, $self; }
  5         65  
392              
393             sub TIEHANDLE {
394 5 50   5   44 return $_[0] if ref $_[0];
395 0         0 my $class = shift;
396 0         0 my $self = bless Symbol::gensym(), $class;
397 0         0 $self->init(@_);
398             }
399              
400             sub READLINE {
401 12 100   12   3818 goto &getlines if wantarray;
402 10         37 goto &getline;
403             }
404              
405              
406             sub DESTROY {
407 414     414   783286 my $self = shift;
408 58     58   104756 no warnings;
  58         147  
  58         7251  
409 414 50       1513 unless ( $] < 5.008 ) {
410 414 100       1745 untie *$self if tied *$self;
411             }
412 414 100       1341 $self->close if $self->is_open;
413             }
414              
415 0     0   0 sub BINMODE { my $self = shift; CORE::binmode *$self->io_handle; }
  0         0  
416              
417             {
418 58     58   450 no warnings;
  58         207  
  58         115559  
419             *GETC = \&getc;
420             *PRINT = \&print;
421             *PRINTF = \&printf;
422             *READ = \&read;
423             *WRITE = \&write;
424             *SEEK = \&seek;
425             *TELL = \&getpos;
426             *EOF = \&eof;
427             *CLOSE = \&close;
428             *FILENO = \&fileno;
429             }
430              
431             #===============================================================================
432             # File::Spec Interface
433             #===============================================================================
434             sub canonpath {
435 2     2 1 5 my $self = shift;
436 2 50       4 eval { Cwd::abs_path($self->pathname); 0 } ||
  2         9  
  2         12  
437             File::Spec->canonpath($self->pathname)
438             }
439              
440             sub catdir {
441 4     4 1 8 my $self = shift;
442 4         10 my @args = grep defined, $self->name, @_;
443 4         11 $self->_constructor->()->dir(File::Spec->catdir(@args));
444             }
445             sub catfile {
446 9     9 1 759 my $self = shift;
447 9         29 my @args = grep defined, $self->name, @_;
448 9         31 $self->_constructor->()->file(File::Spec->catfile(@args));
449             }
450 1     1 1 4 sub join { shift->catfile(@_); }
451 2     2 1 9 sub curdir { shift->_constructor->()->dir(File::Spec->curdir); }
452 4     4 1 18 sub devnull { shift->_constructor->()->file(File::Spec->devnull); }
453 1     1 1 3 sub rootdir { shift->_constructor->()->dir(File::Spec->rootdir); }
454 1     1 1 4 sub tmpdir { shift->_constructor->()->dir(File::Spec->tmpdir); }
455 1     1 1 3 sub updir { shift->_constructor->()->dir(File::Spec->updir); }
456 1     1 1 51 sub case_tolerant{File::Spec->case_tolerant; }
457 165     165 1 542 sub is_absolute { File::Spec->file_name_is_absolute(shift->pathname); }
458 1     1 1 3 sub path { my $self = shift; map { $self->_constructor->()->dir($_) } File::Spec->path; }
  1         37  
  36         83  
459 14     14 1 78 sub splitpath { File::Spec->splitpath(shift->pathname); }
460 2     2 1 9 sub splitdir { File::Spec->splitdir(shift->pathname); }
461 1     1 1 2 sub catpath { my $self=shift; $self->_constructor->(File::Spec->catpath(@_)); }
  1         18  
462 1     1 1 5 sub abs2rel { File::Spec->abs2rel(shift->pathname, @_); }
463 1     1 1 6 sub rel2abs { File::Spec->rel2abs(shift->pathname, @_); }
464              
465             #===============================================================================
466             # Public IO Action Methods
467             #===============================================================================
468             sub absolute {
469 21     21 1 54 my $self = shift;
470 21 100       76 $self->pathname(File::Spec->rel2abs($self->pathname))
471             unless $self->is_absolute;
472 21         123 $self->is_absolute(1);
473 21         126 return $self;
474             }
475              
476             sub all {
477 59     59 1 144 my $self = shift;
478 59         315 $self->_assert_open('<');
479 58         305 local $/;
480 58         219 my $all = $self->io_handle->getline;
481 58         5398 $self->_error_check;
482 58 100       259 $self->_autoclose && $self->close;
483 58         427 return $all;
484             }
485              
486             sub append {
487 6     6 1 19 my $self = shift;
488 6         23 $self->_assert_open('>>');
489 6         20 $self->print(@_);
490             }
491              
492             sub appendln {
493 0     0 1 0 my $self = shift;
494 0         0 $self->_assert_open('>>');
495 0         0 $self->println(@_);
496             }
497              
498             sub binary {
499 9     9 1 23 my $self = shift;
500 9 100       31 CORE::binmode($self->io_handle) if $self->is_open;
501 9         21 push @{$self->_layers}, ":raw";
  9         36  
502 9         70 return $self;
503             }
504              
505             sub binmode {
506 5     5 1 13 my $self = shift;
507 5         13 my $layer = shift;
508 5 100       17 $self->_sane_binmode($layer) if $self->is_open;
509 5         12 push @{$self->_layers}, $layer;
  5         26  
510 5         30 return $self;
511             }
512              
513             sub _sane_binmode {
514 22     22   10752 my ($self, $layer) = @_;
515 22 100   2   101 $layer
  2         15  
  2         5  
  2         14  
516             ? CORE::binmode($self->io_handle, $layer)
517             : CORE::binmode($self->io_handle);
518             }
519              
520             sub buffer {
521 133     133 1 615 my $self = shift;
522 133 100       293 if (not @_) {
523 0         0 *$self->{buffer} = do {my $x = ''; \ $x}
  0         0  
524 130 50       300 unless exists *$self->{buffer};
525 130         428 return *$self->{buffer};
526             }
527 3 50       12 my $buffer_ref = ref($_[0]) ? $_[0] : \ $_[0];
528 3 100       13 $$buffer_ref = '' unless defined $$buffer_ref;
529 3         8 *$self->{buffer} = $buffer_ref;
530 3         11 return $self;
531             }
532              
533             sub clear {
534 21     21 1 34 my $self = shift;
535 21         45 my $buffer = *$self->{buffer};
536 21         40 $$buffer = '';
537 21         35 return $self;
538             }
539              
540             sub close {
541 158     158 1 387 my $self = shift;
542 158 50       479 return unless $self->is_open;
543 158         516 $self->is_open(0);
544 158         416 my $io_handle = $self->io_handle;
545 158         526 $self->io_handle(undef);
546 158         571 $self->mode(undef);
547 158 50       779 $io_handle->close(@_)
548             if defined $io_handle;
549 158         17950 return $self;
550             }
551              
552             sub empty {
553 1     1 1 3 my $self = shift;
554 1         3 my $message =
555             "Can't call empty on an object that is neither file nor directory";
556 1         61 $self->throw($message);
557             }
558              
559 0     0 1 0 sub exists {my $self = shift; -e $self->pathname }
  0         0  
560              
561             sub getline {
562 46     46 1 3794 my $self = shift;
563 46 100       176 return $self->getline_backwards
564             if $self->_backwards;
565 42         178 $self->_assert_open('<');
566 42         130 my $line;
567             {
568 42 50       75 local $/ = @_ ? shift(@_) : $self->separator;
  42         187  
569 42         123 $line = $self->io_handle->getline;
570 42 100 66     1197 chomp($line) if $self->_chomp and defined $line;
571             }
572 42         136 $self->_error_check;
573 42 100       191 return $line if defined $line;
574 4 100       24 $self->close if $self->_autoclose;
575 4         12 return undef;
576             }
577              
578             sub getlines {
579 6     6 1 573 my $self = shift;
580 6 100       46 return $self->getlines_backwards
581             if $self->_backwards;
582 5         33 $self->_assert_open('<');
583 5         10 my @lines;
584             {
585 5 100       12 local $/ = @_ ? shift(@_) : $self->separator;
  5         35  
586 5         22 @lines = $self->io_handle->getlines;
587 5 100       383 if ($self->_chomp) {
588 1         7 chomp for @lines;
589             }
590             }
591 5         25 $self->_error_check;
592 5 50       59 return @lines if @lines;
593 0 0       0 $self->close if $self->_autoclose;
594 0         0 return ();
595             }
596              
597 326     326 1 2414 sub is_dir { UNIVERSAL::isa(shift, 'IO::All::Dir'); }
598 0     0 1 0 sub is_dbm { UNIVERSAL::isa(shift, 'IO::All::DBM'); }
599 131     131 1 664 sub is_file { UNIVERSAL::isa(shift, 'IO::All::File'); }
600 4     4 1 51 sub is_link { UNIVERSAL::isa(shift, 'IO::All::Link'); }
601 0     0 1 0 sub is_mldbm { UNIVERSAL::isa(shift, 'IO::All::MLDBM'); }
602 2     2 1 24 sub is_socket { UNIVERSAL::isa(shift, 'IO::All::Socket'); }
603 0     0 1 0 sub is_stdio { UNIVERSAL::isa(shift, 'IO::All::STDIO'); }
604 0     0 1 0 sub is_string { UNIVERSAL::isa(shift, 'IO::All::String'); }
605 0     0 1 0 sub is_temp { UNIVERSAL::isa(shift, 'IO::All::Temp'); }
606 65     65 1 104 sub length { length ${shift->buffer}; }
  65         123  
607              
608             sub open {
609 3     3 1 9 my $self = shift;
610 3 50       11 return $self if $self->is_open;
611 3         13 $self->is_open(1);
612 3         10 my ($mode, $perms) = @_;
613 3 50       20 $self->mode($mode) if defined $mode;
614 3 50       10 $self->mode('<') unless defined $self->mode;
615 3 50       13 $self->perms($perms) if defined $perms;
616 3         7 my @args;
617 3 50       13 unless ($self->is_dir) {
618 3         12 push @args, $self->mode;
619 3 50       14 push @args, $self->perms if defined $self->perms;
620             }
621 3 50 33     10 if (defined $self->pathname and not $self->type) {
    0 0        
622 3         30 $self->file;
623 3         17 return $self->open(@args);
624             }
625             elsif (defined $self->_handle and
626             not $self->io_handle->opened
627             ) {
628             # XXX Not tested
629 0         0 $self->io_handle->fdopen($self->_handle, @args);
630             }
631 0         0 $self->_set_binmode;
632             }
633              
634             sub println {
635 7     7 1 1000816 my $self = shift;
636 7 50       32 $self->print(map {/\n\z/ ? ($_) : ($_, "\n")} @_);
  22         150  
637             }
638              
639             sub read {
640 44     44 1 532 my $self = shift;
641 44         129 $self->_assert_open('<');
642             my $length = (@_ or $self->type eq 'dir')
643             ? $self->io_handle->read(@_)
644             : $self->io_handle->read(
645 44 50 33     159 ${$self->buffer},
  44         100  
646             $self->block_size,
647             $self->length,
648             );
649 44         468 $self->_error_check;
650 44   66     148 return $length || $self->_autoclose && $self->close && 0;
651             }
652              
653             {
654 58     58   824 no warnings;
  58         160  
  58         45879  
655             *readline = \&getline;
656             }
657              
658             # deprecated
659             sub scalar {
660 18     18 1 600 my $self = shift;
661 18         76 $self->all(@_);
662             }
663              
664             sub slurp {
665 11     11 1 676 my $self = shift;
666 11         123 my $slurp = $self->all;
667 10 100       89 return $slurp unless wantarray;
668 4         23 my $separator = $self->separator;
669 4 100       22 if ($self->_chomp) {
670 1         4 local $/ = $separator;
671 1         61 map {chomp; $_} split /(?<=\Q$separator\E)/, $slurp;
  17         33  
  17         45  
672             }
673             else {
674 3         195 split /(?<=\Q$separator\E)/, $slurp;
675             }
676             }
677              
678             sub utf8 {
679 9     9 1 21 my $self = shift;
680 9 50       39 if ($] < 5.008) {
681 0         0 die "IO::All -utf8 not supported on Perl older than 5.8";
682             }
683 9         39 $self->encoding('UTF-8');
684 9         31 return $self;
685             }
686              
687             sub _has_utf8 {
688 342     342   606 grep { $_ eq ':encoding(UTF-8)' } @{shift->_layers}
  4         22  
  342         967  
689             }
690              
691             sub encoding {
692 17     17 1 39 my $self = shift;
693 17         39 my $encoding = shift;
694 17 50       57 if ($] < 5.008) {
695 0         0 die "IO::All -encoding not supported on Perl older than 5.8";
696             }
697 17 50       48 die "No valid encoding string sent" if !$encoding;
698 17 100 66     57 $self->_set_encoding($encoding) if $self->is_open and $encoding;
699 17         179 push @{$self->_layers}, ":encoding($encoding)";
  17         60  
700 17         64 return $self;
701             }
702              
703             sub _set_encoding {
704 2     2   8 my ($self, $encoding) = @_;
705 2         10 return CORE::binmode($self->io_handle, ":encoding($encoding)");
706             }
707              
708             sub write {
709 21     21 1 73 my $self = shift;
710 21         56 $self->_assert_open('>');
711             my $length = @_
712             ? $self->io_handle->write(@_)
713 21 50       64 : $self->io_handle->write(${$self->buffer}, $self->length);
  21         44  
714 21         492 $self->_error_check;
715 21 50       78 $self->clear unless @_;
716 21         52 return $length;
717             }
718              
719             #===============================================================================
720             # Implementation methods. Subclassable.
721             #===============================================================================
722             sub throw {
723 4     4 1 11 my $self = shift;
724 4         25 require Carp;
725             ;
726 4 50       24 return &{$self->errors}(@_)
  0         0  
727             if $self->errors;
728 4 50       26 return Carp::confess(@_)
729             if $self->_confess;
730 4         789 return Carp::croak(@_);
731             }
732              
733             #===============================================================================
734             # Private instance methods
735             #===============================================================================
736             sub _assert_dirpath {
737 4     4   12 my $self = shift;
738 4         12 my $dir_name = shift;
739             return $dir_name if ((! CORE::length($dir_name)) or
740             -d $dir_name or
741             CORE::mkdir($dir_name, $self->perms || 0755) or
742 4 50 100     111 do {
      50        
      100        
      66        
      33        
743 1         8 require File::Path;
744 1   50     12 File::Path::mkpath($dir_name, 0, $self->perms || 0755 );
745             } or
746             $self->throw("Can't make $dir_name"));
747             }
748              
749             sub _assert_open {
750 10     10   19 my $self = shift;
751 10 100       29 return if $self->is_open;
752 7 100       41 $self->file unless $self->type;
753 7         34 return $self->open(@_);
754             }
755              
756             sub _error_check {
757 239     239   445 my $self = shift;
758 239         1302 my $saved_error = $!;
759 239 50       843 return unless $self->io_handle->can('error');
760 239 50       790 return unless $self->io_handle->error;
761 0         0 $self->throw($saved_error);
762             }
763              
764             sub _set_binmode {
765 123     123   288 my $self = shift;
766 123         249 $self->_sane_binmode($_) for @{$self->_layers};
  123         596  
767 123         50344 return $self;
768             }
769              
770             #===============================================================================
771             # Stat Methods
772             #===============================================================================
773             BEGIN {
774 58     58   511 no strict 'refs';
  58         162  
  58         7420  
775 58     58   447 my @stat_fields = qw(
776             device inode modes nlink uid gid device_id size atime mtime
777             ctime blksize blocks
778             );
779 58         327 foreach my $stat_field_idx (0 .. $#stat_fields)
780             {
781 754         1687 my $idx = $stat_field_idx;
782 754         1365 my $name = $stat_fields[$idx];
783              
784             *$name = sub {
785 13     13   620 my $self = shift;
786 13   33     41 return (stat($self->io_handle || $self->pathname))[$idx];
787 754         11656 };
788             }
789             }
790