File Coverage

blib/lib/IO/All.pm
Criterion Covered Total %
statement 412 470 87.6
branch 133 182 73.0
condition 34 72 47.2
subroutine 104 120 86.6
pod 56 57 98.2
total 739 901 82.0


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