次に、状態依存のコード変換について説明します。先に説明したように、この型の変換は、日本語文字の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 月