1*0Sstevel@tonic-gatepackage PerlIO::via; 2*0Sstevel@tonic-gateour $VERSION = '0.02'; 3*0Sstevel@tonic-gateuse XSLoader (); 4*0Sstevel@tonic-gateXSLoader::load 'PerlIO::via'; 5*0Sstevel@tonic-gate1; 6*0Sstevel@tonic-gate__END__ 7*0Sstevel@tonic-gate 8*0Sstevel@tonic-gate=head1 NAME 9*0Sstevel@tonic-gate 10*0Sstevel@tonic-gatePerlIO::via - Helper class for PerlIO layers implemented in perl 11*0Sstevel@tonic-gate 12*0Sstevel@tonic-gate=head1 SYNOPSIS 13*0Sstevel@tonic-gate 14*0Sstevel@tonic-gate use PerlIO::via::Layer; 15*0Sstevel@tonic-gate open($fh,"<:via(Layer)",...); 16*0Sstevel@tonic-gate 17*0Sstevel@tonic-gate use Some::Other::Package; 18*0Sstevel@tonic-gate open($fh,">:via(Some::Other::Package)",...); 19*0Sstevel@tonic-gate 20*0Sstevel@tonic-gate=head1 DESCRIPTION 21*0Sstevel@tonic-gate 22*0Sstevel@tonic-gateThe PerlIO::via module allows you to develop PerlIO layers in Perl, without 23*0Sstevel@tonic-gatehaving to go into the nitty gritty of programming C with XS as the interface 24*0Sstevel@tonic-gateto Perl. 25*0Sstevel@tonic-gate 26*0Sstevel@tonic-gateOne example module, L<PerlIO::via::QuotedPrint>, is included with Perl 27*0Sstevel@tonic-gate5.8.0, and more example modules are available from CPAN, such as 28*0Sstevel@tonic-gateL<PerlIO::via::StripHTML> and L<PerlIO::via::Base64>. The 29*0Sstevel@tonic-gatePerlIO::via::StripHTML module for instance, allows you to say: 30*0Sstevel@tonic-gate 31*0Sstevel@tonic-gate use PerlIO::via::StripHTML; 32*0Sstevel@tonic-gate open( my $fh, "<:via(StripHTML)", "index.html" ); 33*0Sstevel@tonic-gate my @line = <$fh>; 34*0Sstevel@tonic-gate 35*0Sstevel@tonic-gateto obtain the text of an HTML-file in an array with all the HTML-tags 36*0Sstevel@tonic-gateautomagically removed. 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gatePlease note that if the layer is created in the PerlIO::via:: namespace, it 39*0Sstevel@tonic-gatedoes B<not> have to be fully qualified. The PerlIO::via module will prefix 40*0Sstevel@tonic-gatethe PerlIO::via:: namespace if the specified modulename does not exist as a 41*0Sstevel@tonic-gatefully qualified module name. 42*0Sstevel@tonic-gate 43*0Sstevel@tonic-gate=head1 EXPECTED METHODS 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gateTo create a Perl module that implements a PerlIO layer in Perl (as opposed to 46*0Sstevel@tonic-gatein C using XS as the interface to Perl), you need to supply some of the 47*0Sstevel@tonic-gatefollowing subroutines. It is recommended to create these Perl modules in the 48*0Sstevel@tonic-gatePerlIO::via:: namespace, so that they can easily be located on CPAN and use 49*0Sstevel@tonic-gatethe default namespace feature of the PerlIO::via module itself. 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gatePlease note that this is an area of recent development in Perl and that the 52*0Sstevel@tonic-gateinterface described here is therefore still subject to change (and hopefully 53*0Sstevel@tonic-gatewill have better documentation and more examples). 54*0Sstevel@tonic-gate 55*0Sstevel@tonic-gateIn the method descriptions below I<$fh> will be 56*0Sstevel@tonic-gatea reference to a glob which can be treated as a perl file handle. 57*0Sstevel@tonic-gateIt refers to the layer below. I<$fh> is not passed if the layer 58*0Sstevel@tonic-gateis at the bottom of the stack, for this reason and to maintain 59*0Sstevel@tonic-gatesome level of "compatibility" with TIEHANDLE classes it is passed last. 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gate=over 4 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate=item $class->PUSHED([$mode[,$fh]]) 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gateShould return an object or the class, or -1 on failure. (Compare 66*0Sstevel@tonic-gateTIEHANDLE.) The arguments are an optional mode string ("r", "w", 67*0Sstevel@tonic-gate"w+", ...) and a filehandle for the PerlIO layer below. Mandatory. 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gateWhen layer is pushed as part of an C<open> call, C<PUSHED> will be called 70*0Sstevel@tonic-gateI<before> the actual open occurs whether than be via C<OPEN>, C<SYSOPEN>, 71*0Sstevel@tonic-gateC<FDOPEN> or by letting lower layer do the open. 72*0Sstevel@tonic-gate 73*0Sstevel@tonic-gate=item $obj->POPPED([$fh]) 74*0Sstevel@tonic-gate 75*0Sstevel@tonic-gateOptional - layer is about to be removed. 76*0Sstevel@tonic-gate 77*0Sstevel@tonic-gate=item $obj->UTF8($bellowFlag,[$fh]) 78*0Sstevel@tonic-gate 79*0Sstevel@tonic-gateOptional - if present it will be called immediately after PUSHED has 80*0Sstevel@tonic-gatereturned. It should return true value if the layer expects data to be 81*0Sstevel@tonic-gateUTF-8 encoded. If it returns true result is as if caller had done 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate ":via(YourClass):utf8" 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gateIf not present of it it returns false, then stream is left with 86*0Sstevel@tonic-gateflag clear. 87*0Sstevel@tonic-gateThe I<$bellowFlag> argument will be true if there is a layer below 88*0Sstevel@tonic-gateand that layer was expecting UTF-8. 89*0Sstevel@tonic-gate 90*0Sstevel@tonic-gate 91*0Sstevel@tonic-gate=item $obj->OPEN($path,$mode[,$fh]) 92*0Sstevel@tonic-gate 93*0Sstevel@tonic-gateOptional - if not present lower layer does open. 94*0Sstevel@tonic-gateIf present called for normal opens after layer is pushed. 95*0Sstevel@tonic-gateThis function is subject to change as there is no easy way 96*0Sstevel@tonic-gateto get lower layer to do open and then regain control. 97*0Sstevel@tonic-gate 98*0Sstevel@tonic-gate=item $obj->BINMODE([,$fh]) 99*0Sstevel@tonic-gate 100*0Sstevel@tonic-gateOptional - if not available layer is popped on binmode($fh) or when C<:raw> 101*0Sstevel@tonic-gateis pushed. If present it should return 0 on success -1 on error and undef 102*0Sstevel@tonic-gateto pop the layer. 103*0Sstevel@tonic-gate 104*0Sstevel@tonic-gate=item $obj->FDOPEN($fd[,$fh]) 105*0Sstevel@tonic-gate 106*0Sstevel@tonic-gateOptional - if not present lower layer does open. 107*0Sstevel@tonic-gateIf present called for opens which pass a numeric file 108*0Sstevel@tonic-gatedescriptor after layer is pushed. 109*0Sstevel@tonic-gateThis function is subject to change as there is no easy way 110*0Sstevel@tonic-gateto get lower layer to do open and then regain control. 111*0Sstevel@tonic-gate 112*0Sstevel@tonic-gate=item $obj->SYSOPEN($path,$imode,$perm,[,$fh]) 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gateOptional - if not present lower layer does open. 115*0Sstevel@tonic-gateIf present called for sysopen style opens which pass a numeric mode 116*0Sstevel@tonic-gateand permissions after layer is pushed. 117*0Sstevel@tonic-gateThis function is subject to change as there is no easy way 118*0Sstevel@tonic-gateto get lower layer to do open and then regain control. 119*0Sstevel@tonic-gate 120*0Sstevel@tonic-gate=item $obj->FILENO($fh) 121*0Sstevel@tonic-gate 122*0Sstevel@tonic-gateReturns a numeric value for Unix-like file descriptor. Return -1 if 123*0Sstevel@tonic-gatethere isn't one. Optional. Default is fileno($fh). 124*0Sstevel@tonic-gate 125*0Sstevel@tonic-gate=item $obj->READ($buffer,$len,$fh) 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gateReturns the number of octets placed in $buffer (must be less than or 128*0Sstevel@tonic-gateequal to $len). Optional. Default is to use FILL instead. 129*0Sstevel@tonic-gate 130*0Sstevel@tonic-gate=item $obj->WRITE($buffer,$fh) 131*0Sstevel@tonic-gate 132*0Sstevel@tonic-gateReturns the number of octets from buffer that have been successfully written. 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate=item $obj->FILL($fh) 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gateShould return a string to be placed in the buffer. Optional. If not 137*0Sstevel@tonic-gateprovided must provide READ or reject handles open for reading in 138*0Sstevel@tonic-gatePUSHED. 139*0Sstevel@tonic-gate 140*0Sstevel@tonic-gate=item $obj->CLOSE($fh) 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gateShould return 0 on success, -1 on error. 143*0Sstevel@tonic-gateOptional. 144*0Sstevel@tonic-gate 145*0Sstevel@tonic-gate=item $obj->SEEK($posn,$whence,$fh) 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gateShould return 0 on success, -1 on error. 148*0Sstevel@tonic-gateOptional. Default is to fail, but that is likely to be changed 149*0Sstevel@tonic-gatein future. 150*0Sstevel@tonic-gate 151*0Sstevel@tonic-gate=item $obj->TELL($fh) 152*0Sstevel@tonic-gate 153*0Sstevel@tonic-gateReturns file postion. 154*0Sstevel@tonic-gateOptional. Default to be determined. 155*0Sstevel@tonic-gate 156*0Sstevel@tonic-gate=item $obj->UNREAD($buffer,$fh) 157*0Sstevel@tonic-gate 158*0Sstevel@tonic-gateReturns the number of octets from buffer that have been successfully 159*0Sstevel@tonic-gatesaved to be returned on future FILL/READ calls. Optional. Default is 160*0Sstevel@tonic-gateto push data into a temporary layer above this one. 161*0Sstevel@tonic-gate 162*0Sstevel@tonic-gate=item $obj->FLUSH($fh) 163*0Sstevel@tonic-gate 164*0Sstevel@tonic-gateFlush any buffered write data. May possibly be called on readable 165*0Sstevel@tonic-gatehandles too. Should return 0 on success, -1 on error. 166*0Sstevel@tonic-gate 167*0Sstevel@tonic-gate=item $obj->SETLINEBUF($fh) 168*0Sstevel@tonic-gate 169*0Sstevel@tonic-gateOptional. No return. 170*0Sstevel@tonic-gate 171*0Sstevel@tonic-gate=item $obj->CLEARERR($fh) 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gateOptional. No return. 174*0Sstevel@tonic-gate 175*0Sstevel@tonic-gate=item $obj->ERROR($fh) 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gateOptional. Returns error state. Default is no error until a mechanism 178*0Sstevel@tonic-gateto signal error (die?) is worked out. 179*0Sstevel@tonic-gate 180*0Sstevel@tonic-gate=item $obj->EOF($fh) 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gateOptional. Returns end-of-file state. Default is function of return 183*0Sstevel@tonic-gatevalue of FILL or READ. 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gate=back 186*0Sstevel@tonic-gate 187*0Sstevel@tonic-gate=head1 EXAMPLES 188*0Sstevel@tonic-gate 189*0Sstevel@tonic-gateCheck the PerlIO::via:: namespace on CPAN for examples of PerlIO layers 190*0Sstevel@tonic-gateimplemented in Perl. To give you an idea how simple the implementation of 191*0Sstevel@tonic-gatea PerlIO layer can look, as simple example is included here. 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate=head2 Example - a Hexadecimal Handle 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gateGiven the following module, PerlIO::via::Hex : 196*0Sstevel@tonic-gate 197*0Sstevel@tonic-gate package PerlIO::via::Hex; 198*0Sstevel@tonic-gate 199*0Sstevel@tonic-gate sub PUSHED 200*0Sstevel@tonic-gate { 201*0Sstevel@tonic-gate my ($class,$mode,$fh) = @_; 202*0Sstevel@tonic-gate # When writing we buffer the data 203*0Sstevel@tonic-gate my $buf = ''; 204*0Sstevel@tonic-gate return bless \$buf,$class; 205*0Sstevel@tonic-gate } 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate sub FILL 208*0Sstevel@tonic-gate { 209*0Sstevel@tonic-gate my ($obj,$fh) = @_; 210*0Sstevel@tonic-gate my $line = <$fh>; 211*0Sstevel@tonic-gate return (defined $line) ? pack("H*", $line) : undef; 212*0Sstevel@tonic-gate } 213*0Sstevel@tonic-gate 214*0Sstevel@tonic-gate sub WRITE 215*0Sstevel@tonic-gate { 216*0Sstevel@tonic-gate my ($obj,$buf,$fh) = @_; 217*0Sstevel@tonic-gate $$obj .= unpack("H*", $buf); 218*0Sstevel@tonic-gate return length($buf); 219*0Sstevel@tonic-gate } 220*0Sstevel@tonic-gate 221*0Sstevel@tonic-gate sub FLUSH 222*0Sstevel@tonic-gate { 223*0Sstevel@tonic-gate my ($obj,$fh) = @_; 224*0Sstevel@tonic-gate print $fh $$obj or return -1; 225*0Sstevel@tonic-gate $$obj = ''; 226*0Sstevel@tonic-gate return 0; 227*0Sstevel@tonic-gate } 228*0Sstevel@tonic-gate 229*0Sstevel@tonic-gate 1; 230*0Sstevel@tonic-gate 231*0Sstevel@tonic-gatethe following code opens up an output handle that will convert any 232*0Sstevel@tonic-gateoutput to hexadecimal dump of the output bytes: for example "A" will 233*0Sstevel@tonic-gatebe converted to "41" (on ASCII-based machines, on EBCDIC platforms 234*0Sstevel@tonic-gatethe "A" will become "c1") 235*0Sstevel@tonic-gate 236*0Sstevel@tonic-gate use PerlIO::via::Hex; 237*0Sstevel@tonic-gate open(my $fh, ">:via(Hex)", "foo.hex"); 238*0Sstevel@tonic-gate 239*0Sstevel@tonic-gateand the following code will read the hexdump in and convert it 240*0Sstevel@tonic-gateon the fly back into bytes: 241*0Sstevel@tonic-gate 242*0Sstevel@tonic-gate open(my $fh, "<:via(Hex)", "foo.hex"); 243*0Sstevel@tonic-gate 244*0Sstevel@tonic-gate=cut 245