2020/08/16(Sun)
○[オレオレN6] rewrite HZ/HZ8 support for Citrus iconv
介護やら葬儀やらひと段落したので、とりあえずリハビリがてらここ数年中断してた作業を再開してくかなと。
表題の件、どうにもコードが複雑でウンザリしとったのでスクラッチで 書き直した、つーのも最初に書いたときはHZって
という2つのHZをISO2022的に拡張するプロポーザルが存在したので、それを意識し拡張可能なように書いとったんだけど、当然のようにISO2022みたいにクソめんどいコードになってしまいあまり触れたくないコードになっとったのだ *1。
そもそもCitrusではISO2022のサブセットであるEUCも別モジュールになってるわけで、HZ/HZ8も性能を考えて独立したコードにし、HZ+/EHZのサポートは別モジュールを用意しようかなと。 まぁHZ+/EHZなんて実際に使われてるの見たことないんですけどね…EHZがちょっとめんどくさいんですわBIG5の文字を無理矢理0x2121~0x7d7eに詰め込んでたりしててな。
なおencoding moduleの初期化パラメータであるVARIABLEに旧モジュールと互換性が無いので後方互換に問題あるけど、後述するけどいろいろ書き直していろんなとこのバージョン変更する予定だから放置。
ちなみにHZ8というのはHZの仕様書には載ってないし他にサポートするプログラムも見たことないんだけど、実際に China News Digestというサイトの*.hz8.htmlという古いドキュメントで使われてるので実装してある、最新記事はGB2312やUTF-8だけど過去記事(1989年の例のアレとか)は変換せずそのまんまみたいで歴史は残さないとね(ニッコリ)。
それと Issue #139のバグがあった *2のだけど、これも解消したはずだ。
なお数年前からCitrus iconvの内部APIを変更する作業をしてて、それに沿ったコードになってるので本家TNFにマージするにはけっこう作業が必要なはずなので以下略、まあ誰も興味ないだろうが。
この内部APIの変更ってのは Issue #120にチケット切ってあるけど、GNU libiconvと比較して遅せえよゴルァ問題を解決するための準備 *3で、かなり前から準備を進めてたのだがここ数年まともにコード書ける人生でなかったので未だ未完(馬に乗馬)なのである。
これについては大昔にCitrus iconvのどこがボトルネックなのかを調査した時にある程度の結論は出てて、iconvの内部でmbrtowc/wcrtombとほぼ同じAPIが動くというデザインそのものが悪かったという話。 というのも
- mbrtowc/wcrtomb … mbstate_t中にstateful encodingのシフト状態だけでなく変換途中の文字列を保持する
- iconv … iconv_t中にシフト状態は持するけれどもり変換可能な文字にならない中途半端な文字列は捨てる
という挙動の違いがあるのだけど
- Citrus iconvはこの動作の違いを埋めるため、頻繁にmbstate_t/iconv_tのコピー作業をやっている
- Citrusのmbstate_tは変換途中の文字列を最大32(=MB_LEN_MAX)保持するためなどもあり、他の実装と比較してかなり大きなサイズ(128)なので重くなる
という問題にハマってるようなのね、なので
- iconvに最適化した内部APIとしてencode/decodeを用意
- これまでとは逆にmbrtowc/wcrtombの内部でencode/decodeを呼ぶようにする
- restartのために中途半端な文字をmbstate_tに詰めるのはdecodeを呼んだ後でよく実装もシンプルになる
というデザイン変更を目下作業再開したという感じ、まあencode/decodeも実際プロトタイプとしてはこれまでのmbrtowc_priv/wcrtomb_privとたいして変わらんのだけど、restart止めたことで実装はだいぶ違う。 というか4.4BSD Rune由来である這いずり回る混乱ことsputrune/sgetruneのitojun ISO2022拡張と近い処理になり、一周回ってここかよ感はある *4。
まあ残り作業はVIQRを新APIで書き直し *5、iconv_stdモジュールでそっち使うよう切り替えるだけなのでワイの生きてる間に終わる可能性が出てきたかもしれないが、明日の事など判らない時代なので以下略。
*2:これGNU libiconvも同じバグあるんよな…多分それで俺も仕様を勘違いしたんかのう、ちなみにperl iconvは問題なし。
*3:チケットにはどうせUTF-8<->UTF-32だけ専用モジュールを用意して速くすれば文句言ってる人の8割は黙るだろうというkludge patch貼ったけどあまり現時点では採用したくないかな。
*4:その結果あの複雑なISO2022モジュールの書き直しの手間がほとんどなかったのは亀のご加護ですかね。
*5:とかいいながらまったく仕様思い出せねえんだよなぁ…調べるにもどこにドキュメントあるんだっけ状態。