From: "NARUSE, Yui" Date: 2008-01-23T12:59:04+09:00 Subject: [ruby-dev:33295] Re: requests to transcode 成瀬です。 U.Nakamura wrote: > In message "[ruby-dev:33286] Re: requests to transcode" > on Jan.23,2008 07:41:13, wrote: > | stateful encoding を処理するは、ISO 2022 についてならば直前の escape > | sequence というか、現在の文字集合番号とバイト列があればよいかと。ここで > | 1 byte をブロックに渡すか、多バイト必要な場合なことを考えて複数バイト渡 > | すか、いっそのことバイト列すべてと現在の index を渡すかが迷いどころです > | かねぇ。 > > あんまりたくさんブロックに引数を渡すようにしても書き間違える > だけなので、成瀬さんの2つ目の案のように2個程度に留めるか、情 > 報をまとめたクラスのインスタンスを1個渡すか、どちらかが現実的 > でしょうね。 > とりあえず後者にしておけば後で仕様を追加できるので、実装する > 方は気が楽かもしれません。 それだと converer 一つですかねぇ。 必要な情報は [ruby-dev:33286] のmbsrtowcs 風 API と同じなので、後はそれ をどう詰め込むかと、state をどう保持しどう返すかでしょうか。 > | > フラグを使う例だと、変換不能な文字を任意の指定文字に置換する > | > ことはできないような気がしますが、例えばスレッドローカルな特 > | > 殊変数で指定するとかいうことを考えておられますか? > | > | エンコーディングごとにデフォルトの置換文字が決まっているので、通常はそれ > | を用いればいいかと。変えたい場合はブロックで。ハッシュなりで渡すという方 > | 法もあるでしょうね。 > > 「決まってる」というのは、何で決まってるんでしょう? > # 不勉強ですみません あ、ウソです。 ICU やそれを引いてる Encode は ucm ファイル中の で、 Citrus の場合はエンコーディング定義ファイルの INVALID で、 「実装が決めてる」ケースが多い、ですね。 っと、思ったら GNU libiconv はオプションで与えさせていました。 というか、これってよくよく考えると、 * エラー * 無視 * 特定の置換文字 * 対応する文字列 (U+XXXXや\xXXや\uXXXXなど) になるわけで、無視を空文字、対応する文字列をフォーマット文字列と読み替え れば、エラー以外は string なわけで、これって定数じゃなくて文字列でいい気 がしてきました。 つまり、以下の通り。 * エラー: nil * 無視: "" * 置換文字: "?" "〓" "\uFFFD" 等 * 対応する文字列 "U+%4X" "\\x%2X" "\\u{%X}" 等 っと、思ったのですが、バイトとして不正な場合と変換できない文字の場合で話 が違うような気がちらり。もうちょっと整理が必要かも。mb2mb って暗黙に mb.valid? -> mb2wc -> wc2mb してるので、どの段階で死んだかによって話が変 わるんですよね。 # そういえば多段変換ってのもあったなぁ・・・。 > | > 変換元Cバイト配列、変換元encoding、変換先encoding、変換失敗時 > | > 対応方法、というような引数で呼べると嬉しいです。 > | > 変換失敗時対応方法として、エラー、指定文字に置き換え、のいず > | > れかを選べ、エラー時には例外でなく戻り値で示してもらえると嬉 > | > しいですね。 > | > | 思うに mbsrtowcs 的な API についての話だと思います。 > > ああ、いや、なんというか、単に > rb_funcall(str, rb_intern("encode"), 1, enc); > と書かずに直接rb_str_transcode()相当を呼びたかっただけという > だけです。 > ただしrb_str_transcode()そのものはrubyインタプリタ評価器から > 呼ばれること前提なので、argvをばらした状態で呼べるものが欲し > いな、というそれだけ... あー、なるほど。途中でもうちょっと上のレイヤーカナーって気はしたんです が、まぁ備忘録代りにまとめてもいいかなーと。 > 変換失敗時対応方法という引数があるといいというのは、String#encode > 自体がそういう方向になるはずなので、というだけです。 > > といわわけで、戻り値はVALUE(String)でいいですし、失敗はnilで > 教えてくれればもう十分で、呼んだ側は失敗してたら後は死ぬなり > 何なりすればいいやと思っていたので失敗したところから再開とか > は全然考えていませんでした。 たぶん、「何なりする」ために再開が必要じゃないかなーと思います、たぶん。 > 成瀬さんの案は、String#encodeのブロック引数つき版に対応したAPI > ということになるかと思うのですが、これはまあこれとして、私が > 欲しかったのはもっと手軽に呼べるシンプルな奴です、はい。 ブロック引数付き版を 純粋な C のレイヤーでやるとこうなってしまうという例 ですかね。失敗したら無視かそのまま死んでしまうなら大幅にシンプルになるで しょう。 ただ、失敗を救おうとすると再開や中断場所の情報が必要になって、再開可能に すると状態が必要になるというように情報が増えていくので、とりまわしは多少 楽になっても、本質的に必要な情報はあまり変わらないかなぁと気もします。 -- NARUSE, Yui DBDB A476 FDBD 9450 02CD 0EFC BCE3 C388 472E C1EA