From: Stas Bekman Date: Thu, 20 Dec 2001 17:15:09 +0000 (+0800) Subject: Re: [PATCH pod/perliol.pod] resend X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=d4165bded29b540a8716daf95e9a96ed73736060;p=p5sagit%2Fp5-mst-13.2.git Re: [PATCH pod/perliol.pod] resend Message-ID: p4raw-id: //depot/perl@13818 --- diff --git a/pod/perliol.pod b/pod/perliol.pod index 4ef52d7..cde9be5 100644 --- a/pod/perliol.pod +++ b/pod/perliol.pod @@ -1,4 +1,3 @@ - =head1 NAME perliol - C API for Perl's implementation of IO in Layers. @@ -8,7 +7,6 @@ perliol - C API for Perl's implementation of IO in Layers. /* Defining a layer ... */ #include - =head1 DESCRIPTION This document describes the behavior and implementation of the PerlIO @@ -63,7 +61,7 @@ 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 C, -a C<< &(perlio-Enext) >> "is" a C, and so to some degree +a C<< &(perlio->next) >> "is" a C, 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: @@ -92,40 +90,39 @@ same as the public C functions: char * name; Size_t size; IV kind; - IV (*Pushed)(PerlIO *f,const char *mode,SV *arg); - IV (*Popped)(PerlIO *f); + IV (*Pushed)(pTHX_ PerlIO *f,const char *mode,SV *arg); + IV (*Popped)(pTHX_ PerlIO *f); PerlIO * (*Open)(pTHX_ PerlIO_funcs *tab, AV *layers, IV n, const char *mode, int fd, int imode, int perm, PerlIO *old, int narg, SV **args); - SV * (*Getarg)(PerlIO *f); - IV (*Fileno)(PerlIO *f); + SV * (*Getarg)(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags) + IV (*Fileno)(pTHX_ PerlIO *f); + PerlIO * (*Dup)(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags) /* 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); + SSize_t (*Read)(pTHX_ PerlIO *f, void *vbuf, Size_t count); + SSize_t (*Unread)(pTHX_ PerlIO *f, const void *vbuf, Size_t count); + SSize_t (*Write)(pTHX_ PerlIO *f, const void *vbuf, Size_t count); + IV (*Seek)(pTHX_ PerlIO *f, Off_t offset, int whence); + Off_t (*Tell)(pTHX_ PerlIO *f); + IV (*Close)(pTHX_ 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); + IV (*Flush)(pTHX_ PerlIO *f); + IV (*Fill)(pTHX_ PerlIO *f); + IV (*Eof)(pTHX_ PerlIO *f); + IV (*Error)(pTHX_ PerlIO *f); + void (*Clearerr)(pTHX_ PerlIO *f); + void (*Setlinebuf)(pTHX_ 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); + STDCHAR * (*Get_base)(pTHX_ PerlIO *f); + Size_t (*Get_bufsiz)(pTHX_ PerlIO *f); + STDCHAR * (*Get_ptr)(pTHX_ PerlIO *f); + SSize_t (*Get_cnt)(pTHX_ PerlIO *f); + void (*Set_ptrcnt)(pTHX_ PerlIO *f,STDCHAR *ptr,SSize_t cnt); }; - - The first few members of the struct give a "name" for the layer, the size to C for the per-instance data, and some flags which are attributes of the class as whole (such as whether it is a buffering @@ -255,7 +252,7 @@ Reads are permitted i.e. opened "r" or "w+" (or even "a+" - ick). =item PERLIO_F_ERROR -An error has occurred (for C) +An error has occurred (for C). =item PERLIO_F_TRUNCATE @@ -325,7 +322,45 @@ to change during one "get".) =over 4 -=item IV (*Pushed)(PerlIO *f,const char *mode, SV *arg); +=item char * name; + +The name of the layer whose open() method Perl should invoke on +open(). For example if the layer is called APR, you will call: + + open $fh, ">:APR", ... + +and Perl knows that it has to invoke the PerlIOAPR_open() method +implemented by the APR layer. + +=item Size_t size; + +The size of the per-instance data structure, e.g.: + + sizeof(PerlIOAPR) + +=item IV kind; + + XXX: explain all the available flags here + +=over 4 + +=item * PERLIO_K_BUFFERED + +=item * PERLIO_K_CANCRLF + +=item * PERLIO_K_FASTGETS + +=item * PERLIO_K_MULTIARG + +Used when the layer's open() accepts more arguments than usual. The +extra arguments should come not before the C argument. When this +flag is used it's up to the layer to validate the args. + +=item * PERLIO_K_RAW + +=back + +=item IV (*Pushed)(pTHX_ PerlIO *f,const char *mode, SV *arg); The only absolutely mandatory method. Called when the layer is pushed onto the stack. The C argument may be NULL if this occurs @@ -337,7 +372,9 @@ expecting an argument it need neither save the one passed to it, nor provide C (it could perhaps C that the argument was un-expected). -=item IV (*Popped)(PerlIO *f); +Returns 0 on success. On failure returns -1 and should set errno. + +=item IV (*Popped)(pTHX_ PerlIO *f); Called when the layer is popped from the stack. A layer will normally be popped after C is called. But a layer can be popped @@ -348,6 +385,8 @@ struct. It should also C any unconsumed data that has been read and buffered from the layer below back to that layer, so that it can be re-provided to what ever is now above. +Returns 0 on success and failure. + =item PerlIO * (*Open)(...); The C method has lots of arguments because it combines the @@ -402,100 +441,141 @@ and wait to be "pushed". If a layer does provide C it should normally call the C method of next layer down (if any) and then push itself on top if that succeeds. -=item SV * (*Getarg)(PerlIO *f); +Returns C on failure. + +=item SV * (*Getarg)(pTHX_ PerlIO *f, CLONE_PARAMS *param, int flags) -Optional. If present should return an SV * representing the string argument -passed to the layer when it was pushed. e.g. ":encoding(ascii)" would -return an SvPV with value "ascii". +Optional. If present should return an SV * representing the string +argument passed to the layer when it was +pushed. e.g. ":encoding(ascii)" would return an SvPV with value +"ascii". (I and I arguments can be ignored in most +cases) -=item IV (*Fileno)(PerlIO *f); +=item IV (*Fileno)(pTHX_ PerlIO *f); Returns the Unix/Posix numeric file descriptor for the handle. Normally C (which just asks next layer down) will suffice for this. -=item SSize_t (*Read)(PerlIO *f, void *vbuf, Size_t count); +Returns -1 if the layer cannot provide such a file descriptor, or in +the case of the error. + +XXX: two possible results end up in -1, one is an error the other is +not. + +=item PerlIO * (*Dup)(pTHX_ PerlIO *f, PerlIO *o, CLONE_PARAMS *param, int flags) + +XXX: not documented + +Similar to C, returns PerlIO* on success, C on failure. + +=item SSize_t (*Read)(pTHX_ PerlIO *f, void *vbuf, Size_t count); + +Basic read operation. -Basic read operation. Returns actual bytes read, or -1 on an error. -Typically will call Fill and manipulate pointers (possibly via the API). -C may be suitable for derived classes which provide -"fast gets" methods. +Typically will call C and manipulate pointers (possibly via the +API). C may be suitable for derived classes which +provide "fast gets" methods. -=item SSize_t (*Unread)(PerlIO *f, const void *vbuf, Size_t count); +Returns actual bytes read, or -1 on an error. + +=item SSize_t (*Unread)(pTHX_ PerlIO *f, const void *vbuf, Size_t count); A superset of stdio's C. Should arrange for future reads to see the bytes in C. If there is no obviously better implementation then C provides the function by pushing a "fake" "pending" layer above the calling layer. +Returns the number of unread chars. + =item SSize_t (*Write)(PerlIO *f, const void *vbuf, Size_t count); -Basic write operation. Returns bytes written or -1 on an error. +Basic write operation. -=item IV (*Seek)(PerlIO *f, Off_t offset, int whence); +Returns bytes written or -1 on an error. + +=item IV (*Seek)(pTHX_ PerlIO *f, Off_t offset, int whence); Position the file pointer. Should normally call its own C method and then the C method of next layer down. -=item Off_t (*Tell)(PerlIO *f); +Returns 0 on success, -1 on failure. + +=item Off_t (*Tell)(pTHX_ PerlIO *f); Return the file pointer. May be based on layers cached concept of position to avoid overhead. -=item IV (*Close)(PerlIO *f); +Returns -1 on failure to get the file pointer. + +=item IV (*Close)(pTHX_ PerlIO *f); Close the stream. Should normally call C 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); +Returns 0 on success, -1 on failure. + +=item IV (*Flush)(pTHX_ PerlIO *f); Should make stream's state consistent with layers below. That is, any buffered write data should be written, and file position of lower layers adjusted for data read from below but not actually consumed. (Should perhaps C such data to the lower layer.) -=item IV (*Fill)(PerlIO *f); +Returns 0 on success, -1 on failure. + +=item IV (*Fill)(pTHX_ PerlIO *f); + +The buffer for this layer should be filled (for read) from layer +below. When you "subclass" PerlIOBuf layer, you want to use its +I<_read> method and to supply your own fill method, which fills the +PerlIOBuf's buffer. -The buffer for this layer should be filled (for read) from layer below. +Returns 0 on success, -1 on failure. -=item IV (*Eof)(PerlIO *f); +=item IV (*Eof)(pTHX_ PerlIO *f); Return end-of-file indicator. C is normally sufficient. -=item IV (*Error)(PerlIO *f); +Returns 0 on end-of-file, 1 if not end-of-file, -1 on error. + +=item IV (*Error)(pTHX_ PerlIO *f); Return error indicator. C is normally sufficient. -=item void (*Clearerr)(PerlIO *f); +Returns 1 if there is an error (usually when C is set, +0 otherwise. + +=item void (*Clearerr)(pTHX_ PerlIO *f); Clear end-of-file and error indicators. Should call C to set the C flags, which may suffice. -=item void (*Setlinebuf)(PerlIO *f); +=item void (*Setlinebuf)(pTHX_ PerlIO *f); Mark the stream as line buffered. C sets the PERLIO_F_LINEBUF flag and is normally sufficient. -=item STDCHAR * (*Get_base)(PerlIO *f); +=item STDCHAR * (*Get_base)(pTHX_ PerlIO *f); Allocate (if not already done so) the read buffer for this layer and -return pointer to it. +return pointer to it. Return NULL on failure. -=item Size_t (*Get_bufsiz)(PerlIO *f); +=item Size_t (*Get_bufsiz)(pTHX_ PerlIO *f); Return the number of bytes that last C put in the buffer. -=item STDCHAR * (*Get_ptr)(PerlIO *f); +=item STDCHAR * (*Get_ptr)(pTHX_ PerlIO *f); Return the current read pointer relative to this layer's buffer. -=item SSize_t (*Get_cnt)(PerlIO *f); +=item SSize_t (*Get_cnt)(pTHX_ 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); +=item void (*Set_ptrcnt)(pTHX_ PerlIO *f,STDCHAR *ptr,SSize_t cnt); Adjust the read pointer and count of bytes to match C and/or C. The application (or layer above) must ensure they are consistent. @@ -625,6 +705,68 @@ implementation is being investigated. =back +=head1 TODO + +Things that need to be done to improve this document. + +=over + +=item * + +Explain how to make a valid fh without going through open()(i.e. apply +a layer). For example if the file is not opened through perl, but we +want to get back a fh, like it was opened by Perl. + +How PerlIO_apply_layera fits in, where its docs, was it made public? + +Currently the example could be something like this: + + PerlIO *foo_to_PerlIO(pTHX_ char *mode, ...) + { + char *mode; /* "w", "r", etc */ + const char *layers = ":APR"; /* the layer name */ + PerlIO *f = PerlIO_allocate(aTHX); + if (!f) { + return NULL; + } + + PerlIO_apply_layers(aTHX_ f, mode, layers); + + if (f) { + PerlIOAPR *st = PerlIOSelf(f, PerlIOAPR); + /* fill in the st struct, as in _open() */ + st->file = file; + PerlIOBase(f)->flags |= PERLIO_F_OPEN; + + return f; + } + return NULL; + } + +=item * + +fix/add the documentation in places marked as XXX. + +=item * + +The handling of errors by the layer is not specified. e.g. when $! +should be set explicitly, when the error handling should be just +delegated to the top layer. + +Probably give some hints on using SETERRNO() or pointers to where they +can be found. + +=item * + +I think it would help to give some concrete examples to make it easier +to understand the API. Of course I agree that the API has to be +concise, but since there is no second document that is more of a +guide, I think that it'd make it easier to start with the doc which is +an API, but has examples in it in places where things are unclear, to +a person who is not a PerlIO guru (yet). + +=back + =cut