File Coverage

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


line stmt bran cond sub pod time code
1             package PerlIO::Layers;
2             $PerlIO::Layers::VERSION = '0.012';
3 1     1   77738 use 5.008_001;
  1         5  
4 1     1   6 use strict;
  1         2  
  1         24  
5 1     1   5 use warnings FATAL => 'all';
  1         2  
  1         35  
6 1     1   5 use XSLoader;
  1         2  
  1         18  
7 1     1   4 use PerlIO ();
  1         2  
  1         30  
8 1     1   6 use Carp qw/croak/;
  1         2  
  1         57  
9 1     1   6 use List::Util qw/reduce max/;
  1         2  
  1         72  
10 1     1   7 use Exporter 5.57 qw/import/;
  1         17  
  1         1062  
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   4 return reduce { $a | $b } map { $FLAG_FOR{$_} } @_;
  10     10   48  
  11         44  
19             }
20              
21             sub _flag_names {
22 2     2   7 my $flagbits = shift;
23 2         14 return grep { $FLAG_FOR{$_} & $flagbits } keys %FLAG_FOR;
  30         87  
24             }
25              
26             sub _has_flags {
27 8     8   15 my $check_flag = _names_to_flags(@_);
28             return sub {
29 28     28   58 my ($fh, $layer) = @_;
30 28         176 my @info = PerlIO::get_layers($fh, details => 1);
31 28         130 while (my ($name, $arguments, $flags) = splice @info, 0, 3) {
32 63 50 33     134 next if defined $layer and $name ne $layer;
33 63         102 my $entry = $flags & $check_flag;
34 63 100       230 return 1 if $entry;
35             }
36 18         103 return 0;
37             }
38 8         54 }
39              
40             our %KIND_FOR;
41             sub _is_kind {
42 2     2   4 my $kind = shift;
43             return sub {
44 12     12   20 my $fh = shift;
45 12         49 my $kinds = _get_kinds($fh);
46 12 100       35 if (@_) {
47 2         3 my $layer = shift;
48 2 50 66     25 return exists $kinds->{$layer} && $kinds->{$layer} & $KIND_FOR{$kind} ? 1 : 0;
49             }
50             else {
51 10 100       12 return (grep { $kinds->{$_} & $KIND_FOR{$kind} } keys %{$kinds}) ? 1 : 0;
  20         107  
  10         34  
52             }
53 2         15 };
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 16281 my ($fh, $query_name, @args) = @_;
106 79 50       234 my $layer_query = $layer_query_for{$query_name} or croak "Query $query_name isn't defined";
107 79         200 return $layer_query->($fh, @args);
108             }
109              
110             sub get_layers {
111 1     1 1 147 my $fh = shift;
112 1         5 my @results;
113 1         15 my @info = PerlIO::get_layers($fh, details => 1);
114 1         13 while (my ($name, $arguments, $flags) = splice @info, 0, 3) {
115 2         32 push @results, [ $name, $arguments, [ _flag_names($flags) ] ];
116             }
117 1         6 return @results;
118             }
119              
120             1; # End of PerlIO::Layers
121              
122             # ABSTRACT: Querying your filehandle's capabilities
123              
124             __END__