2008年11月8日土曜日

utf8の扱い

Coyoliteさんが書いたUTF-8Nを吐くワイドストリーム の逆バージョンを試してみたくて、書いてみました。
これ、標準で欲しいです。一応 utf8_codecvt_facet.hpp, utf8_codecvt_facet.cpp を作成して、使います。namespace boost::detail は、ちょっといただけないかもしれませんが、そこはご愛嬌。
// utf8_codecvt_facet.hpp
#ifndef BOOST_DETAIL_UTF8_CODECVT_FACET_HPP
#define BOOST_DETAIL_UTF8_CODECVT_FACET_HPP

#define BOOST_UTF8_BEGIN_NAMESPACE \
namespace boost { namespace detail {
#define BOOST_UTF8_DECL
#define BOOST_UTF8_END_NAMESPACE }}

#include <boost/detail/utf8_codecvt_facet.hpp>

#undef BOOST_UTF8_END_NAMESPACE
#undef BOOST_UTF8_DECL
#undef BOOST_UTF8_BEGIN_NAMESPACE

#endif // BOOST_DETAIL_UTF8_CODECVT_FACET_HPP


// utf8_codecvt_facet.cpp
#include <boost/config.hpp>
#ifdef BOOST_NO_STD_WSTREAMBUF
#error "wide char i/o not supported on this platform"
#else

#define BOOST_UTF8_BEGIN_NAMESPACE \
namespace boost { namespace detail {
#define BOOST_UTF8_DECL
#define BOOST_UTF8_END_NAMESPACE }}
#include <libs/detail/utf8_codecvt_facet.cpp>
#undef BOOST_UTF8_END_NAMESPACE
#undef BOOST_UTF8_DECL
#undef BOOST_UTF8_BEGIN_NAMESPACE

#endif // BOOST_NO_STD_WSTREAMBUF


#include <iostream>
#include <fstream>
#include <string>
#include "utf8_codecvt_facet.hpp"

int main() {
std::locale::global( std::locale("") );
std::wifstream ifs( "x.txt" );
ifs.imbue( std::locale(ifs.getloc(), new boost::detail::utf8_codecvt_facet ) );
while( ifs.good() ) {
std::wstring wstr;
std::getline( ifs, wstr );
std::wcout << wstr << std::endl;
}
}

ほんとは、char型のバッファに読み込まれてしまった utf8のコードに対して変換をかけたいのだが、めんどくさそうだ。
標準機能として、トラックバック機能が無いのは超めんどくさい

2011/07/07 追記: error C2661: 'std::locale::facet::operator new' というエラーになるのは、MFC のデバッグバージョン用 new が原因である。正直、この DEBUG_NEW 鬱陶しい。

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

0 件のコメント: