NAME
open::layers - Set default PerlIO layers
SYNOPSIS
{
# set default layers for open() in this lexical scope
use open::layers r => ':encoding(UTF-8)';
}
# encoding layer no longer applied to handles opened here
use open::layers r => ':encoding(cp1252)', w => ':encoding(UTF-8)';
use open::layers rw => ':encoding(UTF-8)'; # all opened handles
# push layers on the standard handles (not lexical)
use open::layers STDIN => ':encoding(UTF-8)';
use open::layers STDOUT => ':encoding(UTF-8)', STDERR => ':encoding(UTF-8)';
use open::layers STDIO => ':encoding(UTF-8)'; # shortcut for all of above
DESCRIPTION
This pragma is a reimagination of the core open pragma, which either pushes PerlIO layers on the global standard handles, or sets default PerlIO layers for handles opened in the current lexical scope (meaning, innermost braces or the file scope). The interface is redesigned to be more explicit and intuitive. See "COMPARISON TO open.pm" for details.
ARGUMENTS
Each operation is specified in a pair of arguments: the flag specifying the target of the operation, and the layer(s) to apply. Multiple layers can be specified like :foo:bar
, as in open() or binmode().
The flag may be any one of:
- STDIN, STDOUT, STDERR, STDIO
-
These strings indicate to push the layer(s) onto the associated standard handle with binmode(), affecting usage of that handle globally, equivalent to calling binmode() on the handle in a
BEGIN
block.STDIO
is a shortcut to operate on all three standard handles.Note that this will also affect reading from
STDIN
via ARGV (empty<>
,<<>>
, or readline()). - $handle
-
An arbitrary filehandle (glob or reference to a glob, not a bareword) will have layer(s) pushed onto it directly, affecting all usage of that handle, similarly to the operation on standard handles.
Note that the handle must be opened in the compile phase (such as in a preceding
BEGIN
block) in order to be available for this pragma to operate on it. - r, w, rw
-
These strings indicate to set the default layer stack for handles opened in the current lexical scope:
r
for handles opened for reading,w
for handles opened for writing (orO_RDWR
), andrw
for all handles.This lexical effect works by setting ${^OPEN}, like the open pragma and
-C
switch. The functions open(), sysopen(), pipe(), socketpair(), socket(), accept(), and readpipe() (qx
or backticks) are affected by this variable. Indirect calls to these functions via modules like IO::Handle occur in a different lexical scope, so are not affected, nor are directory handles such as opened by opendir().Note that this will also affect implicitly opened read handles such as files opened by ARGV (empty
<>
,<<>>
, or readline()), but notSTDIN
viaARGV
, or DATA.A three-argument open() call that specifies layers will ignore any lexical defaults. A single
:
(colon) also does this, using the default layers for the architecture.use open::layers rw => ':encoding(UTF-8)'; open my $fh, '<', $file; # sets UTF-8 layer (and its implicit platform defaults) open my $fh, '>:unix', $file; # ignores UTF-8 layer and sets :unix open my $fh, '<:', $file; # ignores UTF-8 layer and sets platform defaults
COMPARISON TO open.pm
Unlike open,
open::layers
requires that the target of the operation is always specified so as to not confuse global and lexical operations.Unlike open,
open::layers
can push layers to the standard handles without affecting handles opened in the lexical scope.Unlike open, multiple layers are not required to be space separated.
Unlike open, duplicate existing encoding layers are not removed from the standard handles. Either ensure that nothing else is setting encoding layers on these handles, or use the
:raw
pseudo-layer to "reset" the layers to a binary stream before applying text translation layers.use open::layers STDIO => ':raw:encoding(UTF-16BE)'; use open::layers STDIO => ':raw:encoding(UTF-16BE):crlf'; # on Windows 5.14+
Unlike open, the
:locale
pseudo-layer is not (yet) implemented. Consider installing PerlIO::locale to support this layer.
PERLIO LAYERS
PerlIO layers are described in detail in the PerlIO documentation. Their implementation has several historical quirks that may be useful to know:
Layers are an ordered stack; a read operation will go through the layers in the order they are set (left to right), and a write operation in the reverse order.
The
:unix
layer implements the lowest level unbuffered I/O, even on Windows. Most other layers operate on top of this and usually a buffering layer like:perlio
or:crlf
, and these low-level layers make up the platform defaults.Many layers are not real layers that actually implement I/O or translation; these are referred to as pseudo-layers. Some (like
:utf8
) set flags on previous layers that change how they operate. Some (like:pop
) simply modify the existing set of layers. Some (like:raw
) may do both.The
:crlf
layer is not just a translation between\n
andCRLF
. On Windows, it is the layer that implements I/O buffering (like:perlio
on Unix-like systems), and operations that would remove theCRLF
translation (like binmode() with no layers, or pushing a:raw
pseudo-layer) actually just disable theCRLF
translation flag on this layer. Since Perl 5.14, pushing a:crlf
layer on top of other translation layers on Windows correctly adds aCRLF
translation layer in that position. (On Unix-like systems,:crlf
is a mundaneCRLF
translation layer.)The
:utf8
pseudo-layer sets a flag that indicates the preceding stack of layers will translate the input to Perl's internal upgraded string format, which may resemble UTF-8 or UTF-EBCDIC, or will translate the output from that format. It is not an encoding translation layer, but an assumption about the byte stream; use:encoding(UTF-8)
or PerlIO::utf8_strict to apply a translation layer. Any encoding translation layer will generally set the:utf8
flag, even when the desired encoding is not UTF-8, as they translate between the desired encoding and Perl's internal format. (The:bytes
pseudo-layer unsets this flag, which is very dangerous if encoding translation layers are used.)I/O to an in-memory scalar variable instead of a file is implemented by the
:scalar
layer taking the place of the platform defaults, see PerlIO::scalar. The scalar is expected to act like a file, i.e. only contain or store bytes.Layers specified when opening a handle, such as in a three-argument open() or default layers set in ${^OPEN} (via the lexical usage of this pragma or the open pragma), will define the complete stack of layers on that handle. Certain layers implicitly include lower-level layers that are needed, for example
:encoding(UTF-8)
will implicitly prepend the platform defaults:unix:perlio
(or similar).In contrast, when adjusting layers on an existing handle with binmode() (or the non-lexical usage of this pragma or the open pragma), the specified layers are pushed at the end of the handle's existing layer stack, and any special operations of pseudo-layers take effect. So you can open an unbuffered handle with only
:unix
, but to remove existing layers on an already open handle, you must push pseudo-layers like:pop
or:raw
(equivalent to calling binmode() with no layers).
CAVEATS
The PerlIO layers and open pragma have experienced several issues over the years, most of which can't be worked around by this module. It's recommended to use a recent Perl if you will be using complex layers; for compatibility with old Perls, stick to binmode() (either with no layers for a binary stream, or with a single :encoding
layer). Here are some selected issues:
Before Perl 5.8.8, open() called with three arguments would ignore ${^OPEN} and thus any lexical default layers. [perl #8168]
Before Perl 5.8.9, the
:crlf
layer did not preserve the:utf8
flag from an earlier encoding layer, resulting in an improper translation of the bytes. This can be worked around by adding the:utf8
pseudo-layer after:crlf
(even if it is not a UTF-8 encoding).Before Perl 5.14, the
:crlf
layer does not properly apply on top of another layer, such as an encoding layer, if it had also been applied earlier in the stack such as is default on Windows. Thus you could not usefully use a layer like:encoding(UTF-16BE)
with a following:crlf
. [perl #8325]Before Perl 5.14, the
:pop
,:utf8
, or:bytes
pseudo-layers did not allow stacking further layers, like:pop:crlf
. [perl #11054]Before Perl 5.14, the
:raw
pseudo-layer reset the handle to an unbuffered state, rather than just removing text translation layers as when calling binmode() with no layers. [perl #10904]Before Perl 5.14, the
:raw
pseudo-layer did not work properly with in-memory scalar handles.Before Perl 5.16, use and require() are affected by lexical default layers when loading the source file, leading to unexpected results. [perl #11541]
BUGS
Report any issues on the public bugtracker.
AUTHOR
Dan Book <dbook@cpan.org>
COPYRIGHT AND LICENSE
This software is Copyright (c) 2020 by Dan Book.
This is free software, licensed under:
The Artistic License 2.0 (GPL Compatible)