Author: wayland Date: 2009-02-23 04:07:23 +0100 (Mon, 23 Feb 2009) New Revision: 25488
Modified: docs/Perl6/Spec/S16-io.pod docs/Perl6/Spec/S32-setting-library/IO.pod Log: Moved stuff from S16-io to S32-setting-library/IO Modified: docs/Perl6/Spec/S16-io.pod =================================================================== --- docs/Perl6/Spec/S16-io.pod 2009-02-23 02:21:44 UTC (rev 25487) +++ docs/Perl6/Spec/S16-io.pod 2009-02-23 03:07:23 UTC (rev 25488) @@ -40,946 +40,6 @@ Many of the roles and functions below will operate on the default handles. To set all 3 at once, do C<($*DEFIN, $*DEFOUT, $*DEFERR) ::= ($*IN, $*OUT, $*ERR)>. -=head1 Roles - -The functionality of IO objects is broken down into several roles, -which should identify the features each object supports. - -=head2 IO - -The base role only tags that this is an IO object for more generic -purposes. It doesn't specify any methods or attributes. - -=head2 IO::Readable - -This role provides unbuffered read access to the data stream. - -role IO::Readable { - has $.isReadable; - - method Int read($buf is rw, Int $length) -} - -When the $.isReadable is set, it tries to change the readability of the filehandle. This -is not always possible, but can be done in a number of cases. IO::Socket can remove -readability by calling shutdown(), for example. - -=over - -=item method Int read($buf is rw, Int $length) - -Tries to read $length bytes and store in $buf. The contents of $buf -are replaced and the actual number of bytes read is returned. A return -of 0 means end of file. It might return unthrown failures, to be -specified by each IO implementation. - -It is important to realize that this is "raw" read. You're going to -have plain octets stored in $buf, if this is actually encoded data, -you're going to need to encode it later, or use "getc" or other -IO::Readable::Encoded methods. - -=back - -=head2 IO::Writeable - -This role provides unbuffered write access to the data stream. - -role IO::Writeable { - has $.isWriteable; - - method Int write($buf, Int $length) -} - -When the $.isWriteable is set, it tries to change the writeability of the filehandle. -This is not always possible, but can be done in a number of cases. IO::Socket can remove -writeability by calling shutdown(), for example. - -=over - -=item method Int write($buf, Int $length) - -Tries to write $length bytes of $buf. The actual number of bytes -written is returned. It might return unthrown failures, to be -specified by each IO implementation. - -It is important to realize that this is "raw" write. $buf should -contain plain octets that are going to be sent. If $buf contains -encoded data, you should decode it first, or use "print" or other -IO::Writeable::Encoded methods. - -=back - -=head2 IO::Seekable - -=over - -=item method Bool eoi() - -Returns true if it's the end of the input (ie. end of file or whatever), returns false if -not, returns undef if we can't say for certain. - -=item method Bool seek(Int $position) - -Position this stream into $position. The meaning of this position is -always in "octets". - -=item method Int tell() - -Returns the current raw position in the stream in number of "octets". - -=back - -=head2 IO::Buffered - -Indicates that this object performs buffering. The management of the -buffer is completely implementation specific. - -=over - -=item method Bool flush() - -Flushes the buffers associated with this object. - -=item method Bool autoflush() is rw - -Forces this object to keep its buffers empty - -=back - -=head2 IO::Streamable - -This role represents objects that depend on some external resource, -which means that data might not be available at request. - -=over - -=item method Bool blocking() is rw - -This allows the user to control wether this object should do a -blocking wait or immediatly return in the case of not having data -available. - -=back - -=head2 IO::Encoded - -This is a generic role for encoded data streams. - -=over - -=item method Str encoding() is rw - -=item method Str locale() is rw - -Encoding and locale are required for sane conversions. - -=back - -=head2 IO::Readable::Encoded - -This role provides encoded access to a readable data stream, implies -IO::Encoded. Might imply IO::Buffered, but that's not a requirement. - -=over - -=item method Str input_record_separator() is rw - -This regulates how "readline" behaves. - -=item method Str input_field_separator() is rw - -This regulates how "readfield" behaves. - -=item method Str input_escape() is rw - -This allows the definition of a escape character, which should be used -by readline and readfield. - -=item method Str readline() - -Reads the stream before it finds a $.input_record_separator and -returns it (including the separator). If $.input_escape is set, it -should pay attention to that. - -=item method Str readfield() - -Reads the stream before it finds a $.input_field_separator and returns -it (including the separator). If a readfield finds a -$.input_record_separator it consumes the record separator, but returns -undef. If $.input_escape is set, it should pay attention to that. - -=item method Str getc(Int $length? = 1) - -Reads the next $length character in the set $.encoding according to -the $.locale, or the undefined value at end of file, or if there was -an error (in the latter case C<$!> is set). - -=back - -=head2 IO::Writeable::Encoded - -This role provides encoded access to a writeable data stream, implies -IO::Encoded. Might imply IO::Buffered, but that's not a requirement. - -If these are called in their non-object form, they operate on C<$*DEFOUT>, except in the -case of warn(), which operates on C<$*DEFERR>. The form with leading dot prints C<$_> to -the appropriate default handle unless an explicit filehandle is supplied. - -=over - -=item method Str output_record_separator() is rw - -This regulates how say and print(%hash) behaves. - -=item method Str output_field_separator() is rw - -This regulates how print(@arr), say(@arr), print(%hash) and -say(%hash) behave. - -=item method Str output_escape() is rw - -This allows the definition of a escape character, which should be used -by say and print to preserve the record/field semantics. - -=item method Bool print(Str $str) - -=item method Bool say(Str $str) - -Sends $str to the data stream doing proper encoding conversions. Say -sends an additional $.output_record_separator. This should also -convert "\n" to the desired $.output_record_separator. - -=item method Bool print(Array @arr) - -=item method Bool say(Array @arr) - -Sends each element of @arr separated by $.output_field_separator. Say -should add an additional $.output_record_separator. If an element -contains the $.output_record_separator or the -$.output_field_seaparator and a $.output_escape is defined, it should -do the escaping. - -=item method Bool print(Hash %hash) - -=item method Bool say(Hash %hash) - -Sends each pair of the hash separated by $.output_record_separator, -with key and value separated by $.output_field_separator. If one of -those contains a $.output_record_separator or a -$.output_field_seaparator and $.output_escape is set, it should do the -escaping. - -=item our Bool method print (IO $self: *...@list) - -=item our Bool multi print (*...@list) - -=item our Bool method print (Str $self: IO $io) - -Prints a string or a list of strings. Returns Bool::True if -successful, Failure otherwise. The IO handle, if supplied, must be -an object that supports I/O. Indirect objects in Perl 6 must always -be followed by a colon, and any indirect object more complicated than -a variable should be put into parentheses. - -It is a compiler error to use a bare C<print> without arguments. -(However, it's fine if you have an explicit argument list that evaluates to -the empty list at runtime.) - -=item say our Bool method say (IO $self: *...@list) - -=item our Bool multi say (*...@list) - -=item our Bool method say (Str $self: IO $io) - -This is identical to print() except that it auto-appends a newline after -the final argument. - - Was: print "Hello, world!\n"; - Now: say "Hello, world!"; - -As with C<print>, it is a compiler error to use a bare C<say> without -arguments. - -=item our Bool method printf (IO $self: Str $fmt, *...@list) - -=item our Bool multi printf (Str $fmt, *...@list) - -The function form works as in Perl 5 and always prints to $*DEFOUT. -The method form uses IO handles, not formats, as objects. - -=back - -=head2 IO::Closeable - -This role indicates that this object can be closed. - -=over - -=item method Bool close() - -Closes the file or pipe associated with the object. - -Returns True on success, but might return an unthrown failure. -Returns true only if IO buffers are successfully flushed and closes the system -file descriptor. - -Unlike in Perl 5, an IO object is not a special symbol table entry -neither this object is available magically anywhere else. But as in -Perl 5, unless stated otherwise, IO::Closeable objects always close -themselves during destruction - -=back - -=head2 IO::Socket - -role IO::Socket { - has %.options; -... -} - -Accessing the %.options would on Unix be done with getsockopt/setsockopt. - -=over - -=item pair - - our List of IO method pair(Int $domain, Int $type, Int $protocol) - -A wrapper for socketpair(2), returns a pair of IO objects representing the -reader and writer ends of the socket. - - use Socket; - ($r, $w) = Socket.pair(AF_UNIX, SOCK_STREAM, PF_UNSPEC); - - -=back - -=head2 IO::Listening - -=item open - - method open() - - Does a bind() and a listen(). - -=item accept - - method IO::Socket accept() - -=head2 IO::FileDescriptor - -This role indicates that this object actually represents an open file -descriptor in the os level. - -=over - -=item method int fileno() - -File descriptors are always native integers, conforming to C89. - -=back - -=head1 Classes - -=head2 IO::File - -This does file input and output. - -class IO::File does IO::Streamable { -... -} - -=over - -=item new - - method new(Str :$filename, $options?); - method new(Int :$fd); - - # Read - $fobj = new IO::File($filename); - - # Write - $fobj = new IO::File($filename, :w); - - # Read using file descriptor - $fobj = new IO::File($fd); - -Associate an IO object with an already-open file descriptor, -presumably passed in from the parent process. - -=item open() - - the :binmode option can be passed to open() - -=item IO.truncate - -=item IO.fcntl - -Available only as a handle method. - -=back - -=head2 IO::FileSystem - -This reads directories, deletes filesystem entries, creates links, and the like. - -class IO::FileSystem does IO::Streamable does Tree { - has Str $.fstype; # ext3, ntfs, vfat, reiserfs, etc - has Str $.illegal_chars; # ie. /\x0 - has Int $.max_path; -... -} - -It inherits $cwn and $root from Tree. - -=over 4 - -=item glob - -Returns FSNode objects - -=item find - -Returns FSNode objects - -=item link - -=item mkdir - -=item IO::Dir::open EXPR - - my $dir = IO::Dir::open('.'); - -Opens a directory named EXPR for processing. Makes the directory looks like -a list of autochomped lines, so just use ordinary IO operators after the open. - -=item readlink - -=item rename - -=item rmdir FILENAME -X<rmdir> X<rd> X<directory, remove> - -=item rmdir - -Deletes the directory specified by FILENAME if that directory is -empty. If it succeeds it returns true, otherwise it returns false and -sets C<$!> (errno). If FILENAME is omitted, uses C<$_>. - -=item symlink - -=item unlink LIST -X<unlink> X<delete> X<remove> X<rm> - -=item unlink - -Deletes a list of files. Returns the number of files successfully -deleted. - - $cnt = unlink 'a', 'b', 'c'; - -Be warned that unlinking a directory can inflict damage on your filesystem. -Finally, using C<unlink> on directories is not supported on many operating -systems. Use C<rmdir> instead. - -It is an error to use bare C<unlink> without arguments. - -=back - -=head2 IO::FSNode - -class IO::FSNode does Tree::Node { - has Array of IO::FSNodeACL @.ACLs; - has Hash of %.times; -... -} - -The %times has keys that can be eg. ctime, Modification, and Access (and maybe others on -other operating systems), and the values are all DateTime objects. - -When .path() is implemented, it should return the path that this was opened with. - -=over 4 - -=item IO ~~ :X -X<:r>X<:w>X<:x>X<:o>X<:R>X<:W>X<:X>X<:O>X<:e>X<:z>X<:s>X<:f>X<:d>X<:l>X<:p> -X<:S>X<:b>X<:c>X<:t>X<:u>X<:g>X<:k>X<:T>X<:B>X<:M>X<:A>X<:C> - -=item EXPR ~~ :X - - $file.:X - $file ~~ :X - -A file test, where X is one of the letters listed below. This unary -operator takes one argument, either a filename or a filehandle, and -tests the associated file to see if something is true about it. - -A Pair used as a pattern is treated as a file test. - - :r File is readable by effective uid/gid. - :w File is writable by effective uid/gid. - :x File is executable by effective uid/gid. - :o File is owned by effective uid. - - :R File is readable by real uid/gid. - :W File is writable by real uid/gid. - :X File is executable by real uid/gid. - :O File is owned by real uid. - - :e File exists. - :z File has zero size (is empty). - :s File has nonzero size (returns size in bytes). - - :f File is a plain file. - :d File is a directory. - :l File is a symbolic link. - :p File is a named pipe (FIFO), or Filehandle is a pipe. - :S File is a socket. - :b File is a block special file. - :c File is a character special file. - :t Filehandle is opened to a tty. - - :u File has setuid bit set. - :g File has setgid bit set. - :k File has sticky bit set. - - :T File is an ASCII text file (heuristic guess). - :B File is a "binary" file (opposite of :T). - - :M Script start time minus file modification time, in days. - :A Same for access time. - :C Same for inode change time (Unix, may differ for other platforms) - -The interpretation of the file permission operators C<:r>, C<:R>, -C<:w>, C<:W>, C<:x>, and C<:X> is by default based solely on the mode -of the file and the uids and gids of the user. There may be other -reasons you can't actually read, write, or execute the file. Such -reasons may be for example network filesystem access controls, ACLs -(access control lists), read-only filesystems, and unrecognized -executable formats. - -Also note that, for the superuser on the local filesystems, the C<:r>, -C<:R>, C<:w>, and C<:W> tests always return 1, and C<:x> and C<:X> return 1 -if any execute bit is set in the mode. Scripts run by the superuser -may thus need to do a stat() to determine the actual mode of the file, -or temporarily set their effective uid to something else. - -If you are using ACLs, there is a pragma called C<filetest> that may -produce more accurate results than the bare stat() mode bits. -When under the C<use filetest 'access'> the above-mentioned filetests -will test whether the permission can (not) be granted using the -access() family of system calls. Also note that the C<:x> and C<:X> may -under this pragma return true even if there are no execute permission -bits set (nor any extra execute permission ACLs). This strangeness is -due to the underlying system calls' definitions. Read the -documentation for the C<filetest> pragma for more information. - -The C<:T> and C<:B> switches work as follows. The first block or so of the -file is examined for odd characters such as strange control codes or -characters with the high bit set. If too many strange characters (>30%) -are found, it's a C<:B> file; otherwise it's a C<:T> file. Also, any file -containing null in the first block is considered a binary file. If C<:T> -or C<:B> is used on a filehandle, the current IO buffer is examined -rather than the first block. Both C<:T> and C<:B> return true on a null -file, or a file at EOF when testing a filehandle. Because you have to -read a file to do the C<:T> test, on most occasions you want to use a C<:f> -against the file first, as in C<next unless $file ~~ :f && $file ~~ :T >. - -You can test multiple features using junctions: - - if -$filename ~~ :r & :w & :x {...} - -Or pass multiple tests together in OO style: - - if $filename.TEST(:e,:x) {...} - - -=item realpath - - method Str realpath(); - -Gets the real path to the object, resolving softlinks/shortcuts, etc - -=item === operator - - method infix:<===>(Str $filename); - -Test whether the specified filename is the same file as this file. On a Unix system, -this would presumably be done by comparing inode numbers or something. - -=item new - -This is called automatically on object creation. - -multi method new(Array of Str :@pathelements); -multi method new(String :$type, String :$path); -multi method new(String :$path); - -This last throws an error if "use portable" pragma is used. - -Examples: - - $fsnode = new IO::FSNode(pathelements => ['home', 'wayland']); - $fsnode = new IO::FSNode(type => 'Unix', path => '/home/wayland'); - $fsnode = new IO::FSNode(path => '/home/wayland'); - -=back - -=head2 IO::FSNodeACL - -This is a basic abstraction; for better control, use the operating-system specific -interfaces, over which this is a thin veneer. - -class IO::FSNodeACL { - has Str $.type; # "User", "Group", "Everyone", ??? - has Str $.id; # username or groupname; unused for $type eq "Everyone" - has %.permissions; - # Unsupported values may (or may not) throw - # UnsupportedPermission when set or read - has IO::FSNode $.owningObject; -... -} - -The permissions used in %permissions are: - -=over - -=item Readable - -Should be supported by all filesystems as an item to read from the hash for the group -"Everyone". - -=item Writeable - -Should be supported by all filesystems as an item to read from the hash for the group -"Everyone". - -=item Executeable - -Supported on most Unix systems, anyway. Windows should be able to guess when this is -read, and throw an exception if written to. - -=item Default - -An ACL of User,fred,Default sets the user "fred" to be the owner of the file. This can be -done with groups too. Work on Unix, at least. - -=back - -The $.owningObject attribute of FSNodeACL shows what the ACL is set on. On a -Windows system, this can be a parent directory, as permissions are inherited. - -=head2 IO::FileNode - - role IO::FileNode does IO::FSNode { -... - } - -=over - -=item our List multi method lines (IO $handle:) is export; - -=item our List multi lines (Str $filename); - -Returns all the lines of a file as a (lazy) List regardless of context. -See also C<slurp>. - -=item our Item multi method slurp (IO $handle: *%opts) is export; - -=item our Item multi slurp (Str $filename, *%opts); - -Slurps the entire file into a Str or Buf regardless of context. -(See also C<lines>.) Whether a Str or Buf is returned depends on -the options. - -=back - -=head2 IO::DirectoryNode - - role IO::DirectoryNode does IO::FSNode { -... - } - -=head2 IO::Socket::TCP - -class IO::Socket::TCP does IO::Socket does IO::Streamable { -... -} - -=over - -=item has $.RemoteHost - -=item has $.RemotePort - -=item has $.LocalHost - -=item has $.LocalPort - -=item new - - method IO::Socket::TCP new( - :$RemoteHost, :$RemotePort, - :$LocalHost, :$LocalPort, - :$Blocking, - :$NoOpen - ); - -The creation of the object will also open the connection, unless NoOpen is specified. - -=item open - - method open() - -If it's not an IO::Listening, it does a connect(). - -It's intended for the case where the creation of the object didn't do one. - -=item method Int read($buf is rw, Int $length) - -Does a recv(). - -=item method Int write($buf, Int $length) - -Does a send(). - -=item IO.getpeername - -=item /[get|set][host|net|proto|serv|sock].*/ - -=back - -=head2 IO::Pipe - -class IO::Pipe does IO::Streamable { -... -} - -May also do IO::Readable and IO::Writable, depending on opening method. - -=over - -=item close() - -If the file handle came from a piped open, C<close> will additionally -return false if one of the other system calls involved fails, or if the -program exits with non-zero status. (If the only problem was that the -program exited non-zero, C<$!> will be set to C<0>.) Closing a pipe -also waits for the process executing on the pipe to complete, in case you -want to look at the output of the pipe afterwards, and -implicitly puts the exit status value of that command into C<$!>. - -=item Pipe.to - - our IO method to(Str $command, *%opts) - -Opens a one-way pipe writing to $command. IO redirection for -stderr is specified with :err(IO) or :err<Str>. Other IO redirection -is done with feed operators. XXX how to specify "2>&1"? - -=item Pipe.from - - our IO method from(Str $command, *%opts) - -Opens a one-way pipe reading from $command. IO redirection for -stderr is specified with :err(IO) or :err<Str>. Other IO redirection -is done with feed operators. XXX how to specify "2>&1"? - -=item Pipe.pair - - our List of IO method pair() - -A wrapper for pipe(2), returns a pair of IO objects representing the -reader and writer ends of the pipe. - - ($r, $w) = Pipe.pair; - -=back - -=head1 Calls that operate on the default IO handle - -=over - -=item close() - -=item open() - -... - -=back - -=head1 OS-specific classes - -=head2 Unix - -=head2 IO::FSNode::Unix - -=item chown - - our Int multi chown ($uid = -1, $gid = -1, *...@files) - -Changes the owner (and group) of a list of files. The first -two elements of the list must be the numeric uid and gid, in -that order. A value of -1 in either position is interpreted by -most systems to leave that value unchanged. Returns the number -of files successfully changed. - - $count = chown $uid, $gid, ’foo’, ’bar’; - chown $uid, $gid, @filenames; - -On systems that support C<fchown>, you might pass file handles -among the files. On systems that don’t support C<fchown>, passing -file handles produces a fatal error at run time. - -Here’s an example that looks up nonnumeric uids in the passwd -file: - - $user = prompt "User: "; - $pattern = prompt "Files: "; - - ($login,$pass,$uid,$gid) = getpwnam($user) - or die "$user not in passwd file"; - - @ary = glob($pattern); # expand filenames - chown $uid, $gid, @ary; - -On most systems, you are not allowed to change the ownership of -the file unless you’re the superuser, although you should be -able to change the group to any of your secondary groups. On -insecure systems, these restrictions may be relaxed, but this -is not a portable assumption. On POSIX systems, you can detect -this condition this way: - - use POSIX qw(sysconf _PC_CHOWN_RESTRICTED); - $can_chown_giveaway = not sysconf(_PC_CHOWN_RESTRICTED); - -=item chmod LIST -X<chmod> X<permission> X<mode> - -Changes the permissions of a list of files. The first element of the -list must be the numerical mode, which should probably be an octal -number, and which definitely should I<not> be a string of octal digits: -C<0o644> is okay, C<0644> is not. Returns the number of files -successfully changed. - - $cnt = chmod 0o755, 'foo', 'bar'; - chmod 0o755, @executables; - $mode = '0644'; chmod $mode, 'foo'; # !!! sets mode to --w----r-T - $mode = '0o644'; chmod $mode, 'foo'; # this is better - $mode = 0o644; chmod $mode, 'foo'; # this is best - -=item lstat - -Returns a stat buffer. If the lstat succeeds, the stat buffer evaluates -to true, and additional file tests may be performed on the value. If -the stat fails, all subsequent tests on the stat buffer also evaluate -to false. - -=item stat - -=item IO.stat - -Returns a stat buffer. If the lstat succeeds, the stat buffer evaluates -to true, and additional file tests may be performed on the value. If -the stat fails, all subsequent tests on the stat buffer also evaluate -to false. - -=head2 IO::POSIX - -Indicates that this object can perform standard posix IO -operations. It implies IO::Readable and IO::Writeable. - -=over - -=item method IO dup() - -=item has Bool $.blocking is rw - -=item method Bool flock(:$r,:$w) - -=item method Bool funlock() - -=item ... - -=back - -=head1 Unfiled - -=over 4 - -=item IO.ioctl - -Available only as a handle method. - -=item alarm - -=item prompt - - our Str prompt (Str $prompt) - - Should there be an IO::Interactive role? - -=item Str.readpipe - -=item sysopen - -=item IO.sysseek - -=item umask - -=back - -=head1 Removed functions - -=over - -=item IO.eof - -Gone, see IO::Endable - -=item IO.fileno - -See IO::FileDescriptor - -=item IO.name - -Changed to .path(), but we haven't gotten around to specifying this on all of them. - -The C<.name> method returns the name of the file/socket/uri the handle -was opened with, if known. Returns undef otherwise. There is no -corresponding C<name()> function. - -=item pipe - -Gone, see Pipe.pair - -=item select(both) - -Gone. (Note: for subsecond sleep, just use sleep with a fractional argument.) - -=item IO.shutdown() - -Gone, see IO::Socket.close(), $IO::Readable.isReadable, and $IO::Writeable.isWriteable - -=item socketpair - -Gone, see Socket.pair - -=item IO.sysread - -Gone, see IO::Readable.read() - -=item IO.syswrite - -Gone, see IO::Writeable.read() - -=item utime - -Gone, see %IO::FSNode.times. - -=back - =head1 Additions Please post errors and feedback to perl6-language. If you are making Modified: docs/Perl6/Spec/S32-setting-library/IO.pod =================================================================== --- docs/Perl6/Spec/S32-setting-library/IO.pod 2009-02-23 02:21:44 UTC (rev 25487) +++ docs/Perl6/Spec/S32-setting-library/IO.pod 2009-02-23 03:07:23 UTC (rev 25488) @@ -7,16 +7,17 @@ =head1 Version - Author: Rod Adams <r...@rodadams.net> + Author: Rod Adams <r...@rodadams.net>, the authors of the related Perl 5 docs. Maintainer: Larry Wall <la...@wall.org> Contributions: Aaron Sherman <a...@ajs.com> Mark Stosberg <m...@summersault.com> Carl Mäsak <cma...@gmail.com> Moritz Lenz <mor...@faui2k3.org> Tim Nelson <wayl...@wayland.id.au> - Date: 19 Mar 2009 extracted from S29-functions.pod - Last Modified: 19 Feb 2009 - Version: 1 + Daniel Ruoso <dan...@ruoso.com> + Date: 19 Feb 2009 extracted from S29-functions.pod; added stuff from S16-IO later + Last Modified: 23 Feb 2009 + Version: 2 The document is a draft. @@ -57,12 +58,995 @@ See C<Synopsis 16: IPC / IO / Signals> for details. +=item uri + + IO::Streamable method uri(Str $uri); + +Returns an appropriate IO::Streamable descendant, with the type depending on the uri +passed in. Here's the mapping: + + URI type IO type + ======== ======= + file: IO::File or IO::Directory + ftp: IO::Socket::TCP (data channel) + http: IO::Socket::TCP + +IO::Streamable method uri(Str $uri) { + $uri.match(/^<alnum>+\:/); + return(&$PROTOCOLS{$1}($uri)); +} + +=item %PROTOCOLS global variable + +For each protocol, stores a subroutine reference that returns the appropriate object when +the URI is passed in. + =back +=head1 Roles + +The functionality of IO objects is broken down into several roles, +which should identify the features each object supports. + +=head2 IO + +The base role only tags that this is an IO object for more generic +purposes. It doesn't specify any methods or attributes. + +=head2 IO::Readable + +This role provides unbuffered read access to the data stream. + +role IO::Readable { + has $.isReadable; + + method Int read($buf is rw, Int $length) +} + +When the $.isReadable is set, it tries to change the readability of the filehandle. This +is not always possible, but can be done in a number of cases. IO::Socket can remove +readability by calling shutdown(), for example. + +=over + +=item method Int read($buf is rw, Int $length) + +Tries to read $length bytes and store in $buf. The contents of $buf +are replaced and the actual number of bytes read is returned. A return +of 0 means end of file. It might return unthrown failures, to be +specified by each IO implementation. + +It is important to realize that this is "raw" read. You're going to +have plain octets stored in $buf, if this is actually encoded data, +you're going to need to encode it later, or use "getc" or other +IO::Readable::Encoded methods. + +=back + +=head2 IO::Writeable + +This role provides unbuffered write access to the data stream. + +role IO::Writeable { + has $.isWriteable; + + method Int write($buf, Int $length) +} + +When the $.isWriteable is set, it tries to change the writeability of the filehandle. +This is not always possible, but can be done in a number of cases. IO::Socket can remove +writeability by calling shutdown(), for example. + +=over + +=item method Int write($buf, Int $length) + +Tries to write $length bytes of $buf. The actual number of bytes +written is returned. It might return unthrown failures, to be +specified by each IO implementation. + +It is important to realize that this is "raw" write. $buf should +contain plain octets that are going to be sent. If $buf contains +encoded data, you should decode it first, or use "print" or other +IO::Writeable::Encoded methods. + +=back + +=head2 IO::Seekable + +=over + +=item method Bool eoi() + +Returns true if it's the end of the input (ie. end of file or whatever), returns false if +not, returns undef if we can't say for certain. + +=item method Bool seek(Int $position) + +Position this stream into $position. The meaning of this position is +always in "octets". + +=item method Int tell() + +Returns the current raw position in the stream in number of "octets". + +=back + +=head2 IO::Buffered + +Indicates that this object performs buffering. The management of the +buffer is completely implementation specific. + +=over + +=item method Bool flush() + +Flushes the buffers associated with this object. + +=item method Bool autoflush() is rw + +Forces this object to keep its buffers empty + +=back + +=head2 IO::Streamable + +This role represents objects that depend on some external resource, +which means that data might not be available at request. + +=over + +=item method Bool blocking() is rw + +This allows the user to control wether this object should do a +blocking wait or immediatly return in the case of not having data +available. + +=back + +=head2 IO::Encoded + +This is a generic role for encoded data streams. + +=over + +=item method Str encoding() is rw + +=item method Str locale() is rw + +Encoding and locale are required for sane conversions. + +=back + +=head2 IO::Readable::Encoded + +This role provides encoded access to a readable data stream, implies +IO::Encoded. Might imply IO::Buffered, but that's not a requirement. + +=over + +=item method Str input_record_separator() is rw + +This regulates how "readline" behaves. + +=item method Str input_field_separator() is rw + +This regulates how "readfield" behaves. + +=item method Str input_escape() is rw + +This allows the definition of a escape character, which should be used +by readline and readfield. + +=item method Str readline() + +Reads the stream before it finds a $.input_record_separator and +returns it (including the separator). If $.input_escape is set, it +should pay attention to that. + +=item method Str readfield() + +Reads the stream before it finds a $.input_field_separator and returns +it (including the separator). If a readfield finds a +$.input_record_separator it consumes the record separator, but returns +undef. If $.input_escape is set, it should pay attention to that. + +=item method Str getc(Int $length? = 1) + +Reads the next $length character in the set $.encoding according to +the $.locale, or the undefined value at end of file, or if there was +an error (in the latter case C<$!> is set). + +=back + +=head2 IO::Writeable::Encoded + +This role provides encoded access to a writeable data stream, implies +IO::Encoded. Might imply IO::Buffered, but that's not a requirement. + +If these are called in their non-object form, they operate on C<$*DEFOUT>, except in the +case of warn(), which operates on C<$*DEFERR>. The form with leading dot prints C<$_> to +the appropriate default handle unless an explicit filehandle is supplied. + +=over + +=item method Str output_record_separator() is rw + +This regulates how say and print(%hash) behaves. + +=item method Str output_field_separator() is rw + +This regulates how print(@arr), say(@arr), print(%hash) and +say(%hash) behave. + +=item method Str output_escape() is rw + +This allows the definition of a escape character, which should be used +by say and print to preserve the record/field semantics. + +=item method Bool print(Str $str) + +=item method Bool say(Str $str) + +Sends $str to the data stream doing proper encoding conversions. Say +sends an additional $.output_record_separator. This should also +convert "\n" to the desired $.output_record_separator. + +=item method Bool print(Array @arr) + +=item method Bool say(Array @arr) + +Sends each element of @arr separated by $.output_field_separator. Say +should add an additional $.output_record_separator. If an element +contains the $.output_record_separator or the +$.output_field_seaparator and a $.output_escape is defined, it should +do the escaping. + +=item method Bool print(Hash %hash) + +=item method Bool say(Hash %hash) + +Sends each pair of the hash separated by $.output_record_separator, +with key and value separated by $.output_field_separator. If one of +those contains a $.output_record_separator or a +$.output_field_seaparator and $.output_escape is set, it should do the +escaping. + +=item our Bool method print (IO $self: *...@list) + +=item our Bool multi print (*...@list) + +=item our Bool method print (Str $self: IO $io) + +Prints a string or a list of strings. Returns Bool::True if +successful, Failure otherwise. The IO handle, if supplied, must be +an object that supports I/O. Indirect objects in Perl 6 must always +be followed by a colon, and any indirect object more complicated than +a variable should be put into parentheses. + +It is a compiler error to use a bare C<print> without arguments. +(However, it's fine if you have an explicit argument list that evaluates to +the empty list at runtime.) + +=item say our Bool method say (IO $self: *...@list) + +=item our Bool multi say (*...@list) + +=item our Bool method say (Str $self: IO $io) + +This is identical to print() except that it auto-appends a newline after +the final argument. + + Was: print "Hello, world!\n"; + Now: say "Hello, world!"; + +As with C<print>, it is a compiler error to use a bare C<say> without +arguments. + +=item our Bool method printf (IO $self: Str $fmt, *...@list) + +=item our Bool multi printf (Str $fmt, *...@list) + +The function form works as in Perl 5 and always prints to $*DEFOUT. +The method form uses IO handles, not formats, as objects. + +=back + +=head2 IO::Closeable + +This role indicates that this object can be closed. + +=over + +=item method Bool close() + +Closes the file or pipe associated with the object. + +Returns True on success, but might return an unthrown failure. +Returns true only if IO buffers are successfully flushed and closes the system +file descriptor. + +Unlike in Perl 5, an IO object is not a special symbol table entry +neither this object is available magically anywhere else. But as in +Perl 5, unless stated otherwise, IO::Closeable objects always close +themselves during destruction + +=back + +=head2 IO::Socket + +role IO::Socket { + has %.options; +... +} + +Accessing the %.options would on Unix be done with getsockopt/setsockopt. + +=over + +=item pair + + our List of IO method pair(Int $domain, Int $type, Int $protocol) + +A wrapper for socketpair(2), returns a pair of IO objects representing the +reader and writer ends of the socket. + + use Socket; + ($r, $w) = Socket.pair(AF_UNIX, SOCK_STREAM, PF_UNSPEC); + + +=back + +=head2 IO::Listening + +=item open + + method open() + + Does a bind() and a listen(). + +=item accept + + method IO::Socket accept() + +=head2 IO::FileDescriptor + +This role indicates that this object actually represents an open file +descriptor in the os level. + +=over + +=item method int fileno() + +File descriptors are always native integers, conforming to C89. + +=back + +=head1 Classes + +=head2 IO::File + +This does file input and output. + +class IO::File does IO::Streamable { +... +} + +=over + +=item new + + method new( + FSNode :$FSNode, + Str :$Filename, + :$fd + Bool :$NoOpen, + :$Writeable, + ); + +The FSNode, Filename and fd options are mutually exclusive. If "use portable" is in +effect, the Filename option throws an error; use an FSNode instead. + +Examples: + + # Read -- throws errors with 'use portable' + $fobj = new IO::File(Filename => $filename); + + # Write -- works with 'use portable' + $fobj = new IO::File( + FSNode => IO::FSNode.new(type => 'Unix', Filename => $filename), + Writeable => 1 + ); + + # Read using file descriptor + $fobj = new IO::File(fd => $fd); + +This final example associates an IO object with an already-open file descriptor, +presumably passed in from the parent process. + +=item open() + +This function opens a file that had the "NoOpen" option passed to the new() method. + +=item IO.truncate + +=item IO.fcntl + +Available only as a handle method. + +=back + +=head2 IO::FileSystem + +This represents the filesystem. + +class IO::FileSystem does IO::Streamable does Tree { + has Str $.fstype; # ext3, ntfs, vfat, reiserfs, etc + has Str $.illegal_chars; # ie. /\x0 + has Int $.max_path; +... +} + +It inherits $cwn and $root from Tree. + +=over 4 + +=item glob + +Returns FSNode objects + +=item find + +Returns FSNode objects + +=item rename + +=back + +=head2 IO::FSNode + +class IO::FSNode does Tree::Node { + has Array of IO::FSNodeACL @.ACLs; + has Hash of %.times; +... +} + +The %times has keys that can be eg. ctime, Modification, and Access (and maybe others on +other operating systems), and the values are all DateTime objects. + +When .path() is implemented, it should return the path that this was opened with. + +=over 4 + +=item IO ~~ :X +X<:r>X<:w>X<:x>X<:o>X<:R>X<:W>X<:X>X<:O>X<:e>X<:z>X<:s>X<:f>X<:d>X<:l>X<:p> +X<:S>X<:b>X<:c>X<:t>X<:u>X<:g>X<:k>X<:T>X<:B>X<:M>X<:A>X<:C> + +=item EXPR ~~ :X + + $file.:X + $file ~~ :X + +A file test, where X is one of the letters listed below. This unary +operator takes one argument, either a filename or a filehandle, and +tests the associated file to see if something is true about it. + +A Pair used as a pattern is treated as a file test. + + :r File is readable by effective uid/gid. + :w File is writable by effective uid/gid. + :x File is executable by effective uid/gid. + :o File is owned by effective uid. + + :R File is readable by real uid/gid. + :W File is writable by real uid/gid. + :X File is executable by real uid/gid. + :O File is owned by real uid. + + :e File exists. + :z File has zero size (is empty). + :s File has nonzero size (returns size in bytes). + + :f File is a plain file. + :d File is a directory. + :l File is a symbolic link. + :p File is a named pipe (FIFO), or Filehandle is a pipe. + :S File is a socket. + :b File is a block special file. + :c File is a character special file. + :t Filehandle is opened to a tty. + + :u File has setuid bit set. + :g File has setgid bit set. + :k File has sticky bit set. + + :T File is an ASCII text file (heuristic guess). + :B File is a "binary" file (opposite of :T). + + :M Script start time minus file modification time, in days. + :A Same for access time. + :C Same for inode change time (Unix, may differ for other platforms) + +The interpretation of the file permission operators C<:r>, C<:R>, +C<:w>, C<:W>, C<:x>, and C<:X> is by default based solely on the mode +of the file and the uids and gids of the user. There may be other +reasons you can't actually read, write, or execute the file. Such +reasons may be for example network filesystem access controls, ACLs +(access control lists), read-only filesystems, and unrecognized +executable formats. + +Also note that, for the superuser on the local filesystems, the C<:r>, +C<:R>, C<:w>, and C<:W> tests always return 1, and C<:x> and C<:X> return 1 +if any execute bit is set in the mode. Scripts run by the superuser +may thus need to do a stat() to determine the actual mode of the file, +or temporarily set their effective uid to something else. + +If you are using ACLs, there is a pragma called C<filetest> that may +produce more accurate results than the bare stat() mode bits. +When under the C<use filetest 'access'> the above-mentioned filetests +will test whether the permission can (not) be granted using the +access() family of system calls. Also note that the C<:x> and C<:X> may +under this pragma return true even if there are no execute permission +bits set (nor any extra execute permission ACLs). This strangeness is +due to the underlying system calls' definitions. Read the +documentation for the C<filetest> pragma for more information. + +The C<:T> and C<:B> switches work as follows. The first block or so of the +file is examined for odd characters such as strange control codes or +characters with the high bit set. If too many strange characters (>30%) +are found, it's a C<:B> file; otherwise it's a C<:T> file. Also, any file +containing null in the first block is considered a binary file. If C<:T> +or C<:B> is used on a filehandle, the current IO buffer is examined +rather than the first block. Both C<:T> and C<:B> return true on a null +file, or a file at EOF when testing a filehandle. Because you have to +read a file to do the C<:T> test, on most occasions you want to use a C<:f> +against the file first, as in C<next unless $file ~~ :f && $file ~~ :T >. + +You can test multiple features using junctions: + + if -$filename ~~ :r & :w & :x {...} + +Or pass multiple tests together in OO style: + + if $filename.TEST(:e,:x) {...} + + +=item realpath + + method Str realpath(); + +Gets the real path to the object, resolving softlinks/shortcuts, etc + +=item === operator + + method infix:<===>(Str $filename); + +Test whether the specified filename is the same file as this file. On a Unix system, +this would presumably be done by comparing inode numbers or something. + +=item new + +This is called automatically on object creation. + +multi method new(Array of Str :@PathElements); +multi method new(Str :$Type, Str :$Path, Str :$Create); +multi method new(Str :$Path); + +This last throws an error if "use portable" pragma is used. + +If the "Create" option is passed in, and the node doesn't exist in the filesystem, it +attempts to create the node; this can be used for "mkdir", "link", and similar +functionality. + +Examples: + + $fsnode = new IO::FSNode(PathElements => ['home', 'wayland']); + $fsnode = new IO::FSNode(Type => 'Unix', Path => '/home/wayland'); + $fsnode = new IO::FSNode(Path => '/home/wayland'); # portability error + +=item delete + +This deletes the FSNode from the filesystem. If the node has children, it throws an error +unless the "Recursive" option is specified. Returns the number of nodes deleted. + +=back + +=head2 IO::FSNodeACL + +This is a basic abstraction; for better control, use the operating-system specific +interfaces, over which this is a thin veneer. + +class IO::FSNodeACL { + has Str $.type; # "User", "Group", "Everyone", ??? + has Str $.id; # username or groupname; unused for $type eq "Everyone" + has %.permissions; + # Unsupported values may (or may not) throw + # UnsupportedPermission when set or read + has IO::FSNode $.owningObject; +... +} + +The permissions used in %permissions are: + +=over + +=item Readable + +Should be supported by all filesystems as an item to read from the hash for the group +"Everyone". + +=item Writeable + +Should be supported by all filesystems as an item to read from the hash for the group +"Everyone". + +=item Executeable + +Supported on most Unix systems, anyway. Windows should be able to guess when this is +read, and throw an exception if written to. + +=item Default + +An ACL of User,fred,Default sets the user "fred" to be the owner of the file. This can be +done with groups too. Work on Unix, at least. + +=back + +The $.owningObject attribute of FSNodeACL shows what the ACL is set on. On a +Windows system, this can be a parent directory, as permissions are inherited. + +=head2 IO::FileNode + + role IO::FileNode does IO::FSNode { +... + } + +=over + +=item our List multi method lines (IO $handle:) is export; + +=item our List multi lines (Str $filename); + +Returns all the lines of a file as a (lazy) List regardless of context. +See also C<slurp>. + +=item our Item multi method slurp (IO $handle: *%opts) is export; + +=item our Item multi slurp (Str $filename, *%opts); + +Slurps the entire file into a Str or Buf regardless of context. +(See also C<lines>.) Whether a Str or Buf is returned depends on +the options. + +=back + +=head2 IO::DirectoryNode + + role IO::DirectoryNode does IO::FSNode { +... + } + +=item open + + $dir.open(); + +Opens a directory for processing, if the new() method was passed the NoOpen option. +Makes the directory looks like +a list of autochomped lines, so just use ordinary IO operators after the open. + +=item rmdir FILENAME +X<rmdir> X<rd> X<directory, remove> + +=item rmdir + +Deletes the directory specified by FILENAME if that directory is +empty. If it succeeds it returns true, otherwise it returns false and +sets C<$!> (errno). If FILENAME is omitted, uses C<$_>. + +=head2 IO::LinkNode + + role IO::LinkNode does IO::FSNode { +... + } + +=item link + +=item readlink + +=item symlink + +=head2 IO::Socket::TCP + +class IO::Socket::TCP does IO::Socket does IO::Streamable { +... +} + +=over + +=item has $.RemoteHost + +=item has $.RemotePort + +=item has $.LocalHost + +=item has $.LocalPort + +=item new + + method IO::Socket::TCP new( + Str :$RemoteHost, Str :$RemotePort, + Str :$LocalHost, Str :$LocalPort, + Bool :$Blocking, + Bool :$NoOpen + ); + +The creation of the object will also open the connection, unless NoOpen is specified. + +=item open + + method open() + +If it's not an IO::Listening, it does a connect(). + +It's intended for the case where the creation of the object didn't do one. + +=item method Int read($buf is rw, Int $length) + +Does a recv(). + +=item method Int write($buf, Int $length) + +Does a send(). + +=item IO.getpeername + +=item /[get|set][host|net|proto|serv|sock].*/ + +=back + +=head2 IO::Pipe + +class IO::Pipe does IO::Streamable { +... +} + +May also do IO::Readable and IO::Writable, depending on opening method. + +=over + +=item close() + +If the file handle came from a piped open, C<close> will additionally +return false if one of the other system calls involved fails, or if the +program exits with non-zero status. (If the only problem was that the +program exited non-zero, C<$!> will be set to C<0>.) Closing a pipe +also waits for the process executing on the pipe to complete, in case you +want to look at the output of the pipe afterwards, and +implicitly puts the exit status value of that command into C<$!>. + +=item Pipe.to + + our IO method to(Str $command, *%opts) + +Opens a one-way pipe writing to $command. IO redirection for +stderr is specified with :err(IO) or :err<Str>. Other IO redirection +is done with feed operators. XXX how to specify "2>&1"? + +=item Pipe.from + + our IO method from(Str $command, *%opts) + +Opens a one-way pipe reading from $command. IO redirection for +stderr is specified with :err(IO) or :err<Str>. Other IO redirection +is done with feed operators. XXX how to specify "2>&1"? + +=item Pipe.pair + + our List of IO method pair() + +A wrapper for pipe(2), returns a pair of IO objects representing the +reader and writer ends of the pipe. + + ($r, $w) = Pipe.pair; + +=back + +=head1 Calls that operate on the default IO handle + +=over + +=item close() + +=item open() + +... + +=back + +=head1 OS-specific classes + +=head2 Unix + +=head2 IO::FSNode::Unix + +=item chown + + our Int multi chown ($uid = -1, $gid = -1, *...@files) + +Changes the owner (and group) of a list of files. The first +two elements of the list must be the numeric uid and gid, in +that order. A value of -1 in either position is interpreted by +most systems to leave that value unchanged. Returns the number +of files successfully changed. + + $count = chown $uid, $gid, ’foo’, ’bar’; + chown $uid, $gid, @filenames; + +On systems that support C<fchown>, you might pass file handles +among the files. On systems that don’t support C<fchown>, passing +file handles produces a fatal error at run time. + +Here’s an example that looks up nonnumeric uids in the passwd +file: + + $user = prompt "User: "; + $pattern = prompt "Files: "; + + ($login,$pass,$uid,$gid) = getpwnam($user) + or die "$user not in passwd file"; + + @ary = glob($pattern); # expand filenames + chown $uid, $gid, @ary; + +On most systems, you are not allowed to change the ownership of +the file unless you’re the superuser, although you should be +able to change the group to any of your secondary groups. On +insecure systems, these restrictions may be relaxed, but this +is not a portable assumption. On POSIX systems, you can detect +this condition this way: + + use POSIX qw(sysconf _PC_CHOWN_RESTRICTED); + $can_chown_giveaway = not sysconf(_PC_CHOWN_RESTRICTED); + +=item chmod LIST +X<chmod> X<permission> X<mode> + +Changes the permissions of a list of files. The first element of the +list must be the numerical mode, which should probably be an octal +number, and which definitely should I<not> be a string of octal digits: +C<0o644> is okay, C<0644> is not. Returns the number of files +successfully changed. + + $cnt = chmod 0o755, 'foo', 'bar'; + chmod 0o755, @executables; + $mode = '0644'; chmod $mode, 'foo'; # !!! sets mode to --w----r-T + $mode = '0o644'; chmod $mode, 'foo'; # this is better + $mode = 0o644; chmod $mode, 'foo'; # this is best + +=item lstat + +Returns a stat buffer. If the lstat succeeds, the stat buffer evaluates +to true, and additional file tests may be performed on the value. If +the stat fails, all subsequent tests on the stat buffer also evaluate +to false. + +=item stat + +=item IO.stat + +Returns a stat buffer. If the lstat succeeds, the stat buffer evaluates +to true, and additional file tests may be performed on the value. If +the stat fails, all subsequent tests on the stat buffer also evaluate +to false. + +=head2 IO::POSIX + +Indicates that this object can perform standard posix IO +operations. It implies IO::Readable and IO::Writeable. + +=over + +=item method IO dup() + +=item has Bool $.blocking is rw + +=item method Bool flock(:$r,:$w) + +=item method Bool funlock() + +=item ... + +=back + +=head2 IO::File::Windows + +role IO::File::Windows does IO::File { + method open(Bool :$BinaryMode) {...} +} + +=item open() + +Takes the BinaryMode option to open the file in binary mode. + +=head1 Unfiled + +=over 4 + +=item IO.ioctl + +Available only as a handle method. + +=item alarm + +=item prompt + + our Str prompt (Str $prompt) + + Should there be an IO::Interactive role? + +=item Str.readpipe + +=item sysopen + +=item IO.sysseek + +=item umask + +=back + +=head1 Removed functions + +=over + +=item IO.eof + +Gone, see IO::Endable + +=item IO.fileno + +See IO::FileDescriptor + +=item IO.name + +Changed to .path(), but we haven't gotten around to specifying this on all of them. + +The C<.name> method returns the name of the file/socket/uri the handle +was opened with, if known. Returns undef otherwise. There is no +corresponding C<name()> function. + +=item pipe + +Gone, see Pipe.pair + +=item select(both) + +Gone. (Note: for subsecond sleep, just use sleep with a fractional argument.) + +=item IO.shutdown() + +Gone, see IO::Socket.close(), $IO::Readable.isReadable, and $IO::Writeable.isWriteable + +=item socketpair + +Gone, see Socket.pair + +=item IO.sysread + +Gone, see IO::Readable.read() + +=item IO.syswrite + +Gone, see IO::Writeable.read() + +=item utime + +Gone, see %IO::FSNode.times. + +=back + =head1 Additions Please post errors and feedback to perl6-language. If you are making a general laundry list, please separate messages by topic. - - +=cut