File Coverage

blib/lib/PerlIO/Layers.pm
Criterion Covered Total %
statement 58 58 100.0
branch 9 12 75.0
condition 3 6 50.0
subroutine 17 17 100.0
pod 2 2 100.0
total 89 95 93.6


line stmt bran cond sub pod time code
1             package PerlIO::Layers;
2             $PerlIO::Layers::VERSION = '0.011';
3 1     1   46433 use 5.008_001;
  1         5  
  1         48  
4 1     1   6 use strict;
  1         2  
  1         43  
5 1     1   6 use warnings FATAL => 'all';
  1         3  
  1         45  
6 1     1   6 use XSLoader;
  1         2  
  1         47  
7 1     1   6 use PerlIO ();
  1         2  
  1         28  
8 1     1   5 use Carp qw/croak/;
  1         3  
  1         58  
9 1     1   6 use List::Util qw/reduce max/;
  1         2  
  1         93  
10 1     1   6 use Exporter 5.57 qw/import/;
  1         27  
  1         1332  
11              
12             our @EXPORT_OK = qw/query_handle get_layers get_buffer_sizes/;
13              
14             XSLoader::load(__PACKAGE__, __PACKAGE__->VERSION);
15              
16             our %FLAG_FOR;
17             sub _names_to_flags {
18 1     1   3 return reduce { $a | $b } map { $FLAG_FOR{$_} } @_;
  10     10   42  
  11         58  
19             }
20              
21             sub _flag_names {
22 2     2   3 my $flagbits = shift;
23 2         12 return grep { $FLAG_FOR{$_} & $flagbits } keys %FLAG_FOR;
  30         58  
24             }
25              
26             sub _has_flags {
27 8     8   20 my $check_flag = _names_to_flags(@_);
28             return sub {
29 28     28   42 my ($fh, $layer) = @_;
30 28         216 my @info = PerlIO::get_layers($fh, details => 1);
31 28         158 while (my ($name, $arguments, $flags) = splice @info, 0, 3) {
32 63 50 33     261 next if defined $layer and $name ne $layer;
33 63         122 my $entry = $flags & $check_flag;
34 63 100       306 return 1 if $entry;
35             }
36 18         120 return 0;
37             }
38 8         85 }
39              
40             our %KIND_FOR;
41             sub _is_kind {
42 2     2   6 my $kind = shift;
43             return sub {
44 12     12   19 my $fh = shift;
45 12         64 my $kinds = _get_kinds($fh);
46 12 100       34 if (@_) {
47 2         3 my $layer = shift;
48 2 50 66     30 return exists $kinds->{$layer} && $kinds->{$layer} & $KIND_FOR{$kind} ? 1 : 0;
49             }
50             else {
51 10 100       13 return (grep { $kinds->{$_} & $KIND_FOR{$kind} } keys %{$kinds}) ? 1 : 0;
  20         117  
  10         33  
52             }
53 2         39 };
54             }
55              
56             my %is_binary = map { ( $_ => 1) } qw/unix stdio perlio crlf flock creat excl mmap/;
57              
58             my $nonbinary_flags = _names_to_flags('UTF8', 'CRLF');
59             my $crlf_flags = _names_to_flags('CRLF');
60              
61             my %layer_query_for = (
62             writeable => _has_flags('CANWRITE'),
63             readable => _has_flags('CANREAD'),
64             open => _has_flags('OPEN'),
65             temp => _has_flags('TEMP'),
66             crlf => _has_flags('CRLF'),
67             utf8 => _has_flags('UTF8'),
68             binary => sub {
69             my ($fh, $layer) = @_;
70             my @info = PerlIO::get_layers($fh, details => 1);
71             while (my ($name, $arguments, $flags) = splice @info, 0, 3) {
72             next if defined $layer and $name ne $layer;
73             return 0 if not $is_binary{$name} or $flags & $nonbinary_flags;
74             }
75             return 1;
76             },
77             mappable => sub {
78             my ($fh, $layer) = @_;
79             my @info = PerlIO::get_layers($fh, details => 1);
80             while (my ($name, $arguments, $flags) = splice @info, 0, 3) {
81             next if defined $layer and $name ne $layer;
82             return 0 if not $is_binary{$name} or $flags & $crlf_flags;
83             }
84             return 1;
85             },
86             layer => sub {
87             my ($fh, $layer) = @_;
88             my @info = PerlIO::get_layers($fh, details => 1);
89             while (my ($name, $arguments, $flags) = splice @info, 0, 3) {
90             return 1 if $name eq $layer;
91             }
92             return 0;
93             },
94             buffered => _is_kind('BUFFERED'),
95             can_crlf => _is_kind('CANCRLF'),
96             line_buffered => _has_flags('LINEBUF'),
97             autoflush => _has_flags('UNBUF'),
98             buffer_size => sub {
99             my ($handle, $size) = @_;
100             return max(get_buffer_sizes($handle)) == $size;
101             }
102             );
103              
104             sub query_handle {
105 79     79 1 20457 my ($fh, $query_name, @args) = @_;
106 79 50       240 my $layer_query = $layer_query_for{$query_name} or croak "Query $query_name isn't defined";
107 79         202 return $layer_query->($fh, @args);
108             }
109              
110             sub get_layers {
111 1     1 1 9 my $fh = shift;
112 1         3 my @results;
113 1         10 my @info = PerlIO::get_layers($fh, details => 1);
114 1         7 while (my ($name, $arguments, $flags) = splice @info, 0, 3) {
115 2         6 push @results, [ $name, $arguments, [ _flag_names($flags) ] ];
116             }
117 1         4 return @results;
118             }
119              
120             1; # End of PerlIO::Layers
121              
122             # ABSTRACT: Querying your filehandle's capabilities
123              
124             __END__