アーカイブ

2006 年 11 月 12 日 のアーカイブ

expatのXML_SetUnknownEncodingHandlerとは。

2006 年 11 月 12 日 leiya コメントはありません

そんなわけで、長い間(といっても一週間くらい)悩んでいたXML_SetUnknownEncodingHandlerの正体がわかりました。
結局、中のソースコードを追いかけて、どういう処理をしているかと調べないとわかりませんでした。

結論から先にいうと、expatはutf-8で出力するようにできていて、知らないエンコード→utf8をするのが、XML_SetUnknownEncodingHandlerらしいです。
出力の部分を変えれるのかまではわからんので、今のところ結論はそんな感じ。

cp932→UNICODE→utf-8という流れになっていて、これじゃあ、うちがやりたいこととはまるで真逆のことですぜ旦那って感じorz
cp932をそのまま出力したいから、エンコードをcp932にして、読み込んで、しらんエンコードだから、文字列の解釈はよろしく頼むぜだと思ったんですけどね。

ハンドラの中身。

static int convert(void* data, const char* s)
{
    TExpat *expat = static_cast<texpat *>(data);
    unsigned char lead = s[0];
    
    if (_ismbblead(lead) == 0) {
        //シングルバイト
        return lead;
    }

    unsigned char trail = s[1];

    int sjis =  (lead < < 8) | trail;

    int unicode = expat->cp932.ConvertToUnicode(sjis);

    //マルチバイト
    return unicode;
} 

int XMLCALL TExpat::UnknownEncodingCallback(void *handle_data, const XML_Char *name, XML_Encoding *info) {
    TExpat *expat = static_cast</texpat><texpat *>(handle_data);

    for (int i = 0; i < 128; i++) {
        info->map[i] = i;
    }
    for (int i = 128; i < 256; i++) {
        info->map[i] = -2;
    }

    info->convert = convert;
    info->data = handle_data;

    return XML_STATUS_OK;
}



まずmapを設定するのですが、該当する文字コードが来たときにどうするかというのを設定します。
通常の数値は0×80までぽぽいとつっこんでしまって、いいとおもいます。
あと0×80以降は、エンコードで必要なバイト数をマイナスで突っ込むようです。

convertの中身がキモです。
多分シングルバイトの文字列はこないと思うのですが、一応チェックだけいれてます。
leadバイトとtrailバイトをあわせたコードがsjisになるので、それをUNICODEに変換します。

int unicode = expat->cp932.ConvertToUnicode(sjis);

まぁ、このコンバートするコードはうちが自前で作ったので、どう変換するかは任せます。
各自で用意してください。
んで、げっつしたunicodeの文字コードを返せば、convert関数の処理は終了です。

あとは、expatの方で勝手にutf8にして、XML_SetCharacterDataHandlerの第二引数に文字列ポインタを渡してくれます。

んあー。
わかったのはいいけど、しょんぼーりーだー。

さくさくsjisに変換してoutputするようにしちゃおう。
や、utf8のまま処理してもいいっちゃーいいんだけどー。

カテゴリー: 開発 タグ: