Notes C API探訪: NLS_PINFO(データ型)
NLS_PINFO型はNLS_INFOのポインタ型です。NLSとはNational Language Servicesの略で、Notes/Dominoのi18n的なサービスをするものであり、主に言語文字列で扱う関数を提供します。NLS_INFO型は、その言語に合わせた情報が詰まっているはずですが、定義的にはvoidで、ヘッダファイルを見てもNLS_INFOの内部構成をうかがい知ることはできません。
LMBCS
LMBCSとは、「Lotus Multi-Bytes Character Set」の略で、Notes/Dominoの内部文字列の標準となっている文字セットです。LMBCSは、UTF-8のように1文字当たりのバイト数が1〜4と可変になっています。半角英数は1バイト、日本語全角の場合は3バイトで、半角カナも3バイトです。LMBCSも、NLSで扱う言語セットの1つになっています。
ロードとアンロード
通常NLS_PINFOは、NLS_load_charset関数でロードして、言語セットポインタを格納します。
#include <nls.h>
NLS_STATUS LNPUBLIC NLS_load_charset(WORD CSID, NLS_PINFO FAR *ppInfo);
NLS_load_charsetでロードしたポインタは、NLS_unload_charsetでアンロードします。
#include <nls.h>
NLS_STATUS LNPUBLIC NLS_unload_charset(NLS_PINFO pInfo);
ただ、LMBCSセットやプラットフォームネイティブの文字セットは、以下の関数で扱えます。取得したポインタは、経験上NLS_unload_charsetで解放してはいけません。
#include <osmisc.h>
NLS_PINFO LNPUBLIC OSGetLMBCSCLS(void);
NLS_PINFO LNPUBLIC OSGetNativeCLS(void);
NLS_PINFOを使った関数
取得したポインタはハンドル感覚でNLS系関数を使えるようになります。以下は、文字判定系の関数です。
#include <nls.h>
NLS_STATUS LNPUBLIC NLS_isalpha (const BYTE far * pCharacter, NLS_PINFO pInfo);
NLS_STATUS LNPUBLIC NLS_isalnum (const BYTE far * pCharacter, NLS_PINFO pInfo);
NLS_STATUS LNPUBLIC NLS_isarith (const BYTE far * pCharacter, NLS_PINFO pInfo);
NLS_STATUS LNPUBLIC NLS_iscntrl (const BYTE far * pCharacter, NLS_PINFO pInfo);
NLS_STATUS LNPUBLIC NLS_isdigit (const BYTE far * pCharacter, NLS_PINFO pInfo);
NLS_STATUS LNPUBLIC NLS_islower (const BYTE far * pCharacter, NLS_PINFO pInfo);
NLS_STATUS LNPUBLIC NLS_ispunct (const BYTE far * pCharacter, NLS_PINFO pInfo);
NLS_STATUS LNPUBLIC NLS_isspace (const BYTE far * pCharacter, NLS_PINFO pInfo);
NLS_STATUS LNPUBLIC NLS_isupper (const BYTE far * pCharacter, NLS_PINFO pInfo);
NLS_STATUS LNPUBLIC NLS_isleadbyte (BYTE Character, NLS_PINFO pInfo);
以下は、文字列内を検索したり移動したりする関数です。
#include <nls.h>
NLS_STATUS LNPUBLIC NLS_find (BYTE far * far * ppString, WORD Len, const BYTE far * pSetOfChars, WORD ControlFlags, NLS_PINFO pInfo);
NLS_STATUS LNPUBLIC NLS_find_substr (BYTE far * far * ppString, WORD Len1, const BYTE far * pSubString, WORD Len2, NLS_PINFO pInfo);
NLS_STATUS LNPUBLIC NLS_get (BYTE far * far * ppString, WORD Len, BYTE far * pCharacter, NLS_PINFO pInfo);
WORD LNPUBLIC NLS_goto_next (BYTE far * far * ppString, WORD Len, NLS_PINFO pInfo);
WORD LNPUBLIC NLS_goto_prev (BYTE far * far * ppString, const BYTE far * pStrStart, NLS_PINFO pInfo);
WORD LNPUBLIC NLS_goto_next_word_end (BYTE far * far * ppString, WORD Len, NLS_PINFO pInfo);
WORD LNPUBLIC NLS_goto_next_word_start(BYTE far * far * ppString, WORD Len, NLS_PINFO pInfo);
WORD LNPUBLIC NLS_goto_next_break (BYTE far * far * ppString, WORD Len, NLS_PINFO pInfo);
WORD LNPUBLIC NLS_goto_prev_word_end (BYTE far * far * ppString, const BYTE far * pStrStart, NLS_PINFO pInfo);
WORD LNPUBLIC NLS_goto_prev_word_start(BYTE far * far * ppString, const BYTE far * pStrStart, NLS_PINFO pInfo);
以下は、文字を別のバッファにコピーします。
#include <nls.h>
NLS_STATUS LNPUBLIC NLS_put (BYTE far * far * ppString, const BYTE far * pCharacter, NLS_PINFO pInfo);
NLS_STATUS LNPUBLIC NLS_put_term (BYTE far * far * ppString, const BYTE far * pCharacter, NLS_PINFO pInfo);
以下は、バッファ内のデータを文字単位かバイト単位かでサイズを算出します。LMBCS文字列は1文字当たりのバイト数が1〜4と可変なので、文字の区切りを
#include <nls.h>
NLS_STATUS LNPUBLIC NLS_string_chars (const BYTE far * pString, WORD NumBytes, WORD far * pNumChars, NLS_PINFO pInfo);
NLS_STATUS LNPUBLIC NLS_string_bytes (const BYTE far * pString, WORD NumChars, WORD far * pNumBytes, NLS_PINFO pInfo);
以下は、ある文字セットの文字列を、別の文字セットの文字列に変換します。変換元と変換先の文字セットは、LMBCS文字列(Lotus Multi Bytes Character Setの略で、Notes/Dominoの内部文字列の標準)、UNICODE(UTF-16)、プラットフォームデフォルトの3種類を設定できます。
#include <nls.h>
NLS_STATUS LNPUBLIC NLS_translate (BYTE far * pString, WORD Len, BYTE far * pStringTarget, WORD far * pSize, WORD ControlFlags, NLS_PINFO pInfo);
例えば、Notes C APIで受け取ったLMBCS文字列をUnicode系の文字列(例: std::wstring)で扱う場合、ヌル終端の有無、変換元と変換先の文字セットを第5引数のフラグに指定して、
NLS_STATUS status = NLS_translate(lmbcs, lmbcsLen, buffer, &bufferLen, NLS_NONULLTERMINATE | NLS_SOURCEISLMBCS | NLS_TARGETISUNICODE, pUnicodeInfo);
のようにします。
OSTranslate関数
Notes C APIには、この他にOSTranslateという関数もあり、歴史的にはこちらの方が古いと思います(NLS系はR5.0から)。
#include <osmisc.h>
WORD LNPUBLIC OSTranslate(WORD TranslateMode, const char far *In, WORD InLength, char far *Out, WORD OutLength);
NLS_translateと同等の機能を有していますが、UTF-8や大文字/小文字など変換可能な文字セットが少し多いのが特徴です。デメリットとして、処理結果(STATUS値)を返さなかったり、同じヘッダーファイルにマルチバイト文字の境界を知るすべがなかったりするので、この点でNLS系の関数を利用した方が有用だと思います。
LMBCSとC++文字列間の相互変換について
LMBCS文字列は、ASCII文字列であれば無変換で使用できますが、マルチバイト文字列の場合、独特のルールに基づいてエンコードされます。そのため、C++で日本語などのマルチバイト文字言語を扱う場合は、LMBCSからの変換、LMBCSへの変換は日常茶飯事になるので、きちんと押さえておく必要があります。
これまで、日本語文字コードについてはWindowsならShift JISやCP932、UNIXならEUC-JPなどに、プラットフォームを意識した変換をする必要がありました。しかし近年では、どのプラットフォームもUnicode(UTF-16)をデフォルトの文字コードにするようになってきているので、マルチプラットフォームを目指すならUTF-16を選択するのが賢明でしょう。