srfi.181
- カスタムポート ¶このsrfiは、ポートをSchemeで実装する方法を定義します。
Gaucheは仮想ポートとしてそういう機能を提供しています(gauche.vport
- 仮想ポート)が、
ポータブルなコードを書く場合はこのsrfiが便利でしょう。
インタフェースはR6RSの上位互換になっています。
R7RSではバイナリポートとテキストポートは区別されますが、 Gaucheのポートはバイナリもテキストもどちらも読み書きできます。
• カスタムポートの作成: | ||
• 符号変換ポート: |
[SRFI-181]{srfi.181
}
それぞれ、新たなバイナリポートとテキストポートを作って返します。
id引数は任意のSchemeオブジェクトです。このsrfiではそれがどう使われるかは
規定されません。Gaucheでは、idに渡した値は
port-name
手続きで得ることができます(ポート共通の操作参照)。
read!引数は手続きで、
(read! buffer start count)
のように呼び出されます。
make-custom-binary-input-port
では、bufferは
バイトベクタ(u8vector)です。
make-custom-textual-input-port
では、bufferは文字列か
文字のベクタです(Gaucheでは常に文字のベクタが渡されますが、
ポータブルなコードはどちらにも対応できるように書かれなければなりません)。
read!手続きは、最大でcount個のバイトもしくは文字を生成し、 それをbufferのstart番目から書き込んで、 生成されたバイト/文字数を返します。 read!手続きは入力データがあるなら、 少なくとも1バイト/文字をバッファに書き込まなければなりません。 入力データがもう無いことを示すには、バッファを変更せず、0を返します。
get-pos引数は、引数を取らない手続きで、呼ばれたら入力ストリーム中の現在の位置を
示す処理系依存のオブジェクトを返します。「現在の位置」とは、次にread!が呼ばれた
時に読み出される位置です。カスタムポートが位置情報を扱う必要がなければ、
この引数は#f
で構いません。
ただし、make-custom-binary-input-port
については、
get-posが正確な整数を返す場合、
それは入力ストリーム中のバイト位置でなければなりません。
set-pos!引数はひとつの引数を取る手続きです。
渡された引数は以前のget-posが返した値か、
make-custom-binary-input-port
の場合は、
入力先頭からのバイトオフセットです。
この手続きは、次のread!が指定位置からデータを読み出すように内部状態を更新します。
カスタムポートが位置情報のセットをサポートしなくて良いなら、この引数は#f
で
構いません。
set-pos!に渡された位置情報が不正なものであった場合、それは
i/o-invalid-position-error?
を満たすエラーを投げなければなりません。
ポータブルに書くには、make-i/o-invalid-position-error
で作った
エラーオブジェクトを投げます(srfi.192
- ポート位置参照)。
Gauche特有のコードで良ければ、
<io-invalid-position-error>
コンディションを投げても良いです。
close引数は、カスタムポートがクローズされた時に呼び出される、
引数を取らない手続きです。特にクローズ時のクリーンアップが不要であれば
#f
を渡すこともできます。
[SRFI-181]{srfi.181
}
それぞれ、バイナリ出力ポートおよびテキスト出力ポートを作成して返します。
idは任意のSchemeオブジェクトです。このSRFIはその用途について特に規定しません。
Gaucheでは、port-name
手続きによってidを得ることができます
(ポート共通の操作参照)。
write!引数は、(write! buffer start count)
のように
呼び出される手続きです。make-custom-binary-output-port
では
bufferはバイトベクタで、make-custom-textual-output-port
では
bufferは文字列もしくは文字のベクタです(Gaucheでは常にベクタが渡されますが、
ポータブルなコードではどちらが来ても良いように書いておく必要があります)。
write!手続きは、bufferのインデックスstartから最大count要素 を外部のシンクへと書き出し、実際に書き出された要素数を返します。
get-pos引数は、引数を取らない手続きか#f
でなければなりません。
手続きの場合、呼ばれたら、次のwrite!が書き込むであろうシンクの位置を返します。
位置は任意のSchemeオブジェクトが許されますが、
make-custom-binary-output-port
の場合、get-posが
正確な整数を返すならそれはポートのバイトオフセットでなければなりません。
set-pos!引数は引数をひとつ取る手続きか#f
でなければなりません。
手続きの場合、引数はシンクの位置を示すオブジェクトで、次のwrite!が
その位置から書き込まれるようにポートと状態をセットします。
位置を示すオブジェクトは、同じポートに対してget-posが以前返した位置か、
もしくはmake-custom-binary-output-port
の場合、ポートの先頭からの
バイトオフセットを示す正確な整数です。set-pos!が#f
の場合は、
ポートは位置を変える手段を持ちません。set-pos!の戻り値は無視されます。
set-pos!に渡された引数が位置を示すオブジェクトとして不適切だった場合は、
述語i/o-invalid-position-error?
を満たすエラーを投げなければなりません。
ポータブルなコードでは、make-i/o-invalid-position-error
を使って
そのようなエラーを作ることができます (srfi.192
- ポート位置参照)。
Gauche特有のコードなら、<io-invalid-position-error>
コンディションを
投げることもできます。
close引数は引数を取らない手続きで、ポートが閉じられた時に呼ばれます。
ポートが閉じられた時に特にすることが無ければ#f
を渡しても構いません。
flush引数は、引数を取らない手続きか#f
です。
ポートが、バッファされたデータが確実にシンクに書き出されたことを保証したい時に
呼ばれます。
[SRFI-181]{srfi.181
}
バイナリ入出力ポートを作って返します。Gaucheはバイナリポートと
テキストポートを区別しないので、作られたポートをテキスト入出力に使うこともできますが、
ポータブルなコードではそれは避けるべきでしょう。
(このSRFIではテキスト入出力ポートは定義されません。 というのも、文字ストリームの内部表現とは独立した一貫性のあるセマンティクスを 定義するのが難しいからです。Gaucheでは文字の入出力は 内部エンコーディングに従ったオクテット列の入出力とみなします。)
引数id、read!、write!、get-pos、set-pos!、
close、flushの意味は、
make-custom-binary-input-port
およびmake-custom-binary-output-port
のそれらと同じです。
符号変換ポートとは、システムの文字エンコーディング以外の符号化方式でエンコードされた 文字の読み書きをポータブルにする方法です。 このAPIは当初R6RSで定義され、SRFI-181に採用されました。
SRFI-181(およびR6RS)の世界では、文字列と文字はエンコーディングという概念を持たない 抽象化されたオブジェクトです (内部的には、システムのネイティブエンコーディングで 保持されていると考えて良いでしょう)。 従って、エンコーディングを考える必要があるのは、 外部から与えられる、ファイルやバイトベクタに格納されたバイナリデータを扱いたい時だけです。 従って符号変換は、バイナリポート(外部世界)とテキストポート(内部世界)の間か、 バイトベクタ(外部世界)と文字列(内部世界)の間でのみ定義されます。
用語の定義:
文字エンコーディング方式(CES)を特定するオブジェクトです
行末文字の扱いを指定する名前
コーデック、行末スタイル、エラー処理をまとめるオブジェクト
註: Gauche特有のコードなら、gauche.charconv
モジュールがさらに柔軟な
機能を提供しています(gauche.charconv
- 文字コード変換参照)。
[SRFI-181]{srfi.181
}
与えられたパラメータをまとめたトランスコーダを作って返します。
トランスコーダは変更不可なオブジェクトです。
codec引数はmake-codec
で作られるか、あらかじめ作られている
コーデックオブジェクトです。下で説明します。
eol-style引数は行末文字の処理を指定する、次のシンボルのいずれかです。
none
行末文字の変換を行いません。
lf
出力ポートは#\nelwine
文字をLF
オクテットに変換します。
入力ポートはどんな行末文字でも#\newline
に変換します。
crlf
出力ポートは#\nelwine
文字をCR-LF
オクテット列に変換します。
入力ポートはどんな行末文字でも#\newline
に変換します。
error-handling引数は、エンコードもしくはデコードできない文字があったときの 振る舞いを指定する、以下のシンボルのいずれかです。
replace
有効な文字エンコーディングにならないオクテットは文字#\xFFFD
に置き換えられます
(出力変換ポートで変換先の文字セットが#\xFFFD
を持っていない場合は#\?
が
使われます)。
raise
i/o-encoding-error?
を満たすコンディションを伴ってエラーを投げます。
原因になったオクテットは消費され、次のI/Oは次の文字から続行されます。
[SRFI-181]{srfi.181
}
システム内部で使われているコーデックおよび行末スタイルを表すトランスコーダを返します。
Gaucheでは、内部コーデックは内部文字エンコーディング
(gauche-character-encoding
が返すもの。文字参照)
を使うコーデックで、行末スタイルはnone
です。
[SRFI-181]{srfi.181
}
binary-portをラップし、transcoderにより符号変換を行うポートを返します。
binary-portが入力ポートなら、返されるのはテキスト入力ポートで、 transcoderが指定する方式で符号化された外部データを読み込む際に 内部エンコーディングへと変換します。
binary-portが出力ポートなら、返されるのはテキスト出力ポートで、 内部エンコーディングによる文字や文字列を出力する際に、 transcoderが指定する方式へと変換します。
Gaucheでは符号変換は変換ポートで行われます。 詳しくは変換ポートを参照してください。
[SRFI-181]{srfi.181
}
bytevectorに格納されたバイナリデータを、
transcoderで指定される符号化方式によるものとみなして、
それを内部エンコーディングによる文字列に変換したものを返します。
Gaucheのces-convert
のラッパーです (変換ポート参照)。
[SRFI-181]{srfi.181
}
文字列を、transcoderが指定する符号化方式に変換したものをバイトベクタとして返します。
Gaucheのces-convert-to
のラッパーです (変換ポート参照)。
[SRFI-181]{srfi.181
}
nameで指定される文字符号化方式を表すコーデックを返します。
ポータブルなコードではnameに文字列を渡してください。Gaucheではシンボルも
受け付けます。
nameがサポートされているコーデックの名前でなければ、
述語unknown-encoding-error?
を満たすコンディションを伴ってエラーが投げられます。
[SRFI-181]{srfi.181
}
システムが認識しないあるいはサポートしないコーデックを使うように指示された場合、
この述語を満たすコンディションが投げられます。
[SRFI-181]{srfi.181
}
引数は述語unknown-encoding-error?
を満たすコンディションでなければなりません。
このコンディションの原因となったコーデック名を返します。
[SRFI-181]{srfi.181
}
あらかじめ作られている、
latin-1
(ISO8859-1)、utf-8
、およびutf-16
コーデックを返します。
utf-16
コーデックは入力にBOMがあればそのバイトオーダーを使い、
無ければUTF-16BEを使います。
出力に使われた場合は常にBOMを出力します。
[SRFI-181]{srfi.181
}
デフォルトの行末スタイルを返します。Gaucheではnone
です。
[SRFI-181]{srfi.181
}
入力変換ポートがコーデックとして不正なバイトシーケンスに出会った場合、
この述語を満たすコンディションが投げられます。
Gaucheではそのコンディションは<io-decoding-error>
のインスタンスです。
[SRFI-181]{srfi.181
}
出力変換ポートが出力しようとした文字がコーデックで表わせず、
エラーハンドリングモードがraise
である場合、
この述語を満たすコンディションが投げられます。
Gaucheではそのコンディションは<io-encoding-error>
のインスタンスです。
[SRFI-181]{srfi.181
}
<io-encoding-error>
コンディションの原因となった文字を返します。