[ < ] [ > ]   [ << ] [ Up ] [ >> ]         [Top] [Contents] [Index] [ ? ]

9.27 gauche.vport - 仮想ポート

Module: gauche.vport

仮想ポートあるいは手続き的ポートとは、その振舞いを Scheme でプログラム可能なポートです。

このモジュールは 2 種類の仮想ポートを提供します。ひとつは、 完全仮想ポートで、すべての I/O 操作でユーザが提供する手続きが 呼出されるものです。もうひとつは、仮想バッファポートで、 I/O 操作は内部バッファ上で行われ、ユーザが提供する手続きは バッファを一杯にするかフラッシュする必要がある場合にのみ 呼出されます。

このモジュールはさらに、ユニフォームベクタにより バックアップされる仮想バッファポートも提供します。 これは仮想ポートの使用例でもあります。

完全仮想ポート

このタイプの仮想ポートは、<virtual-input-port> クラス および <virtual-output-port> クラスで実現されています。 適切なスロットに手続きをセットすることでポートの振舞いをカスタマイズ 可能です。

Class: <virtual-input-port>

このクラスのインスタンスは入力ポートとして使えます。 このポートの振舞いはインスタンスのスロットに設定された値に依存します。

まともな入力ポートとして動かすためには、少くとも、getb スロット あるいは getc スロットのどちらか一方は設定しなければなりません。 さもなければ、このポートはすべての入力要求に対して EOF を返します。

Instance Variable of <virtual-input-port>: getb

設定されているのなら、その値は、引数を取らない手続きでなければなりません。 バイナリ入力の要求のたびに、この手続きが呼ばれます。

この手続きは、0 から 255 までの正確な整数を返すか、#fあるいは EOF オブジェクトを返さなければなりません。整数を返す場合には、 それがこのポートから読みとられる値となります。それ以外の値を返す 場合は、このポートは EOF を返します。

このポートが文字入力を要求され、かつ、getc 手続きを持たない場合、 このポートはこの手続きを呼び(複数回の可能性もある)文字全体を構築します。

Instance Variable of <virtual-input-port>: getc

設定されているのなら、その値は、引数を取らない手続きでなければなりません。 文字入力の要求のたびに、この手続きが呼ばれます。

この手続きは文字を返すか、または#fあるいはEOFオブジェクトを返さなければ なりません。文字を返した場合には、それがこのポートから読みとられる値と なります。それ以外の値を返す場合は、このポートは EOF を返します。

このポートがバイナリ入力を要求され、かつ、getb 手続きを持たない場合、 このポートはこの手続きを呼び、文字をバイト列に変換し、それをこのポートから 読みだされる値として使います。

Instance Variable of <virtual-input-port>: gets

設定されているなら、その値は、正の正確な整数の引数をひとつだけとる手続き でなければなりません。ブロックバイナリ入力、たとえば、 read-blockなどが要求された場合に、呼出されます。

そしてそれは文字列、 不完全文字列、 #f、 EOF オブジェクトを 返さなくてはなりません. 文字列を返す場合は上記正の正確な整数によって 指定された大きさを越えてはなりません。空文字列、 #f、EOF を 返した場合はポートの終端にたどり着いたものとみなされます。 (注意: 文字列大きさは文字数でなく文字列が占めるバイト数で指定されます。)

この手続きは効率のためにあります。もし、この手続きが用意されて いなければ、このポートは、データブロックを準備するのに getbを 繰り返し呼びます。場合によっては、ブロック入力を用意するほうが はるかに効率的です。(たとえば、メモリチャンクのブロックからの読みだし を行なうような場合です。)

こうした利点を必要としないのなら、このスロットは未設定のままにして おいてもかまいません。

Instance Variable of <virtual-input-port>: ready

設定されているなら、その値は、真偽値をひとつだけとる手続きでなければ なりません。この手続きは、このポートに対して、char-ready? あるいは byte-ready? が呼ばれたときに呼出されます。設定した手続き が返す値が、これらの手続きの結果になります。

char-ready? が呼ばれたのなら、真偽値引数は #t です。 byte-ready? が呼ばれたのなら、真偽値引数は #f になります。

未設定なら、char-ready? および byte-ready? は このポートに対して常に、#t を返します。

Instance Variable of <virtual-input-port>: close

設定されているのなら、その値は引数を取らない手続きでなければなりません。 その手続きはこのポートがクローズされるときに呼びだされ、返り値は 捨てられます。このポートをクローズするときになんらかのアクションが 必要でないのなら、未設定にしておけます。

この手続きはファイナライザから呼ばれることもあり得ます。したがって、 この手続きは慎重に書く必要があります。後述のファイナライズに 関する注意を参照してください。

Instance Variable of <virtual-input-port>: seek

設定されているのなら、その値は、オフセット引数とそれがどこからかを示す引数 の 2つの引数をとる手続きでなければなりません。これらの引数の意味は、 port-seek (ポート共通の操作 参照) のそれと同じです。 この手続きは、次の読み出しが新しい位置から始められるように 内部のリードポインタを調整しなければなりません。そして 更新されたポインタ(ポート先頭からのバイトオフセット) を返さなければなりません。

未設定なら、このポートに対する port-seek および port-tell の呼び出しは #f になります。

この手続きは単に現在の位置を問合せるために、 offset として 0 を、whence として SEEK_CUR を与えて 呼び出すこともあることに注意してください。リードポインタの位置は知って いるが、動かすことができないという場合にも、この手続きを提供することが できます。上のような問合せには、現在位置を返し、そうでない場合には、 #f を返します。

Class: <virtual-output-port>

このクラスのインスタンスは出力ポートとして使えます。 このポートの振舞いはインスタンスのスロットに設定された値に依存します。

まともな出力ポートとして動かすためには、少くとも、putb スロット あるいは putc スロットのどちらか一方は設定しなければなりません。

Instance Variable of <virtual-output-port>: putb

設定されているなら、その値は、バイト値(0 から 255までの正確な整数)を ひとつだけ引数としてとる手続きでなければなりません。バイナリ出力 の要求のたびに、この手続きが呼ばれます。この手続きの返り値は無視 されます。

このスロットが未設定の場合、バイナリ出力を要求されると、このポートは <io-unit-error> エラーを発生させることがあります。

Instance Variable of <virtual-output-port>: putc

設定されているなら、それは文字をひとつ引数にとる手続きでなければなりません。 文字出力の要求があるたびにこの手続きがよばれます。この手続きの返り値は 無視されます。

このスロットが未設定であっても、putb スロットが設定されていれば、 この仮想ポートは文字をバイト列に展開してから、putb を呼びだします。

Instance Variable of <virtual-output-port>: puts

設定されていれば、その値は、文字列(不完全なものである可能性もある)を ひとつ引数としてとる手続きでなければなりません。この手続きの返り値は 無視されます。

これは、効率のためにあります。このスロットが未設定であれば、この 仮想ポートは、データのかたまりを出力するために、putb あるいは putc を繰り返し呼びます。もし、ひとかたまりの 出力を効率的に実行可能なコードであれば、この手続きを提供できます。

Instance Variable of <virtual-output-port>: flush

設定されていれば、その値は引数をとらない手続きでなければなりません。 ポートのフラッシュを要求されたときに呼ばれます(たとえば、flush がこのポートに対して呼ばれたとき、あるいは、このポートがクローズ されるとき)。

この手続きは、ポートが何らかのバッファリングをおこなうか、なんらかの 状態を持つような場合に便利です。ポートが状態をともなう操作を行わない のなら、これは未設定にしておけます。

この手続きはファイナライザから呼ばれることがあります。したがって、 特別な注意が必要です。後述のファイナライザに関する注意を 参照してください。

Instance Variable of <virtual-output-port>: close

<virtual-input-port>close スロットと同様です。

Instance Variable of <virtual-output-port>: seek

<virtual-input-port>seek スロットと同様です。

仮想バッファポート

このタイプの仮想ポートは <buffered-input-port> クラス および <buffered-output-port> クラスで実現されています。 適切なスロットに手続きを設定するこでポートの振舞いをカスタマイズ することができます。

これらのポートは、内部バッファを持っており、そのバッファを満たすか フラッシュするかの必要があるときにのみ、Scheme の手続きが呼ばれます。 通常、I/O毎に Scheme の手続きを呼ぶよりも遥かに効率がいいものです。 実際の内部バッファリング機構は、GaucheのファイルI/Oポートと同じです。

これらのポートはバッファとして u8vector を使います。詳細は、 gauche.uvector - ユニフォームベクタ を参照してください。

Class: <buffered-input-port>

このクラスのインスタンスは、入力ポートとして振舞います。 これは以下のようなインスタンススロットを持ちます。 意味のある入力ポートとして使うには少くとも、fill スロットを 設定しなければなりません。

Instance Variable of <buffered-input-port>: fill

設定されているなら、u8vector の引数を一つとる手続きでなければ なりません。そのベクタの最初からデータを満たさなければなりません。 要求されたものよりデータの残りが少ない場合には、 ベクタ全体を満たす必要はありません。しかしながら、 データが残っている場合には少くとも1バイトは満たさなければなりません。 もしデータがまだ利用可能になっていなければ、なにがしかのデータが利用可能に なるまで待たなければなりません。

この手続きは実際に満されたバイト数を返さなければなりません。ポートが EOFに達したことを示すために、0 または EOFオブジェクトを返すこともできます。

Instance Variable of <buffered-input-port>: ready

設定されているなら、引数をとらない手続きでなければなりません。 この手続きは、なにがしかの読み込み用データが利用可能になっていれば 真の値を返し、そうでなければ、#fを返します。完全仮想ポートとはちがい、 バイナリI/Oと文字I/Oを区別する必要はありません。

このスロットが未定義の場合、このポートは常にデータが利用可能になっている とみなされます。

Instance Variable of <buffered-input-port>: close

設定されていれば、引数をとらない手続きでなければなりません。この手続きは 仮想バッファポートがクローズされるときに呼出されます。ポートがクローズ されるときに、なにがしかのクリーンアップを行うのでなければ、設定する必要 はありません。

この手続きは、ファイナライザから呼ばれる可能性がありますので、特別な 注意が必要です。後述のファイナライズに関する注意書きを参照してください。

Instance Variable of <buffered-input-port>: filenum

設定されているなら、このポートの使っているファイルディスクリプタ番号(正確な非負整数) を返す手続きでなければなりません。この手続きは port-file-number をこのポートに対して呼出したときに呼ばれます。

そのようなファイルディスクリプタが存在していなければ、 #f を返すことができます。 あるいは、このスロットを未設定にしておくこともできます。

Instance Variable of <buffered-input-port>: seek

設定されているなら、オフセット引数とどこからかを示す引数の2つをとる 手続きでなければなりません。これは、前述の <virtual-input-port>のseek 手続きと同じように動作します。

この手続きはファイナライザから呼ばれる可能性があり、特別な注意が 必要です。後述のファイナライズに関する注意を参照してください。

これらのスロットの値以外に、当該ポートの内部バッファのサイズを設定する のにはmakeメソッドに:buffer-sizeというキーワード引数で非 負の正確な整数を渡します。:buffer-sizeが省略されるか、0 が渡さ れた場合にはシステムのデフォルトのバッファサイズ(たとえば、8kとか)が使 われます。:buffer-sizeはインスタンススロットではないので、バッ ファポートのインスタンスを生成したあとで設定することはできません。以下 は 64K のバッファを使うバッファの作り方の例です。

 
(make <buffered-input-port> :buffer-size 65536 :fill my-filler)
Class: <buffered-output-port>

このクラスのインスタンスは出力ポートして振舞います。これは、以下のような インスタンススロットを持ちます。少くとも flush は設定しなければ なりません。

Instance Variable of <buffered-output-port>: flush

設定されているなら、u8vectorのバッファとフラグという2つの 引数をとる手続きでなければなりません。手続きはバッファ内のデータを どこかへ出力しなければならず、実際に出力したバイト数を返します。

フラグが偽なら、この手続きはバッファ全体よりも少い(ただし、最低でも 1バイト)の出力を行ってもかまいません。もしフラグが真ならば、この手続きは、 バッファの内容をすべて出力しなければなりません。

Instance Variable of <buffered-output-port>: close

<buffered-input-port>close スロットと同様です。

Instance Variable of <buffered-output-port>: filenum

<buffered-input-port>filenum スロットと同様です。

Instance Variable of <buffered-output-port>: seek

<buffered-input-port>seek スロットと同様です。

これらのスロットの値以外に、当該ポートの内部バッファのサイズを設定する のにはmakeメソッドに:buffer-sizeというキーワード引数で非 負の正確な整数を渡します。詳しくは前述 <buffered-input-port> の項を見てください。

ユニフォームベクタポート

以下の 2つの手続きは、ユニフォームベクタでバックアップされた、 バッファ入/出力ポートを返します。読み込み元のベクタあるいは 書き出し相手のベクタはどのようなユニフォームベクタであってもかまいませんが、 実際の入出力時にはu8vector にaliasされます (ユニフォームベクタの変換uvector-alias 参照)。

pack/unpack(binary.pack - バイナリデータのパック参照) と一緒に使うと バイナリのデータ構造をパースしたり、構築したりするのに便利です。 また、仮想ポートの使い方の例でもあります。実装法に興味があれば、 ソースツリーの ‘gauche/vport.scm’(あるいは ‘ext/vport/vport.scm’) を読んでください。

Function: open-input-uvector uvector

与えられたユニフォームベクタ uvectorの最初からその内容を読む 入力ポートを返します。読み込み動作が、uvectorの終端に到達したら EOFが返されます。シーク操作も実装されています。

Function: open-output-uvector uvector

与えられた uvector をポートへのデータ出力で満たす出力ポートを返します。 uvectorが満杯になれば、それ以上のデータは黙って廃棄されます。 シーク操作も実装されています。

ファイナライズに関する注意

クローズされていない仮想ポートがガベージ・コレクションされると、 クローズ手続きが呼ばれます(仮想バッファポートの場合は、 フラッシュ手続きがクローズ手続きの前に呼ばれます)。これは、 そのポートのファイナライザによって行われます。これはガベージ・コレクション 処理の一部ですから(Scheme 手続きそのものはガーベッジ・コレクタの メインパートの外側で呼ばれているのですが、それでも)特別な注意が必要です。


[ < ] [ > ]   [ << ] [ Up ] [ >> ]

This document was generated by Shiro Kawai on November, 22 2009 using texi2html 1.78.