diff --git a/src/utf8.cpp b/src/utf8.cpp index 00d557110..9fb6845d5 100644 --- a/src/utf8.cpp +++ b/src/utf8.cpp @@ -40,67 +40,124 @@ POSSIBILITY OF SUCH DAMAGE. namespace libtorrent { - utf8_conv_result_t utf8_wchar(const std::string &utf8, std::wstring &wide) + namespace + { + // ==== utf-8 -> wide === + template + struct convert_to_wide + { + static utf8_conv_result_t convert(UTF8 const** src_start + , UTF8 const* src_end + , std::wstring& wide) + { + return source_illegal; + } + }; + + // ==== utf-8 -> utf-32 === + template<> + struct convert_to_wide<4> + { + static utf8_conv_result_t convert(char const** src_start + , char const* src_end + , std::wstring& wide) + { + wchar_t const* dst_start = wide.c_str(); + int ret = ConvertUTF8toUTF32((UTF8 const**)src_start + , (UTF8 const*)src_end + , (UTF32**)&dst_start, (UTF32*)dst_start + wide.size() + , lenientConversion); + wide.resize(dst_start - wide.c_str()); + return (utf8_conv_result_t)ret; + } + }; + + // ==== utf-8 -> utf-16 === + template<> + struct convert_to_wide<2> + { + static utf8_conv_result_t convert(char const** src_start + , char const* src_end + , std::wstring& wide) + { + wchar_t const* dst_start = wide.c_str(); + int ret = ConvertUTF8toUTF16((UTF8 const**)src_start + , (UTF8 const*)src_end + , (UTF16**)&dst_start, (UTF16*)dst_start + wide.size() + , lenientConversion); + wide.resize(dst_start - wide.c_str()); + return (utf8_conv_result_t)ret; + } + }; + + // ==== wide -> utf-8 === + template + struct convert_from_wide + { + static utf8_conv_result_t convert(wchar_t const** src_start + , wchar_t const* src_end + , std::string& utf8) + { + return source_illegal; + } + }; + + // ==== utf-32 -> utf-8 === + template<> + struct convert_from_wide<4> + { + static utf8_conv_result_t convert(wchar_t const** src_start + , wchar_t const* src_end + , std::string& utf8) + { + char const* dst_start = utf8.c_str(); + int ret = ConvertUTF32toUTF8((UTF32 const**)src_start + , (UTF32 const*)src_end, (UTF8**)&dst_start + , (UTF8*)dst_start + utf8.size() + , lenientConversion); + utf8.resize(dst_start - &utf8[0]); + return (utf8_conv_result_t)ret; + } + }; + + // ==== utf-16 -> utf-8 === + template<> + struct convert_from_wide<2> + { + static utf8_conv_result_t convert(wchar_t const** src_start + , wchar_t const* src_end + , std::string& utf8) + { + char const* dst_start = utf8.c_str(); + int ret = ConvertUTF16toUTF8((UTF16 const**)src_start + , (UTF16 const*)src_end, (UTF8**)&dst_start + , (UTF8*)dst_start + utf8.size() + , lenientConversion); + utf8.resize(dst_start - &utf8[0]); + return (utf8_conv_result_t)ret; + } + }; + } // anonymous namespace + + utf8_conv_result_t utf8_wchar(std::string const& utf8, std::wstring &wide) { // allocate space for worst-case wide.resize(utf8.size()); wchar_t const* dst_start = wide.c_str(); char const* src_start = utf8.c_str(); - ConversionResult ret; - // TODO: 3 refactor this to use wchar_t as a template - // it would cause less code to be generated without - // relying on dead-code elimination and fix msvc constant - // expression warning - if (sizeof(wchar_t) == sizeof(UTF32)) - { - ret = ConvertUTF8toUTF32((const UTF8**)&src_start, (const UTF8*)src_start - + utf8.size(), (UTF32**)&dst_start, (UTF32*)dst_start + wide.size() - , lenientConversion); - wide.resize(dst_start - wide.c_str()); - return (utf8_conv_result_t)ret; - } - else if (sizeof(wchar_t) == sizeof(UTF16)) - { - ret = ConvertUTF8toUTF16((const UTF8**)&src_start, (const UTF8*)src_start - + utf8.size(), (UTF16**)&dst_start, (UTF16*)dst_start + wide.size() - , lenientConversion); - wide.resize(dst_start - wide.c_str()); - return (utf8_conv_result_t)ret; - } - else - { - return source_illegal; - } + return convert_to_wide::convert( + &src_start, src_start + utf8.size(), wide); } - utf8_conv_result_t wchar_utf8(const std::wstring &wide, std::string &utf8) + utf8_conv_result_t wchar_utf8(std::wstring const& wide, std::string &utf8) { // allocate space for worst-case utf8.resize(wide.size() * 6); if (wide.empty()) return conversion_ok; char* dst_start = &utf8[0]; wchar_t const* src_start = wide.c_str(); - ConversionResult ret; - if (sizeof(wchar_t) == sizeof(UTF32)) - { - ret = ConvertUTF32toUTF8((const UTF32**)&src_start, (const UTF32*)src_start - + wide.size(), (UTF8**)&dst_start, (UTF8*)dst_start + utf8.size() - , lenientConversion); - utf8.resize(dst_start - &utf8[0]); - return (utf8_conv_result_t)ret; - } - else if (sizeof(wchar_t) == sizeof(UTF16)) - { - ret = ConvertUTF16toUTF8((const UTF16**)&src_start, (const UTF16*)src_start - + wide.size(), (UTF8**)&dst_start, (UTF8*)dst_start + utf8.size() - , lenientConversion); - utf8.resize(dst_start - &utf8[0]); - return (utf8_conv_result_t)ret; - } - else - { - return source_illegal; - } + return convert_from_wide::convert( + &src_start, src_start + wide.size(), utf8); } }