diff options
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/string.cpp | 94 | ||||
-rw-r--r-- | src/util/string.h | 10 |
2 files changed, 103 insertions, 1 deletions
diff --git a/src/util/string.cpp b/src/util/string.cpp index 231eaf6be..49aff4a1f 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -29,9 +29,103 @@ with this program; if not, write to the Free Software Foundation, Inc., #include <iomanip> #include <map> +#ifndef _WIN32 +#include <iconv.h> +#else +#define _WIN32_WINNT 0x0501 +#include <windows.h> +#endif + static bool parseHexColorString(const std::string &value, video::SColor &color); static bool parseNamedColorString(const std::string &value, video::SColor &color); +#ifndef _WIN32 +size_t convert(const char *to, const char *from, char *outbuf, + size_t outbuf_size, char *inbuf, size_t inbuf_size) +{ + iconv_t cd = iconv_open(to, from); + +#if defined(__FreeBSD__) || defined(__FreeBSD) + const char *inbuf_ptr = inbuf; +#else + char *inbuf_ptr = inbuf; +#endif + + char *outbuf_ptr = outbuf; + + size_t *inbuf_left_ptr = &inbuf_size; + size_t *outbuf_left_ptr = &outbuf_size; + + while (inbuf_size > 0) + iconv(cd, &inbuf_ptr, inbuf_left_ptr, &outbuf_ptr, outbuf_left_ptr); + + iconv_close(cd); + return 0; +} + +std::wstring utf8_to_wide(const std::string &input) +{ + size_t inbuf_size = input.length() + 1; + // maximum possible size, every character is sizeof(wchar_t) bytes + size_t outbuf_size = (input.length() + 1) * sizeof(wchar_t); + + char *inbuf = new char[inbuf_size]; + memcpy(inbuf, input.c_str(), inbuf_size); + char *outbuf = new char[outbuf_size]; + memset(outbuf, 0, outbuf_size); + + convert("WCHAR_T", "UTF-8", outbuf, outbuf_size, inbuf, inbuf_size); + std::wstring out((wchar_t*)outbuf); + + delete[] inbuf; + delete[] outbuf; + + return out; +} + +std::string wide_to_utf8(const std::wstring &input) +{ + size_t inbuf_size = (input.length() + 1) * sizeof(wchar_t); + // maximum possible size: utf-8 encodes codepoints using 1 up to 6 bytes + size_t outbuf_size = (input.length() + 1) * 6; + + char *inbuf = new char[inbuf_size]; + memcpy(inbuf, input.c_str(), inbuf_size); + char *outbuf = new char[outbuf_size]; + memset(outbuf, 0, outbuf_size); + + convert("UTF-8", "WCHAR_T", outbuf, outbuf_size, inbuf, inbuf_size); + std::string out(outbuf); + + delete[] inbuf; + delete[] outbuf; + + return out; +} +#else +std::wstring utf8_to_wide(const std::string &input) +{ + size_t outbuf_size = input.size() + 1; + wchar_t *outbuf = new wchar_t[outbuf_size]; + memset(outbuf, 0, outbuf_size * sizeof(wchar_t)); + MultiByteToWideChar(CP_UTF8, 0, input.c_str(), input.size(), outbuf, outbuf_size); + std::wstring out(outbuf); + delete[] outbuf; + return out; +} + +std::string wide_to_utf8(const std::wstring &input) +{ + size_t outbuf_size = (input.size() + 1) * 6; + char *outbuf = new char[outbuf_size]; + memset(outbuf, 0, outbuf_size); + WideCharToMultiByte(CP_UTF8, 0, input.c_str(), input.size(), outbuf, outbuf_size, NULL, NULL); + std::string out(outbuf); + delete[] outbuf; + return out; +} +#endif + // You must free the returned string! // The returned string is allocated using new diff --git a/src/util/string.h b/src/util/string.h index b80e3c9a8..5bf2b5b7c 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -39,10 +39,18 @@ struct FlagDesc { u32 flag; }; +// try not to convert between wide/utf8 encodings; this can result in data loss +// try to only convert between them when you need to input/output stuff via Irrlicht +std::wstring utf8_to_wide(const std::string &input); +std::string wide_to_utf8(const std::wstring &input); + +// NEVER use those two functions unless you have a VERY GOOD reason to +// they just convert between wide and multibyte encoding +// multibyte encoding depends on current locale, this is no good, especially on Windows + // You must free the returned string! // The returned string is allocated using new wchar_t *narrow_to_wide_c(const char *str); - std::wstring narrow_to_wide(const std::string &mbs); std::string wide_to_narrow(const std::wstring &wcs); |