File Coverage

blib/lib/open/layers.pm
Criterion Covered Total %
statement 37 38 97.3
branch 22 30 73.3
condition 6 8 75.0
subroutine 5 5 100.0
pod n/a
total 70 81 86.4


line stmt bran cond sub pod time code
1             package open::layers;
2              
3 20     20   1494134 use strict;
  20         200  
  20         461  
4 20     20   80 use warnings;
  20         20  
  20         341  
5 20     20   80 use Carp ();
  20         20  
  20         10599  
6              
7             our $VERSION = '0.001';
8              
9             # series of layers delimited by colons and consisting of non-space characters
10             # allow spaces before and between layers because core does, but don't require them
11             # we require a leading colon even though core doesn't, because it's expected anyway
12             my $LAYERS_SPEC = qr/\A\s*(?::[^\s:]+\s*)+\z/;
13              
14             sub import {
15 45     45   28575193 my $class = shift;
16 45         52336 while (@_) {
17 28         901 my $arg = shift;
18 28 100 100     2805 if (ref $arg or ref \$arg eq 'GLOB') {
    100          
    50          
19 2 50       6 Carp::croak "open::layers: No layer provided for handle $arg" unless @_;
20 2         5 my $layer = shift;
21 2 50       18 Carp::croak "open::layers: Invalid layer specification $layer" unless $layer =~ m/$LAYERS_SPEC/;
22 2 50       22 binmode $arg, $layer or Carp::croak "open::layers: binmode $arg failed: $!";
23             } elsif ($arg =~ m/\ASTD(IN|OUT|ERR|IO)\z/) {
24 16         679 my $which = $1;
25 16 50       288 Carp::croak "open::layers: No layer provided for handle $arg" unless @_;
26 16         272 my $layer = shift;
27 16 50       682 Carp::croak "open::layers: Invalid layer specification $layer" unless $layer =~ m/$LAYERS_SPEC/;
28 16 100       482 my @handles = $which eq 'IN' ? \*STDIN
    100          
    100          
29             : $which eq 'OUT' ? \*STDOUT
30             : $which eq 'ERR' ? \*STDERR
31             : (\*STDIN, \*STDOUT, \*STDERR);
32 16   33 8   1844 binmode $_, $layer or Carp::croak "open::layers: binmode $_ failed: $!" for @handles;
  8         320  
  8         64  
  8         284  
33             } elsif ($arg =~ m/\A(rw|r|w)\z/) {
34 10         133 my $which = $1;
35 10 50       44 Carp::croak "open::layers: No layer provided for $arg handles" unless @_;
36 10         39 my $layer = shift;
37 10 50       196 Carp::croak "open::layers: Invalid layer specification $layer" unless $layer =~ m/$LAYERS_SPEC/;
38 10         72 my @layers = $layer =~ m/(:[^\s:]+)/g; # split up the layers so we can set ${^OPEN} like open.pm
39 10   100     162 my ($in, $out) = split /\0/, (${^OPEN} || "\0"), -1;
40 10 100       45 if ($which ne 'w') { # r, rw
41 8         40 $in = join ' ', @layers;
42             }
43 10 100       67 if ($which ne 'r') { # w, rw
44 8         19 $out = join ' ', @layers;
45             }
46 10         2465 ${^OPEN} = join "\0", $in, $out;
47             } else {
48 0         0 Carp::croak "open::layers: Unknown flag $arg";
49             }
50             }
51             }
52              
53             1;
54              
55             =head1 NAME
56              
57             open::layers - Set default PerlIO layers
58              
59             =head1 SYNOPSIS
60              
61             {
62             # set default layers for open() in this lexical scope
63             use open::layers r => ':encoding(UTF-8)';
64             }
65             # encoding layer no longer applied to handles opened here
66              
67             use open::layers r => ':encoding(cp1252)', w => ':encoding(UTF-8)';
68             use open::layers rw => ':encoding(UTF-8)'; # all opened handles
69              
70             # push layers on the standard handles (not lexical)
71             use open::layers STDIN => ':encoding(UTF-8)';
72             use open::layers STDOUT => ':encoding(UTF-8)', STDERR => ':encoding(UTF-8)';
73             use open::layers STDIO => ':encoding(UTF-8)'; # shortcut for all of above
74              
75             =head1 DESCRIPTION
76              
77             This pragma is a reimagination of the core L pragma, which either pushes
78             L layers on the global standard handles, or sets default L
79             layers for handles opened in the current lexical scope (meaning, innermost
80             braces or the file scope). The interface is redesigned to be more explicit and
81             intuitive. See L for details.
82              
83             =head1 ARGUMENTS
84              
85             Each operation is specified in a pair of arguments. The first argument, the
86             flag, specifies the target of the operation, which may be one of:
87              
88             =over
89              
90             =item STDIN, STDOUT, STDERR, STDIO
91              
92             These strings indicate to push the layer(s) onto the associated standard handle
93             with L, affecting usage of that handle globally,
94             equivalent to calling L on the handle in a C
95             block. C is a shortcut to operate on all three standard handles.
96              
97             Note that this will also affect reading from C via L
98             (empty C<< <> >>, C<<< <<>> >>>, or L).
99              
100             =item $handle
101              
102             An arbitrary filehandle will have layer(s) pushed onto it directly, affecting
103             all usage of that handle, similarly to the operation on standard handles.
104             Handles must be passed as a glob or reference to a glob, B a bareword.
105              
106             Note that the handle must be opened in the compile phase (such as in a
107             preceding C block) in order to be available for this pragma to operate
108             on it.
109              
110             =item r, w, rw
111              
112             These strings indicate to set the default layer stack for handles opened in the
113             current lexical scope: C for handles opened for reading, C for handles
114             opened for writing (or C), and C for all handles.
115              
116             This lexical effect works by setting L<${^OPEN}|perlvar/${^OPEN}>, like the
117             L pragma and C<-C> switch. The functions L,
118             L, L,
119             L, L,
120             L, and L (C or
121             backticks) are affected by this variable. Indirect calls to these functions via
122             modules like L occur in a different lexical scope, so are not
123             affected, nor are directory handles such as opened by
124             L.
125              
126             Note that this will also affect implicitly opened read handles such as files
127             opened by L (empty C<< <> >>, C<<< <<>> >>>, or
128             L), but B C via C, or
129             L.
130              
131             A three-argument L call that specifies layers will ignore
132             any lexical defaults. A single C<:> (colon) also does this, using the default
133             layers for the architecture.
134              
135             use open::layers rw => ':encoding(UTF-8)';
136             open my $fh, '<', $file; # sets UTF-8 layer (and its implicit platform defaults)
137             open my $fh, '>:unix', $file; # ignores UTF-8 layer and sets :unix
138             open my $fh, '<:', $file; # ignores UTF-8 layer and sets platform defaults
139              
140             =back
141              
142             The second argument is the layer or layers to set. Multiple layers can be
143             specified like C<:foo:bar>, as in L or
144             L.
145              
146             =head1 COMPARISON TO open.pm
147              
148             =over
149              
150             =item *
151              
152             Unlike L, C requires that the target of the operation is
153             always specified so as to not confuse global and lexical operations.
154              
155             =item *
156              
157             Unlike L, C can push layers to the standard handles without
158             affecting handles opened in the lexical scope.
159              
160             =item *
161              
162             Unlike L, multiple layers are not required to be space separated.
163              
164             =item *
165              
166             Unlike L, duplicate existing encoding layers are not removed from the
167             standard handles. Either ensure that nothing else is setting encoding layers on
168             these handles, or use the C<:raw> pseudo-layer to "reset" the layers to a
169             binary stream before applying text translation layers.
170              
171             use open::layers STDIO => ':raw:encoding(UTF-16BE)';
172             use open::layers STDIO => ':raw:encoding(UTF-16BE):crlf'; # on Windows 5.14+
173              
174             =item *
175              
176             Unlike L, the C<:locale> pseudo-layer is not (yet) implemented. Consider
177             installing L to support this layer.
178              
179             =back
180              
181             =head1 PERLIO LAYERS
182              
183             PerlIO layers are described in detail in the L documentation. Their
184             implementation has several historical quirks that may be useful to know:
185              
186             =over
187              
188             =item *
189              
190             Layers are an ordered stack; a read operation will go through the layers in the
191             order they are set (left to right), and a write operation in the reverse order.
192              
193             =item *
194              
195             The C<:unix> layer implements the lowest level unbuffered I/O, even on Windows.
196             Most other layers operate on top of this and usually a buffering layer like
197             C<:perlio> or C<:crlf>, and these low-level layers make up the platform
198             defaults.
199              
200             =item *
201              
202             Many layers are not real layers that actually implement I/O or translation;
203             these are referred to as pseudo-layers. Some (like C<:utf8>) set flags on
204             previous layers that change how they operate. Some (like C<:pop>) simply modify
205             the existing set of layers. Some (like C<:raw>) may do both.
206              
207             =item *
208              
209             The C<:crlf> layer is not just a translation between C<\n> and C. On
210             Windows, it is the layer that implements I/O buffering (like C<:perlio> on
211             Unix-like systems), and operations that would remove the C translation
212             (like L with no layers, or pushing a C<:raw>
213             pseudo-layer) actually just disable the C translation flag on this layer.
214             Since Perl 5.14, pushing a C<:crlf> layer on top of other translation layers on
215             Windows correctly adds a C translation layer in that position. (On
216             Unix-like systems, C<:crlf> is a mundane C translation layer.)
217              
218             =item *
219              
220             The C<:utf8> pseudo-layer sets a flag that indicates the preceding stack of
221             layers will translate the input to Perl's internal upgraded string format,
222             which may resemble UTF-8 or UTF-EBCDIC, or will translate the output from that
223             format. It is B an encoding translation layer, but an assumption about the
224             byte stream; use C<:encoding(UTF-8)> or L to apply a
225             translation layer. Any encoding translation layer will generally set the
226             C<:utf8> flag, even when the desired encoding is not UTF-8, as they translate
227             between the desired encoding and Perl's internal format. (The C<:bytes>
228             pseudo-layer unsets this flag, which is very dangerous if encoding translation
229             layers are used.)
230              
231             =item *
232              
233             I/O to an in-memory scalar variable instead of a file is implemented by the
234             C<:scalar> layer taking the place of the platform defaults, see
235             L. The scalar is expected to act like a file, i.e. only contain
236             or store bytes.
237              
238             =item *
239              
240             Layers specified when opening a handle, such as in a three-argument
241             L or default layers set in L<${^OPEN}|perlvar/${^OPEN}>
242             (via the lexical usage of this pragma or the L pragma), will define the
243             complete stack of layers on that handle. Certain layers implicitly include
244             lower-level layers that are needed, for example C<:encoding(UTF-8)> will
245             implicitly prepend the platform defaults C<:unix:perlio> (or similar).
246              
247             =item *
248              
249             In contrast, when adjusting layers on an existing handle with
250             L (or the non-lexical usage of this pragma or the
251             L pragma), the specified layers are pushed at the end of the handle's
252             existing layer stack, and any special operations of pseudo-layers take effect.
253             So you can open an unbuffered handle with only C<:unix>, but to remove existing
254             layers on an already open handle, you must push pseudo-layers like L<:pop> or
255             C<:raw> (equivalent to calling L with no layers).
256              
257             =back
258              
259             =head1 CAVEATS
260              
261             The L layers and L pragma have experienced several issues over
262             the years, most of which can't be worked around by this module. It's
263             recommended to use a recent Perl if you will be using complex layers; for
264             compatibility with old Perls, stick to L (either
265             with no layers for a binary stream, or with a single C<:encoding> layer). Here
266             are some selected issues:
267              
268             =over
269              
270             =item *
271              
272             Before Perl 5.8.8, L called with three arguments would
273             ignore L<${^OPEN}|perlvar/${^OPEN}> and thus any lexical default layers.
274             L<[perl #8168]|https://github.com/Perl/perl5/issues/8168>
275              
276             =item *
277              
278             Before Perl 5.8.9, the C<:crlf> layer did not preserve the C<:utf8> flag from
279             an earlier encoding layer, resulting in an improper translation of the bytes.
280             This can be worked around by adding the C<:utf8> pseudo-layer after C<:crlf>
281             (even if it is not a UTF-8 encoding).
282              
283             =item *
284              
285             Before Perl 5.14, the C<:crlf> layer does not properly apply on top of another
286             layer, such as an encoding layer, if it had also been applied earlier in the
287             stack such as is default on Windows. Thus you could not usefully use a layer
288             like C<:encoding(UTF-16BE)> with a following C<:crlf>.
289             L<[perl #8325]|https://github.com/Perl/perl5/issues/8325>
290              
291             =item *
292              
293             Before Perl 5.14, the C<:pop>, C<:utf8>, or C<:bytes> pseudo-layers did not
294             allow stacking further layers, like C<:pop:crlf>.
295             L<[perl #11054]|https://github.com/perl/perl5/issues/11054>
296              
297             =item *
298              
299             Before Perl 5.14, the C<:raw> pseudo-layer reset the handle to an unbuffered
300             state, rather than just removing text translation layers as when calling
301             L with no layers.
302             L<[perl #10904]|https://github.com/perl/perl5/issues/10904>
303              
304             =item *
305              
306             Before Perl 5.14, the C<:raw> pseudo-layer did not work properly with in-memory
307             scalar handles.
308              
309             =item *
310              
311             Before Perl 5.16, L and L are
312             affected by lexical default layers when loading the source file, leading to
313             unexpected results. L<[perl #11541]|https://github.com/perl/perl5/issues/11541>
314              
315             =back
316              
317             =head1 BUGS
318              
319             Report any issues on the public bugtracker.
320              
321             =head1 AUTHOR
322              
323             Dan Book
324              
325             =head1 COPYRIGHT AND LICENSE
326              
327             This software is Copyright (c) 2020 by Dan Book.
328              
329             This is free software, licensed under:
330              
331             The Artistic License 2.0 (GPL Compatible)
332              
333             =head1 SEE ALSO
334              
335             L, L