NCAPI & C++11+ & RX & Qt #10 ~LMBCS

はじめに

タイトル、短縮しました。とにかく長かった。

僭越ながら、名著をアップデート

私にとってのバイブル的存在、「Notes/Domino APIプログラミング」(2000年 津田義史著)を改めて紹介します。

Notes/Domino APIプログラミング―C++とSTLによる実践的プログラミング

Notes/Domino APIプログラミング―C++とSTLによる実践的プログラミング

Notes C APIに携わる数少ない(であろう)日本人の一人として、18年経った今でも拠り所となる本です。とはいえ、です。そろそろアップデートしないと厳しいところも出てきているのも事実です。この本で学んだことを元に、お気に入りのフレームワークQtと、手になじんでいる範囲でのC++11以降のスタイルと、今年お気に入りとなったReactiveXを混ぜ込んで、私なりのアップデートを試みていきたいと思います。

LMBCS

このブログでは何度か取り上げている、Notes/Domino独自のマルチバイト文字セット「LMBCS(リンビックス)」。前著にも「2.7 LMBCS文字コードと日本語処理」として、初期化/終了処理、マルチスレッドに続く早い段階でAPIが紹介されています。このLMBCSの処理方法は、APIでプログラムを書く上でも早々に確立しておかないと、何もできなくなってしまいます。

シフトJIS

日本語Windows文字コードは長らくシフトJISでしたが、最近ではUnicode(UTF-16)が使われているらしいです。WindowsAPIでもchar型(シングルバイト文字列とシフトJISなどのマルチバイト文字列)とwchat_t型(ワイド文字列)と、同じAPIでも扱う文字列によって2種類の関数が用意されています(前者をANSI版、後者をUnicode版と呼称します)。VCでは両者を区別して書かなくてもいいように、_TCHAR型という型を用意して、宣言次第でどちらでも扱えるようにしています。ただし、このANSI版とUnicode版はまったく機能差がないわけではないようで、例えばパス文字列などの最大文字数などで、ANSI版では短いパス長しか扱えないことがあります。

なお、前著では、LMBCSとシフトJISを、std::string上で相互変換する関数を紹介しています。

UnicodeとQt文字列

WindowsでもUnicode(UTF-16)が優位になってきていますが、マルチプラットフォームC++フレームワークであるQtでは、文字列はどのように扱っているのでしょうか。最近のUnix系(LinuxMac)はUnicodeでもUTF-8が主流のようですが、Qtが扱う文字列クラスQStringの内部文字コードは、ずいぶん前からUTF-16のようです。シフトJISUTF-8も、文字によって長さが変わる文字コードは扱いにくいんでしょうか。

ただ、Notes C APIから受け取る文字列をQStringに統一しておくと、マルチプラットフォームでの開発はとても楽になります。また、Notes C API関数には、LMBCSとUnicode(UTF-16)との相互変換関数が用意されているので、LMBCS文字列をラップするクラスと、QStringと相互に変換できるメソッドを用意することにします。

NLS

前著では、C++側の文字列をシフトJISとしていたので、変換時に扱うバイト数は、「半角カナ文字1バイトをLMBCSにすると3バイトになる」という法則をもって用意するバッファの大きさを決めていました。原因は、LMBCS、シフトJISともに1文字当たりのバイト数が変化するところでしょう。

QStringは1文字当たりのバイト数は2バイトと固定です。課題はLMBCSということになります。前著では紹介されませんでしたが、現在Notes C APIには「NLS(National Language Service)」というものがあり(以前紹介しました)、LMBCSを含む対応文字セットの文字数を数える機能があります(NLS_string_chars関数)。これを使えば、LMBCS→Unicode変換時にムダのないバッファサイズを決めることができます。ただしUnicode→LMBCS変換時は、相変わらず推測計算するしかないですが。

  • LMBCS→文字数を取得→2倍にする→QString(Unicode)バイト数が判明

  • QString(Unicode)→(半角英数0.5倍、全角1.5倍、半角カナ1.5倍)→文字数×2バイト×1.5→LMBCS推定バイト数を算出

(続く)