NCAPI & C++11+ & RX & Qt #10 ~LMBCS
はじめに
タイトル、短縮しました。とにかく長かった。
僭越ながら、名著をアップデート
私にとってのバイブル的存在、「Notes/Domino APIプログラミング」(2000年 津田義史著)を改めて紹介します。
Notes/Domino APIプログラミング―C++とSTLによる実践的プログラミング
- 作者: 津田義史
- 出版社/メーカー: オーム社
- 発売日: 2000/03
- メディア: 単行本
- 購入: 1人 クリック: 18回
- この商品を含むブログを見る
Notes C APIに携わる数少ない(であろう)日本人の一人として、18年経った今でも拠り所となる本です。とはいえ、です。そろそろアップデートしないと厳しいところも出てきているのも事実です。この本で学んだことを元に、お気に入りのフレームワークQtと、手になじんでいる範囲でのC++11以降のスタイルと、今年お気に入りとなったReactiveXを混ぜ込んで、私なりのアップデートを試みていきたいと思います。
LMBCS
このブログでは何度か取り上げている、Notes/Domino独自のマルチバイト文字セット「LMBCS(リンビックス)」。前著にも「2.7 LMBCS文字コードと日本語処理」として、初期化/終了処理、マルチスレッドに続く早い段階でAPIが紹介されています。このLMBCSの処理方法は、APIでプログラムを書く上でも早々に確立しておかないと、何もできなくなってしまいます。
シフトJIS
日本語Windowsの文字コードは長らくシフトJISでしたが、最近ではUnicode(UTF-16)が使われているらしいです。WindowsのAPIでも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系(Linux、Mac)はUnicodeでもUTF-8が主流のようですが、Qtが扱う文字列クラスQString
の内部文字コードは、ずいぶん前からUTF-16のようです。シフトJISもUTF-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推定バイト数を算出
(続く)