From: <man...@us...> - 2013-09-07 13:53:40
|
Revision: 2651 http://sourceforge.net/p/modplug/code/2651 Author: manxorist Date: 2013-09-07 13:53:32 +0000 (Sat, 07 Sep 2013) Log Message: ----------- [Ref] Move charset conversion functions to common/mptString, so that they could also be used by tracker code. Modified Paths: -------------- trunk/OpenMPT/common/mptString.cpp trunk/OpenMPT/common/mptString.h trunk/OpenMPT/libopenmpt/libopenmpt_impl.cpp Modified: trunk/OpenMPT/common/mptString.cpp =================================================================== --- trunk/OpenMPT/common/mptString.cpp 2013-09-07 13:24:00 UTC (rev 2650) +++ trunk/OpenMPT/common/mptString.cpp 2013-09-07 13:53:32 UTC (rev 2651) @@ -13,7 +13,11 @@ #include <vector> #include <cstdarg> +#if !defined(WIN32) +#include <iconv.h> +#endif // !WIN32 + namespace mpt { namespace String { @@ -44,4 +48,131 @@ } +#if defined(WIN32) +static UINT CharsetToCodepage(Charset charset) +{ + switch(charset) + { + case CharsetLocale: return CP_ACP; break; + case CharsetUTF8: return CP_UTF8; break; + case CharsetUS_ASCII: return 20127; break; + case CharsetISO8859_1: return 28591; break; + case CharsetISO8859_15: return 28605; break; + case CharsetCP437: return 437; break; + case CharsetWindows1252: return 1252; break; + } + return 0; +} +#else // !WIN32 +static const char * CharsetToString(Charset charset) +{ + switch(charset) + { + case CharsetLocale: return "char"; break; + case CharsetUTF8: return "UTF-8"; break; + case CharsetUS_ASCII: return "ASCII"; break; + case CharsetISO8859_1: return "ISO-8859-1"; break; + case CharsetISO8859_15: return "ISO-8859-15"; break; + case CharsetCP437: return "CP437"; break; + case CharsetWindows1252: return "CP1252"; break; + } + return 0; +} +#endif // WIN32 + + +std::string Encode(const std::wstring &src, Charset charset) +{ + #if defined(WIN32) + const UINT codepage = CharsetToCodepage(charset); + int required_size = WideCharToMultiByte(codepage, 0, src.c_str(), -1, nullptr, 0, nullptr, nullptr); + if(required_size <= 0) + { + return std::string(); + } + std::vector<CHAR> encoded_string(required_size); + WideCharToMultiByte(codepage, 0, src.c_str(), -1, &encoded_string[0], encoded_string.size(), nullptr, nullptr); + return &encoded_string[0]; + #else // !WIN32 + iconv_t conv = iconv_t(); + conv = iconv_open(CharsetToString(charset), "wchar_t"); + std::vector<wchar_t> wide_string(src.c_str(), src.c_str() + src.length() + 1); + std::vector<char> encoded_string(wide_string.size() * 8); // large enough + char * inbuf = (char*)&wide_string[0]; + size_t inbytesleft = wide_string.size() * sizeof(wchar_t); + char * outbuf = &encoded_string[0]; + size_t outbytesleft = encoded_string.size(); + if(iconv(conv, &inbuf, &inbytesleft, &outbuf, &outbytesleft) == (size_t)-1) + { + iconv_close(conv); + conv = iconv_t(); + return std::string(); + } + iconv_close(conv); + conv = iconv_t(); + return &encoded_string[0]; + #endif // WIN32 +} + + +std::wstring Decode(const std::string &src, Charset charset) +{ + #if defined(WIN32) + const UINT codepage = CharsetToCodepage(charset); + int required_size = MultiByteToWideChar(codepage, 0, src.c_str(), -1, nullptr, 0); + if(required_size <= 0) + { + return std::wstring(); + } + std::vector<WCHAR> decoded_string(required_size); + MultiByteToWideChar(codepage, 0, src.c_str(), -1, &decoded_string[0], decoded_string.size()); + return &decoded_string[0]; + #else // !WIN32 + iconv_t conv = iconv_t(); + conv = iconv_open("wchar_t", CharsetToString(charset)); + std::vector<char> encoded_string(src.c_str(), src.c_str() + src.length() + 1); + std::vector<wchar_t> wide_string(encoded_string.size() * 8); // large enough + char * inbuf = &encoded_string[0]; + size_t inbytesleft = encoded_string.size(); + char * outbuf = (char*)&wide_string[0]; + size_t outbytesleft = wide_string.size() * sizeof(wchar_t); + if(iconv(conv, &inbuf, &inbytesleft, &outbuf, &outbytesleft) == (size_t)-1) + { + iconv_close(conv); + conv = iconv_t(); + return std::wstring(); + } + iconv_close(conv); + conv = iconv_t(); + return &wide_string[0]; + #endif // WIN32 +} + + +std::string Convert(const std::string &src, Charset from, Charset to) +{ + #if defined(WIN32) + return Encode(Decode(src, from), to); + #else // !WIN32 + iconv_t conv = iconv_t(); + conv = iconv_open(CharsetToString(to), CharsetToString(from)); + std::vector<char> src_string(src.c_str(), src.c_str() + src.length() + 1); + std::vector<char> dst_string(src_string.size() * 8); // large enough + char * inbuf = &src_string[0]; + size_t inbytesleft = src_string.size(); + char * outbuf = &dst_string[0]; + size_t outbytesleft = dst_string.size(); + if(iconv(conv, &inbuf, &inbytesleft, &outbuf, &outbytesleft) == (size_t)-1) + { + iconv_close(conv); + conv = iconv_t(); + return std::string(); + } + iconv_close(conv); + conv = iconv_t(); + return &dst_string[0]; + #endif // WIN32 +} + + } } // namespace mpt::String Modified: trunk/OpenMPT/common/mptString.h =================================================================== --- trunk/OpenMPT/common/mptString.h 2013-09-07 13:24:00 UTC (rev 2650) +++ trunk/OpenMPT/common/mptString.h 2013-09-07 13:53:32 UTC (rev 2651) @@ -134,6 +134,32 @@ } +enum Charset { + CharsetLocale, + + CharsetUTF8, + + CharsetUS_ASCII, + + CharsetISO8859_1, + CharsetISO8859_15, + + CharsetCP437, + + CharsetWindows1252, +}; + + +namespace String { + +std::string Encode(const std::wstring &src, Charset charset); +std::wstring Decode(const std::string &src, Charset charset); + +std::string Convert(const std::string &src, Charset from, Charset to); + +} // namespace String + + } // namespace mpt Modified: trunk/OpenMPT/libopenmpt/libopenmpt_impl.cpp =================================================================== --- trunk/OpenMPT/libopenmpt/libopenmpt_impl.cpp 2013-09-07 13:24:00 UTC (rev 2650) +++ trunk/OpenMPT/libopenmpt/libopenmpt_impl.cpp 2013-09-07 13:53:32 UTC (rev 2651) @@ -22,10 +22,6 @@ #include <cstdlib> #include <cstring> -#if !defined(WIN32) -#include <iconv.h> -#endif // !WIN32 - #include "soundlib/Sndfile.h" #include "soundlib/AudioReadTarget.h" #include "soundlib/FileReader.h" @@ -154,58 +150,19 @@ } std::string module_impl::mod_string_to_utf8( const std::string & encoded ) const { - std::string charset = m_sndFile->GetCharset().second; - #if defined(WIN32) - std::transform( charset.begin(), charset.end(), charset.begin(), tolower ); - UINT codepage = 0; - if ( charset == "" ) { - codepage = 20127; // us ascii fallback - } else if ( charset == "windows-1252" ) { - codepage = 1252; - } else if ( charset == "iso-8859-1" ) { - codepage = 28591; - } else if ( charset == "utf-8" ) { - codepage = 65001; - } else if ( charset == "us-ascii" ) { - codepage = 20127; - } else if ( charset == "cp437" ) { - codepage = 437; - } else { - codepage = 20127; // us ascii fallback - } - int required_size = 0; - required_size = MultiByteToWideChar( codepage, 0, encoded.c_str(), -1, NULL, 0 ); - if ( required_size <= 0 ) { - return std::string(); - } - std::vector<WCHAR> unicode_string( required_size ); - MultiByteToWideChar( codepage, 0, encoded.data(), -1, &unicode_string[0], unicode_string.size() ); - required_size = WideCharToMultiByte( CP_UTF8, 0, &unicode_string[0], -1, NULL, 0, NULL, NULL ); - if ( required_size <= 0 ) { - return std::string(); - } - std::vector<CHAR> utf8_string( required_size ); - WideCharToMultiByte( CP_UTF8, 0, &unicode_string[0], -1, &utf8_string[0], utf8_string.size(), NULL, NULL ); - return &utf8_string[0]; - #else - iconv_t conv = iconv_t(); - conv = iconv_open( "UTF-8", charset.c_str() ); - std::vector<char> encoded_string( encoded.c_str(), encoded.c_str() + encoded.length() + 1 ); - std::vector<char> utf8_string( encoded_string.size() * 8 ); // large enough - char * inbuf = &encoded_string[0]; - size_t inbytesleft = encoded_string.size(); - char * outbuf = &utf8_string[0]; - size_t outbytesleft = utf8_string.size(); - if ( iconv( conv, &inbuf, &inbytesleft, &outbuf, &outbytesleft ) == (size_t)-1 ) { - iconv_close( conv ); - conv = iconv_t(); - return std::string(); - } - std::string result = &utf8_string[0]; - iconv_close( conv ); - conv = iconv_t(); - return result; - #endif + std::string encoding = m_sndFile->GetCharset().second; + std::transform( encoding.begin(), encoding.end(), encoding.begin(), tolower ); + mpt::Charset charset = mpt::CharsetUS_ASCII; + if ( encoding == "" ) { charset = mpt::CharsetUS_ASCII; } // fallback + else if ( encoding == "utf-8" ) { charset = mpt::CharsetUTF8; } + else if ( encoding == "ascii" ) { charset = mpt::CharsetUS_ASCII; } + else if ( encoding == "us-ascii" ) { charset = mpt::CharsetUS_ASCII; } + else if ( encoding == "iso-8859-1" ) { charset = mpt::CharsetISO8859_1; } + else if ( encoding == "iso-8859-15" ) { charset = mpt::CharsetISO8859_15; } + else if ( encoding == "cp437" ) { charset = mpt::CharsetCP437; } + else if ( encoding == "windows-1252" ) { charset = mpt::CharsetWindows1252; } + else { charset = mpt::CharsetUS_ASCII; } // fallback + return mpt::String::Convert( encoded, charset, mpt::CharsetUTF8 ); } void module_impl::apply_mixer_settings( std::int32_t samplerate, int channels ) { if ( This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |