そんなわけで、長い間(といっても一週間くらい)悩んでいた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を設定するのですが、該当する文字コードが来たときにどうするかというのを設定します。
通常の数値は0x80までぽぽいとつっこんでしまって、いいとおもいます。
あと0x80以降は、エンコードで必要なバイト数をマイナスで突っ込むようです。
convertの中身がキモです。
多分シングルバイトの文字列はこないと思うのですが、一応チェックだけいれてます。
leadバイトとtrailバイトをあわせたコードがsjisになるので、それをUNICODEに変換します。
int unicode = expat->cp932.ConvertToUnicode(sjis);
まぁ、このコンバートするコードはうちが自前で作ったので、どう変換するかは任せます。
各自で用意してください。
んで、げっつしたunicodeの文字コードを返せば、convert関数の処理は終了です。
あとは、expatの方で勝手にutf8にして、XML_SetCharacterDataHandlerの第二引数に文字列ポインタを渡してくれます。
んあー。
わかったのはいいけど、しょんぼーりーだー。
さくさくsjisに変換してoutputするようにしちゃおう。
や、utf8のまま処理してもいいっちゃーいいんだけどー。