コメント - CLX C++ Libraries の動作確認 への対応.コメントで,以下のソースコードでうまく encode/decode されないと言う指摘がありました(ソースコードは若干改変).
#include <iostream> #include <string> #include "clx/uri.h" int main() { std::string dest = clx::uri::encode("http://日本語.com"); std::cout << "encode: " << dest << std::endl; std::cout << "decode: " << clx::uri::decode(dest) << std::endl; return 0; }
これを手元の環境(cygwin gcc 4.1.2, VC++ 8.0)で実行すると,以下のような結果が得られました.
encode: http://%ffffff93%fffffffa%ffffff96%7b%ffffff8c%ffffffea.com decode: http://ÿffff93ÿfffffaÿffff96{ÿffff8cÿffffea.com
所謂,符号拡張 に関連したバグのようです.ある文字の文字コードを出力する場合('A' ではなく '65' と出力する) iostream (多くの場合は stringstream)を利用することが多いのですが,<< 演算子にそのまま char 型の値を渡すと文字として出力されてしまうため,いったん int にキャストしてから << 演算子へ渡します.この際,元の文字が ASCII 文字コードに収まらない*1 ような値のときに int へキャストすると,符号拡張のため上位の領域がすべて 1 で埋められてしまうようです.
同様の問題は CLX C++ Libraries - hexdump でも発生していたのですが,こちらの方は未修正でした.対策としては,0xFF (キャスト元が char の場合)でマスクした後に出力すると言う方法を用いています.
蛇足
修正したコードを試していたところ,VC++ の方でコンパイルエラーが発生していました.どうやら,マスク用の値を作成するために numeric_limit<int>::max() を使用していたのが問題だったようです.
VCだと(少なくともVC8では)、std::numeric_limits<Type>::max() がマクロに潰されます。 #define max(a, b)
http://blogs.wankuma.com/ddnp/archive/2007/10/16/102248.aspx
対策としては,上記の記事にある通り VC++ の(_MSC_VER が定義されてある)場合,NOMINMAX を定義すると言う方法を取っています.
Reference
*1:0x7F よりも大きな値.例えば,2バイト文字など.