PerlIOの実装メモ#2 PerlIOで出来ること

そもそもPerlIOで何が出来るのか。
その理解のために,標準PerlIO(組み込み+標準ライブラリ)とPerlIO::Utilなどのレイヤについて機能別に分類してみた*1

リソースアクセス系

PerlIOはI/Oのためのシステムだから,何らかのリソースにアクセスするレイヤが常にレイヤスタック*2の最下部(bottom)にある。
リソースアクセス系レイヤは,:stdioのように自前でバッファリングすることもあれば,:unixのようにバッファリング機能を持たないものもある。

  • 標準PerlIO
  • PerlIO::Util
    • :dir

リソース加工系

PerlIOを使うプログラムと低レベルのレイヤとの間にあり,リソースを加工するもの。ただし,このとき扱えるデータタイプには強い制限があり,バイトストリーム(void*)だけである。ルーチンはvoid*を受け取りvoid*を返すのみで,オブジェクトはもちろん「行」を扱うこともできない。PerlIO::via::*のほとんどはこの系統だと思われる。

  • 標準PerlIO
    • :perlio - バッファリングのみで加工はしない
    • :crlf
    • :via::QuotedPrint
    • :encoding
  • PerlIO::Util
    • :tee
    • :reverse

疑似レイヤ/PerlIO制御系

PerlIOの制御のためのコマンドと考えられる疑似レイヤであり,レイヤスタックに乗ることはなくI/Oのパフォーマンスには影響しない。また,:popによって効果を取り除くことはできない。基本的には,open()またはbinmode()を拡張するもの。

  • 標準PerlIO
    • :raw - binmode($fh)の実体
    • :utf8 - Perlに返すデータにUTF-8フラグを付ける
    • :bytes - :utf8の逆
    • :pop - レイヤスタックの最上部にあるレイヤを取り除く
  • PerlIO::Util

したがって,「ファイル以外のリソースにアクセスしたい」「バイトストリームレベルでデータを加工したい」「open()またはbinmode()を少しだけ拡張したい」と感じたとき,それがPerlIOレイヤを実装する動機となりうる。これ以外の要求,たとえばバイトストリームよりも高いレベルでデータの加工をしたいときなどは,tieや入力演算子<>のオーバーロードを考えた方がいい。

*1:ただし,この分類は絶対ではない。

*2:PerlIOはレイヤインスタンスのリンクリストとなっている。参照:http://perldoc.perl.org/perliol.html