Permalink
Browse files

Support more modes in IO::Handle.open

Introduces the following named parameters:

    :mode<ro> :mode<wo> :mode<rw> :mode<pipe>
    :create :append :truncate :exclusive

In addition to :p, :r, :w, :a and the (previously broken) :rw,
there's now also :update, :x, :rx and :ra, with following
expansions:

    :p      --> :mode<pipe>
    :r      --> :mode<ro>
    :w      --> :mode<wo> :create :truncate
    :x      --> :mode<wo> :create :exclusive
    :a      --> :mode<wo> :create :append
    :update --> :mode<rw>
    :rw     --> :mode<rw> :create
    :rx     --> :mode<rw> :create :exclusive
    :ra     --> :mode<rw> :create :append

The combination of :r with one of the flags :w, :x or :a tries
to DWIM, ie

    :r :w --> :rw
    :r :x --> :rx
    :r :a --> :ra

In particular, :r :w does NOT truncate.

C11 fopen() and Perl 5 &open modes correspond to the following
Perl 6 modes:

    C11     P5      P6
    r       <       :r
    w       >       :w
    wx              :x
    a       >>      :a
    r+      +<      :update
    w+      +>      :rw :truncate
    w+x             :rx
    a+      +>>     :ra

Neither Perl 5 nor C11 come with an equivalent to :rw which
(in contrast to update) does not fail if the file had to be created.

On Parrot and the JVM, none of the new modes are supported.
In addition, using :rw on these backends will now throw an error
instead of silently gettind adjusted to :w (cf #125170).
  • Loading branch information...
cygx committed May 16, 2015
1 parent 55ed38e commit 36f773eb010df7c6b8bf0d431d209537a6061d15
Showing with 65 additions and 13 deletions.
  1. +65 −13 src/core/IO/Handle.pm
@@ -14,23 +14,48 @@ my class IO::Handle does IO {
}
method open(IO::Handle:D:
:$r is copy,
:$w is copy,
:$rw,
:$a,
:$p,
:$p, :$r, :$w, :$x, :$a, :$update,
:$rw, :$rx, :$ra,
:$mode is copy,
:$create is copy,
:$append is copy,
:$truncate is copy,
:$exclusive is copy,
:$bin,
:$chomp = True,
:$enc = 'utf8',
:$nl = "\n",
) {
$mode //= do {
when so $p { 'pipe' }
when so ($r && $w) || $rw { $create = True; 'rw' }
when so ($r && $x) || $rx { $create = $exclusive = True; 'rw' }
when so ($r && $a) || $ra { $create = $append = True; 'rw' }
when so $r { 'ro' }
when so $w { $create = $truncate = True; 'wo' }
when so $x { $create = $exclusive = True; 'wo' }
when so $a { $create = $append = True; 'wo' }
when so $update { 'rw' }
default { 'ro' }
}
if $!path eq '-' {
$!path =
IO::Special.new(:what( $w ?? << <STDOUT> >> !! << <STDIN> >> ));
$!path = IO::Special.new:
what => do given $mode {
when 'ro' { '<STDIN>' }
when 'wo' { '<STDOUT>' }
default {
die "Cannot open standard stream in mode '$_'";
}
}
}
if nqp::istype($!path,IO::Special) {
if nqp::istype($!path, IO::Special) {
my $what := $!path.what;
if $what eq '<STDIN>' {
$!PIO := nqp::getstdin();
@@ -51,9 +76,8 @@ my class IO::Handle does IO {
fail (X::IO::Directory.new(:$!path, :trying<open>))
if $!path.e && $!path.d;
$r = $w = True if $rw;
if $p {
if $mode eq 'pipe' {
$!pipe = 1;
my str $errpath;
@@ -65,11 +89,40 @@ my class IO::Handle does IO {
);
}
else {
my $mode = $w ?? 'w' !! ($a ?? 'wa' !! 'r' );
my $llmode = do given $mode {
when 'ro' { 'r' }
when 'wo' { '-' }
when 'rw' { '+' }
default { die "Unknown mode '$_'" }
}
$llmode = join '', $llmode,
$create ?? 'c' !! '',
$append ?? 'a' !! '',
$truncate ?? 't' !! '',
$exclusive ?? 'x' !! '';
#?if !moar
# don't use new modes on anything but MoarVM
# TODO: check what else can be made to work on Parrot
# cf io/utilities.c, Parrot_io_parse_open_flags()
# platform/generic/io.c, convert_flags_to_unix()
# platform/win32/io.c, convert_flags_to_win32 ()
$llmode = do given $llmode {
when 'r' { 'r' }
when '-ct' { 'w' }
when '-ca' { 'wa' }
default {
die "Backend { $*VM.name
} does not support opening files in mode '$llmode'";
}
}
#?endif
# TODO: catch error, and fail()
$!PIO := nqp::open(
nqp::unbox_s($!path.abspath),
nqp::unbox_s($mode),
nqp::unbox_s($llmode),
);
}
@@ -79,7 +132,6 @@ my class IO::Handle does IO {
self;
}
method input-line-separator {
DEPRECATED("nl",|<2015.03 2015.09>);
self.nl;

0 comments on commit 36f773e

Please sign in to comment.