内容

名称

PerlIO::via - Perl 中实现的 PerlIO 层的辅助类

概要

use PerlIO::via::Layer;
open($fh,"<:via(Layer)",...);

use Some::Other::Package;
open($fh,">:via(Some::Other::Package)",...);

描述

PerlIO::via 模块允许您在 Perl 中开发 PerlIO 层,而无需深入了解使用 XS 作为 Perl 接口的 C 编程。

一个示例模块,PerlIO::via::QuotedPrint,包含在 Perl 5.8.0 中,更多示例模块可从 CPAN 获得,例如 PerlIO::via::StripHTMLPerlIO::via::Base64。例如,PerlIO::via::StripHTML 模块允许您说

	use PerlIO::via::StripHTML;
	open( my $fh, "<:via(StripHTML)", "index.html" );
        my @line = <$fh>;

以数组形式获取 HTML 文件的文本,并自动删除所有 HTML 标签。

请注意,如果层是在 PerlIO::via:: 命名空间中创建的,则不需要完全限定。如果指定的模块名称不存在作为完全限定的模块名称,PerlIO::via 模块将添加 PerlIO::via:: 命名空间前缀。

预期方法

要创建一个在 Perl 中实现 PerlIO 层的 Perl 模块(而不是使用 XS 作为 Perl 接口的 C 中),您需要提供以下一些子例程。建议在 PerlIO::via:: 命名空间中创建这些 Perl 模块,以便它们可以轻松地在 CPAN 上找到并使用 PerlIO::via 模块本身的默认命名空间功能。

请注意,这是 Perl 中最近开发的领域,因此此处描述的接口仍可能发生变化(并且希望会有更好的文档和更多示例)。

在下面的方法描述中,$fh 将是一个指向 glob 的引用,可以将其视为 perl 文件句柄。它引用下面的层。如果层位于堆栈的底部,则不会传递 $fh,出于这个原因以及为了保持与 TIEHANDLE 类的一定程度的“兼容性”,它最后传递。

$class->PUSHED([$mode,[$fh]])

应返回一个对象或类,或在失败时返回 -1。(与 TIEHANDLE 相比。)参数是一个可选的模式字符串(“r”,“w”,“w+”,...)和一个指向下面 PerlIO 层的文件句柄。强制性。

当层作为 open 调用的一部分被推入时,PUSHED 将在实际打开发生之前被调用,无论它是通过 OPENSYSOPENFDOPEN 还是让较低层进行打开。

$obj->POPPED([$fh])

可选 - 当层即将被移除时调用。

$obj->UTF8($belowFlag,[$fh])

可选 - 如果存在,它将在 PUSHED 返回后立即被调用。如果层期望数据以 UTF-8 编码,则应返回一个真值。如果它返回真值,则结果与调用者已执行以下操作相同

":via(YourClass):utf8"

如果不存在或返回假值,则流将保持 UTF-8 标志清除。$belowFlag 参数如果存在下面的层并且该层期望 UTF-8,则为真。

$obj->OPEN($path,$mode,[$fh])

可选 - 如果不存在,则较低层执行打开操作。如果存在,则在层被推入后针对正常打开操作调用。此函数可能会发生变化,因为没有简单的方法让较低层执行打开操作,然后重新获得控制权。

$obj->BINMODE([$fh])

可选 - 如果不存在,则在 binmode($fh) 或当 :raw 被推入时,层会被弹出。如果存在,它应该在成功时返回 0,在错误时返回 -1,或返回 undef 以弹出层。

$obj->FDOPEN($fd,[$fh])

可选 - 如果不存在,则较低层执行打开操作。如果存在,则在层被推入后针对传递数字文件描述符的打开操作调用。此函数可能会发生变化,因为没有简单的方法让较低层执行打开操作,然后重新获得控制权。

$obj->SYSOPEN($path,$imode,$perm,[$fh])

可选 - 如果不存在,则底层执行打开操作。如果存在,则在将层推入后调用,用于 sysopen 样式的打开操作,这些操作传递数值模式和权限。此函数可能会发生变化,因为没有简单的方法让底层执行打开操作,然后重新获得控制权。

$obj->FILENO($fh)

返回类似 Unix 的文件描述符的数值。如果不存在,则返回 -1。可选。默认值为 fileno($fh)。

$obj->READ($buffer,$len,$fh)

返回放置在 $buffer 中的八位字节数(必须小于或等于 $len)。可选。默认情况下使用 FILL 代替。

$obj->WRITE($buffer,$fh)

返回已成功写入的 $buffer 中的八位字节数。

$obj->FILL($fh)

应返回要放置在缓冲区中的字符串。可选。如果未提供,则必须提供 READ 或拒绝在 PUSHED 中打开以供读取的句柄。

$obj->CLOSE($fh)

成功时应返回 0,错误时返回 -1。可选。

$obj->SEEK($posn,$whence,$fh)

成功时应返回 0,错误时返回 -1。可选。默认情况下失败,但可能会在将来更改。

$obj->TELL($fh)

返回文件位置。可选。默认值待定。

$obj->UNREAD($buffer,$fh)

返回已成功保存到 $buffer 中的八位字节数,以便在将来的 FILL/READ 调用中返回。可选。默认情况下将数据推入此层之上的临时层。

$obj->FLUSH($fh)

刷新任何缓冲的写入数据。 也可能在可读句柄上调用。 成功时应返回 0,错误时返回 -1。

$obj->SETLINEBUF($fh)

可选。 无返回值。

$obj->CLEARERR($fh)

可选。 无返回值。

$obj->ERROR($fh)

可选。 返回错误状态。 默认情况下,直到制定出信号错误的机制(die?)之前,都没有错误。

$obj->EOF($fh)

可选。 返回文件结束状态。 默认情况下,它是 FILL 或 READ 返回值的函数。

示例

在 CPAN 上查看 PerlIO::via:: 命名空间以获取 Perl 中实现的 PerlIO 层的示例。 为了让您了解 PerlIO 层的实现可以有多简单,这里包含一个简单的示例。

示例 - 十六进制句柄

给定以下模块,Perlio::via::Hex

package PerlIO::via::Hex;

sub PUSHED
{
 my ($class,$mode,$fh) = @_;
 # When writing we buffer the data
 my $buf = '';
 return bless \$buf,$class;
}

sub FILL
{
 my ($obj,$fh) = @_;
 my $line = <$fh>;
 return (defined $line) ? pack("H*", $line) : undef;
}

sub WRITE
{
 my ($obj,$buf,$fh) = @_;
 $$obj .= unpack("H*", $buf);
 return length($buf);
}

sub FLUSH
{
 my ($obj,$fh) = @_;
 print $fh $$obj or return -1;
 $$obj = '';
 return 0;
}

1;

以下代码打开一个输出句柄,该句柄将任何输出转换为输出字节的十六进制转储:例如“A”将转换为“41”(在基于 ASCII 的机器上,在 EBCDIC 平台上,“A”将变为“c1”)

use PerlIO::via::Hex;
open(my $fh, ">:via(Hex)", "foo.hex");

以下代码将读取十六进制转储并在运行时将其转换回字节

open(my $fh, "<:via(Hex)", "foo.hex");