expatのXML_SetUnknownEncodingHandlerとは。
2006 年 11 月 12 日
コメントはありません
そんなわけで、長い間(といっても一週間くらい)悩んでいた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のまま処理してもいいっちゃーいいんだけどー。
カテゴリー: 開発
最近のコメント