次に、状態依存のコード変換について説明します。先に説明したように、この型の変換は、日本語文字のJIS のような状態依存の複数バイト符号化と、 Unicode のようなワイド文字符号化の間で行います。一般に、外部デバイスは複数バイト符号化を使用し、内部処理ではワイド文字符号化を使用します。
状態依存のコード変換ファセットを実装し、使用するための手順は、次のとおりです。
次に、以上の手順の詳細を説明します。
複数バイトシーケンスを、状態依存の複数バイト符号化で構文解析したり作成するには、コード変換ファセットで変換状態を管理する必要があります。この状態は、デフォルトでは mbstate_t 型であり、C ライブラリで定義する実装依存の状態型です。この型で変換状態を追跡するのに不充分な場合は、ユーザー定義の変換状態型を作成してください。以下のコードはその定義方法を示したものですが、新しい状態型には、次のメンバー関数が必要なので注意してください。
次に、新しい変換状態型を示します。
class JISstate_t { public: JISstate_t( int state=0 ) : state_(state) { ; } JISstate_t(const JISstate_t& state) : state_(state.state_) { ; } JISstate_t& operator=(const JISstate_t& state) { if ( &state != this ) state_= state.state_; return *this; } JISstate_t& operator=(const int state) { state_= state; return *this; } bool operator==(const JISstate_t& state) const { return ( state_ == state.state_ ); } bool operator!=(const JISstate_t& state) const { return ( !(state_ == state.state_) ); } private: int state_; };
変換状態型は、 文字特性の一部です。そのため、新しい変換状態型では、新しい文字特性型が必要です。
標準以外で、移植性のないライブラリ機能を使用しない場合、新しい文字特性型を定義して、必要な型を定義しなおす必要があります。
struct JIS_char_traits: public char_traits<wchar_t> { typedef JISstate_t state_type; typedef fpos<state_type> pos_type; typedef wstreamoff off_type; };
最初の例と同様に、実際のコード変換ファセットを定義します。手順は、基本的に前と同様ですが、新しいコード変換型に新しいクラステンプレートを定義し、それを特殊化します。コードは次のようになります。
template <class internT, class externT, class stateT> class UnicodeJISConversion : public codecvt<internT, externT, stateT> { }; class UnicodeJISConversion<wchar_t, char, JISstate_t> : public codecvt<wchar_t, char, JISstate_t> { protected: result do_in(JISstate_t& state, const char* from, const char* from_end, const char*& from_next, wchar_t* to, wchar_t* to_limit, wchar_t*& to_next) const; result do_out(JISstate_t& state, const wchar_t* from, const wchar_t* from_end, const wchar_t*& from_next, char* to, char* to_limit, char*& to_next) const; bool do_always_noconv() const throw() { return false; }; int do_encoding() const throw(); { return -1; } };
この例では、関数 do_encoding() で コード変換が状態依存であることを表す -1 を返す必要があります。ここでも関数 in() と out() は、『標準 C++ クラスライブラリ・リファレンス』のクラス codecvt で説明しているエラー表示方式に沿って処理を行います。
非状態依存の変換を特徴付けているのは、in() と out() に対して変換状態引数を使用して、ファイルストリームバッファとコード変換ファセット間の通信に利用している点です。ファイルストリームバッファは、変換状態の作成、管理、削除を行います。最初に、ファイルストリームバッファでは、変換状態オブジェクトを作成します。これは、変換状態の初期状態を表し、それをコード変換ファセットに渡します。ファセットでは、実行する変換に合わせてそれを変更します。ファイルストリームバッファでは、続く 2 つのコード変換の間もそれを保存します。
次に、新しいコード変換ファセットの使用方法の例を示します。
typedef basic_fstream<wchar_t,JIS_char_traits> JIS_fstream; //1 JIS_fstream inout("/tmp/fil"); UnicodeJISConversion<wchar_t,char,JISstate_t> cvtfac; locale cvtloc(locale(),&cvtfac); inout.rdbuf()->pubimbue(cvtloc) //2 wcout << inout.rdbuf(); //3
//1 | Unicode-JIS コード変換では、デフォルトの型 mbstate_t ではない変換状態型を使用します。変換状態型は文字特性に含まれるので、新しいファイル型を作成する必要があります。JIS_char_traits の代わりに、文字特性テンプレートの特別な拡張機能を利用し、char_traits<wchar_t,JISstate_t> を使用しました。 |
//2 | ここで、ストリームバッファのロケールは、Unicode-JIS コード変換ファセットのある大域ロケールのコピーに置き換えられます。 |
//3 | JIS 符号化ファイル "/tmp/fil" が読み取られ、自動的に Unicode に変換され、wcout に書き込まれます。 |
Copyright (c) 1998, Rogue Wave Software, Inc.
このマニュアルに関する誤りのご指摘やご質問は、電子メールにてお送りください。
OEM リリース, 1998 年 6 月