Rogue Wave バナー
前へマニュアルの先頭へ目次次へ

19.4 例 2: 複数バイト文字コード変換の定義 (JIS <-> Unicode)

次に、状態依存のコード変換について説明します。先に説明したように、この型の変換は、日本語文字のJIS のような状態依存の複数バイト符号化と、 Unicode のようなワイド文字符号化の間で行います。一般に、外部デバイスは複数バイト符号化を使用し、内部処理ではワイド文字符号化を使用します。

状態依存のコード変換ファセットを実装し、使用するための手順は、次のとおりです。

  1. 必要に応じて新しい変換状態型を定義します。

  2. 必要に応じて新しい文字の特性型を定義します。または、新しい状態型で文字特性テンプレートのインスタンスを生成します。

  3. コード変換ファセットを定義します。

  4. 新しい文字の特性型を利用して、新しいストリーム型のインスタンスを生成します。

  5. 新しいコード変換ファセットを持ったロケールに、ファイルストリームのバッファを組み込みます。

次に、以上の手順の詳細を説明します。

19.4.1 新しい変換状態型の定義

複数バイトシーケンスを、状態依存の複数バイト符号化で構文解析したり作成するには、コード変換ファセットで変換状態を管理する必要があります。この状態は、デフォルトでは 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_;
 
                 };

19.4.2 新しい文字特性型の定義

変換状態型は、 文字特性の一部です。そのため、新しい変換状態型では、新しい文字特性型が必要です。

標準以外で、移植性のないライブラリ機能を使用しない場合、新しい文字特性型を定義して、必要な型を定義しなおす必要があります。

struct JIS_char_traits: public char_traits<wchar_t> 
{
        typedef JISstate_t                state_type;
        typedef fpos<state_type>          pos_type;
        typedef wstreamoff                off_type;
};

19.4.3 コード変換ファセットの定義

最初の例と同様に、実際のコード変換ファセットを定義します。手順は、基本的に前と同様ですが、新しいコード変換型に新しいクラステンプレートを定義し、それを特殊化します。コードは次のようになります。

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 つのコード変換の間もそれを保存します。

19.4.4 新しいコード変換ファセットの使用

次に、新しいコード変換ファセットの使用方法の例を示します。

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 月