diff options
author | Nick Ing-Simmons <nik@tiuk.ti.com> | 2001-01-28 19:22:40 +0000 |
---|---|---|
committer | Nick Ing-Simmons <nik@tiuk.ti.com> | 2001-01-28 19:22:40 +0000 |
commit | 50b80e251bdb7e866faeb20ccfeb18b474ffc6cb (patch) | |
tree | 610c0994ea6a9a5934c7e618ddae39b465ef4695 /pod/perliol.pod | |
parent | 2d21c56fa464c047967b23958ffb68fcbd02aff4 (diff) | |
download | perl-50b80e251bdb7e866faeb20ccfeb18b474ffc6cb.tar.gz |
PerlIO documentation. Proofing and sub-editing requested.
p4raw-id: //depot/perlio@8581
Diffstat (limited to 'pod/perliol.pod')
-rw-r--r-- | pod/perliol.pod | 513 |
1 files changed, 513 insertions, 0 deletions
diff --git a/pod/perliol.pod b/pod/perliol.pod new file mode 100644 index 0000000000..6169d43949 --- /dev/null +++ b/pod/perliol.pod @@ -0,0 +1,513 @@ + +=head1 NAME + +perliol - C API for Perl's implementation of IO in Layers. + +=head1 SYNOPSIS + + /* Defining a layer ... */ + #include <perliol.h> + + +=head1 DESCRIPTION + +This document describes the behavior and implementation of the PerlIO abstraction +described in L<perlapio> when C<USE_PERLIO> is defined (and C<USE_SFIO> is not). + +=head2 History and Background + +The PerlIO abstraction was introduced in perl5.003_02 but languished as just +an abstraction until perl5.7.0. However during that time a number of perl extenstions +switch to using it, so the API is mostly fixed to maintain (source) compatibility. + +The aim of the implementation is to provide the PerlIO API in a flexible and +platform neutral manner. It is also a trial of an "Object Oriented C, with vtables" +approach which may be applied to perl6. + +=head2 Layers vs Disciplines + +Initial discussion of the ability to modify IO streams behaviour used the term +"discipline" for the entities which were added. This came (I believe) from the use +of the term in "sfio", which in turn borowed it from "line disciplines" on Unix +terminals. However, this document (and the C code) uses the term "layer". +This is I hope a natural term given the implementation, and should avoid conotations +that are inherent in earlier uses of "discipline" for things which are rather different. + +=head2 Data Structures + +The basic data structure is a PerlIOl: + + typedef struct _PerlIO PerlIOl; + typedef struct _PerlIO_funcs PerlIO_funcs; + typedef PerlIOl *PerlIO; + + struct _PerlIO + { + PerlIOl * next; /* Lower layer */ + PerlIO_funcs * tab; /* Functions for this layer */ + IV flags; /* Various flags for state */ + }; + +A PerlIOl * is a pointer to to the struct, and the I<application> level PerlIO * +is a pointer to a PerlIOl * - i.e. a pointer to a pointer to the struct. +This allows the application level PerlIO * to remain constant while the actual +PerlIOl * underneath changes. (Compare perl's SV * which remains constant +while its sv_any field changes as the scalar's type changes.) +An IO stream is then in general represented as a pointer to this linked-list +of "layers". + +It should be noted that because of the double indirection in a PerlIO *, +a &(perlio->next) "is" a PerlIO *, and so to some degree at least +one layer can use the "standard" API on the next layer down. + +A "layer" is composed of two parts: + +=over 4 + +=item 1. The functions and attributes of the "layer class". + +=item 2. The per-instance data for a particular handle. + +=back + +=head2 Functions and Attributes + +The functions and attributes are accessed via the "tab" (for table) member of +PerlIOl. The functions (methods of the layer "class") are fixed, and are defined by the +PerlIO_funcs type. They are broadly the same as the public PerlIO_xxxxx functions: + + struct _PerlIO_funcs + { + char * name; + Size_t size; + IV kind; + IV (*Fileno)(PerlIO *f); + PerlIO * (*Fdopen)(PerlIO_funcs *tab, int fd, const char *mode); + PerlIO * (*Open)(PerlIO_funcs *tab, const char *path, const char *mode); + int (*Reopen)(const char *path, const char *mode, PerlIO *f); + IV (*Pushed)(PerlIO *f,const char *mode,const char *arg,STRLEN len); + IV (*Popped)(PerlIO *f); + /* Unix-like functions - cf sfio line disciplines */ + SSize_t (*Read)(PerlIO *f, void *vbuf, Size_t count); + SSize_t (*Unread)(PerlIO *f, const void *vbuf, Size_t count); + SSize_t (*Write)(PerlIO *f, const void *vbuf, Size_t count); + IV (*Seek)(PerlIO *f, Off_t offset, int whence); + Off_t (*Tell)(PerlIO *f); + IV (*Close)(PerlIO *f); + /* Stdio-like buffered IO functions */ + IV (*Flush)(PerlIO *f); + IV (*Fill)(PerlIO *f); + IV (*Eof)(PerlIO *f); + IV (*Error)(PerlIO *f); + void (*Clearerr)(PerlIO *f); + void (*Setlinebuf)(PerlIO *f); + /* Perl's snooping functions */ + STDCHAR * (*Get_base)(PerlIO *f); + Size_t (*Get_bufsiz)(PerlIO *f); + STDCHAR * (*Get_ptr)(PerlIO *f); + SSize_t (*Get_cnt)(PerlIO *f); + void (*Set_ptrcnt)(PerlIO *f,STDCHAR *ptr,SSize_t cnt); + }; + +The first few members of the struct give a "name" for the layer, the size to C<malloc> +for the per-instance data, and some flags which are attributes of the class as whole +(such as whether it is a buffering layer), then follow the functions which fall into +four basic groups: + +=over 4 + +=item 1. Opening and setup functions + +=item 2. Basic IO operations + +=item 3. Stdio class buffering options. + +=item 4. Functions to support Perl's traditional "fast" access to the buffer. + +=back + +A layer does not have to implement all the functions, but the whole table has +to be present. Unimplemented slots can be NULL (which will will result in an error +when called) or can be filled in with stubs to "inherit" behaviour from +a "base class". This "inheritance" is fixed for all instances of the layer, +but as the layer chooses which stubs to populate the table, limited +"multiple inheritance" is possible. + +=head2 Per-instance Data + +The per-instance data are held in memory beyond the basic PerlIOl struct, +by making a PerlIOl the first member of the layer's struct thus: + + typedef struct + { + struct _PerlIO base; /* Base "class" info */ + STDCHAR * buf; /* Start of buffer */ + STDCHAR * end; /* End of valid part of buffer */ + STDCHAR * ptr; /* Current position in buffer */ + Off_t posn; /* Offset of buf into the file */ + Size_t bufsiz; /* Real size of buffer */ + IV oneword; /* Emergency buffer */ + } PerlIOBuf; + +In this way (as for perl's scalars) a pointer to a PerlIOBuf can be treated +as a pointer to a PerlIOl. + +=head2 Layers in action. + + table perlio unix + | | + +-----------+ +----------+ +--------+ + PerlIO ->| |--->| next |--->| NULL | + +-----------+ +----------+ +--------+ + | | | buffer | | fd | + +-----------+ | | +--------+ + | | +----------+ + + +The above attempts to show how the layer scheme works in a simple case. +The applications PerlIO * points to an entry in the table(s) representing open +(allocated) handles. For example the first three slots in the table correspond +to C<stdin>,C<stdout> and C<stderr>. The table in turn points to the current +"top" layer for the handle - in this case an instance of the generic buffering +layer "perlio". That layer in turn points to the next layer down - in this +case the lowlevel "unix" layer. + +The above is roughly equivalent to a "stdio" buffered stream, but with much more +flexibility: + +=over 4 + +=item * + +If Unix level read/write/lseek is not appropriate for (say) sockets then +the "unix" layer can be replaced (at open time or even dynamically) with a +"socket" layer. + +=item * + +Different handles can have different buffering schemes. The "top" layer +could be the "mmap" layer if reading disk files was quicker using C<mmap> +than C<read>. An "unbuffered" stream can be implemented simply by +not having a buffer layer. + +=item * + +Extra layers can be inserted to process the data as it flows through. +This was the driving need for including the scheme in perkl5.70+ - we needed a mechanism +to allow data to be translated bewteen perl's internal encoding (conceptually +at least Unicode as UTF-8), and the "native" format used by the system. +This is provided by the ":encoding(xxxx)" layer which typically sits above +the buffering layer. + +=item * + +A layer can be added that does "\n" to CRLF translation. This layer can be used +on any platform, not just those that normally do such things. + +=back + +=head2 Per-instance flag bits + +The generic flag bits are a hybrid of O_XXXXX style flags deduced from +the mode string passed to PerlIO_open() and state bits for typical buffer +layers. + +=over4 + +=item PERLIO_F_EOF + +End of file. + +=item PERLIO_F_CANWRITE + +Writes are permited i.e. opened as "w" or "r+" or "a". etc. + +=item PERLIO_F_CANREAD + +Reads are permited i.e. opened "r" or "w+" (or even "a+" - ick). + +=item PERLIO_F_ERROR + +An error has occured (for PerlIO_error()) + +=item PERLIO_F_TRUNCATE + +Truncate file suggested by open mode. + +=item PERLIO_F_APPEND + +All writes should be appends. + +=item PERLIO_F_CRLF + +Layer is performing Win32-like "\n" => CR,LF for output and CR,LF => "\n" for +input. Normally the provided "crlf" layer is only layer than need bother about +this. PerlIO_binmode() will mess with this flag rather than add/remove layers +if the PERLIO_K_CANCRLF bit is set for the layers class. + +=item PERLIO_F_UTF8 + +Data for this written to this layer should be UTF-8 encoded, data provided +by this layer should be considered UTF-8 encoded. Can be set on any layer +by ":utf8" dummy layer. Also set on ":encoding" layer. + +=item PERLIO_F_UNBUF + +Layer is unbuffered - i.e. write to next layer down should occur for +each write to this layer. + +=item PERLIO_F_WRBUF + +The buffer for this layer currently holds data written to it but not sent +to next layer. + +=item PERLIO_F_RDBUF + +The buffer for this layer currently holds unconsumed data read from +layer below. + +=item PERLIO_F_LINEBUF + +Layer is line buffered. Write data should be passed to next layer down whenever a +"\n" is seen. Any data beyond the "\n" should then be processed. + +=item PERLIO_F_TEMP + +File has been unlink()ed, or should be deleted on close(). + +=item PERLIO_F_OPEN + +Handle is open. + +=item PERLIO_F_FASTGETS + +This instance of this layer supports the "fast gets" interface. +Normally set based on PERLIO_K_FASTGETS for the class and by the +existance of the function(s) in the table. However a class that +normally provides that interface may need to avoid it on a +particular instance. The "pending" layer needs to do this when +it is pushed above an layer which does not support the interface. +(Perls sv_gets() does not expect the steams fast gets behaviour +to change during one "get".) + +=back + +=head2 Methods in Detail + +=over 4 + +=item IV (*Fileno)(PerlIO *f); + +Returns the Unix/Posix numeric file decriptor for the handle. +Normally PerlIOBase_fileno() (which just asks next layer down) will suffice for this. + +=item PerlIO * (*Fdopen)(PerlIO_funcs *tab, int fd, const char *mode); + +Should (perhaps indirectly) call PerlIO_allocate() to allocate a slot +in the table and associate it with the given numeric file descriptor, +which will be open in an manner compatible with the supplied mode string. + +=item PerlIO * (*Open)(PerlIO_funcs *tab, const char *path, const char *mode); + +Should attempt to open the given path and if that succeeds then (perhaps indirectly) +call PerlIO_allocate() to allocate a slot in the table and associate it with the +layers information for the opened file. + +=item int (*Reopen)(const char *path, const char *mode, PerlIO *f); + +Re-open the supplied PerlIO * to connect it to C<path> in C<mode>. Returns as success flag. +Perl does not use this and L<perlapio> marks it as subject to change. + +=item IV (*Pushed)(PerlIO *f,const char *mode,const char *arg,STRLEN len); + +Called when the layer is pushed onto the stack. The C<mode> argument may be NULL if this +occurs post-open. The C<arg> and C<len> will be present if an argument string was +passed. In most cases this should call PerlIOBase_pushed() to conver C<mode> into +the appropriate PERLIO_F_XXXXX flags in addition to any actions the layer itself takes. + +=item IV (*Popped)(PerlIO *f); + +Called when the layer is popped from the stack. A layer will normally be popped after +Close() is called. But a layer can be popped without being closed if the program +is dynamically managing layers on the stream. In such cases Popped() should free +any resources (buffers, translation tables, ...) not held directly in the layer's +struct. + +=item SSize_t (*Read)(PerlIO *f, void *vbuf, Size_t count); + +Basic read operation. Returns actual bytes read, or -1 on an error. +Typically will call Fill and manipulate pointers (possibly via the API). +PerlIOBuf_read() may be suitable for derived classes which provide "fast gets" methods. + +=item SSize_t (*Unread)(PerlIO *f, const void *vbuf, Size_t count); + +A superset of stdio's ungetc(). Should arrange for future reads to see the bytes in C<vbuf>. +If there is no obviously better implementation then PerlIOBase_unread() provides +the function by pushing a "fake" "pending" layer above the calling layer. + +=item SSize_t (*Write)(PerlIO *f, const void *vbuf, Size_t count); + +Basic write operation. Returns bytes written or -1 on an error. + +=item IV (*Seek)(PerlIO *f, Off_t offset, int whence); + +Position the file pointer. Should normally call its own Flush method and +then the Seek method of next layer down. + +=item Off_t (*Tell)(PerlIO *f); + +Return the file pointer. May be based on layers cached concept of position to +avoid overhead. + +=item IV (*Close)(PerlIO *f); + +Close the stream. Should normally call PerlIOBase_close() to flush itself +and Close layers below and then deallocate any data structures (buffers, translation +tables, ...) not held directly in the data structure. + +=item IV (*Flush)(PerlIO *f); + +Should make streams state consistent with layers below. That is any +buffered write data should be written, and file position of lower layer +adjusted for data read fron below but not actually consumed. + +=item IV (*Fill)(PerlIO *f); + +The buffer for this layer should be filled (for read) from layer below. + +=item IV (*Eof)(PerlIO *f); + +Return end-of-file indicator. PerlIOBase_eof() is normally sufficient. + +=item IV (*Error)(PerlIO *f); + +Return error indicator. PerlIOBase_error() is normally sufficient. + +=item void (*Clearerr)(PerlIO *f); + +Clear end-of-file and error indicators. Should call PerlIOBase_clearerr() +to set the PERLIO_F_XXXXX flags, which may suffice. + +=item void (*Setlinebuf)(PerlIO *f); + +Mark the stream as line buffered. + +=item STDCHAR * (*Get_base)(PerlIO *f); + +Allocate (if not already done so) the read buffer for this layer and +return pointer to it. + +=item Size_t (*Get_bufsiz)(PerlIO *f); + +Return the number of bytes that last Fill() put in the buffer. + +=item STDCHAR * (*Get_ptr)(PerlIO *f); + +Return the current read pointer relative to this layers buffer. + +=item SSize_t (*Get_cnt)(PerlIO *f); + +Return the number of bytes left to be read in the current buffer. + +=item void (*Set_ptrcnt)(PerlIO *f,STDCHAR *ptr,SSize_t cnt); + +Adjust the read pointer and count of bytes to match C<ptr> and/or C<cnt>. +The application (or layer above) must ensure they are consistent. +(Checking is allowed by the paranoid.) + +=back + + +=head2 Core Layers + +The file C<perlio.c> provides the following layers: + +=over 4 + +=item "unix" + +A basic non-buffered layer which calls Unix/POSIX read(), write(), lseek(), close(). +No buffering. Even on platforms that distinguish between O_TEXT and O_BINARY +this layer is always O_BINARY. + +=item "perlio" + +A very complete generic buffering layer which provides the whole of PerlIO API. +It is also intended to be used as a "base class" for other layers. (For example +its Read() method is implemented in terms of the Get_cnt()/Get_ptr()/Set_ptrcnt() +methods). + +"perlio" over "unix" provides a complete replacement for stdio as seen via PerlIO API. +This is the default for USE_PERLIO when system's stdio does not permit perl's +"fast gets" access, and which do not distinguish between O_TEXT and O_BINARY. + +=item "stdio" + +A layer which provides the PerlIO API via the layer scheme, but implements it by calling +system's stdio. This is (currently) the default if system's stdio provides sufficient +access to allow perl's "fast gets" access and which do not distinguish between O_TEXT and +O_BINARY. + +=item "crlf" + +A layer derived using "perlio" as a base class. It provides Win32-like "\n" to CR,LF +translation. Can either be applied above "perlio" or serve as the buffer layer itself. +"crlf" over "unix" is the default if system distinguishes between O_TEXT and O_BINARY +opens. (At some point "unix" will be replaced by a "native" Win32 IO layer on that +platform, as Win32's read/write layer has various drawbacks.) +The "crlf" layer is a reasonable model for a layer which transforms data in some way. + +=item "mmap" + +If Configure detects C<mmap()> functions this layer is provided (with "perlio" as a +"base") which does "read" operations by mmap()ing the file. Performance improvement +is marginal on modern systems, so it is mainly there as a proof of concept. +It is likely to be unbundled from the core at some point. +The "mmap" layer is a reasonable model for a minimalist "derived" layer. + +=item "pending" + +An "internal" derivative of "perlio" which can be used to provide Unread() function +for layers which have no buffer or cannot be bothered. +(Basically this layer's Fill() pops itself off the stack and so resumes reading +from layer below.) + +=item "raw" + +A dummy layer which never exists on the layer stack. Instead when "pushed" it +actually pops the stack!, removing itself, and any other layers until it reaches +a layer with the class PERLIO_K_RAW bit set. + +=item "utf8" + +Another dummy layer. When pushed it pops itself and sets the PERLIO_F_UTF8 flag +on the layer which was (and now is once more) the top of the stack. + +=back + +In addition C<perlio.c> also provides a number of PerlIOBase_xxxx() functions +which are intended to be used in the table slots of classes which do not need +to do anything special for a particular method. + +=head2 Extension Layers + +Layers can made available by extension modules. + +=over 4 + +=item "encoding" + + use Encoding; + +makes this layer available. It is an example of a layer which takes an argument. +as it is called as: + + open($fh,"<:encoding(iso-8859-7)",$pathname) + +=back + + +=cut + + + |