Reduce gettext wide/narrow and string/char* conversions
[oweals/minetest.git] / src / util / string.cpp
index 1d95606081220c0df8daee9770f1d26ddc84aa22..b4908d62d71ac16cccde4028c9b267a615a2b3de 100644 (file)
@@ -32,6 +32,10 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 #include <iomanip>
 #include <map>
 
+#if defined(_WIN32)
+#include <windows.h>  // MultiByteToWideChar
+#endif
+
 static bool parseHexColorString(const std::string &value, video::SColor &color);
 static bool parseNamedColorString(const std::string &value, video::SColor &color);
 
@@ -58,51 +62,72 @@ int wctomb(char *s, wchar_t wc)
 
 int mbtowc(wchar_t *pwc, const char *s, size_t n)
 {
-       std::wstring intermediate = narrow_to_wide(s);
+       wchar_t *intermediate = narrow_to_wide(s);
 
        if (intermediate.length() > 0) {
                *pwc = intermediate[0];
                return 1;
-       }
-       else {
+       } else {
                return -1;
        }
 }
+// You must free the returned string!
+const wchar_t *narrow_to_wide_c(const char *mbs)
+{
+       size_t mbl = strlen(mbs);
+       wchar_t wcs = new wchar_t[mbl + 1];
 
-std::wstring narrow_to_wide(const std::string& mbs) {
-       size_t wcl = mbs.size();
-
-       std::wstring retval = L"";
-
-       for (unsigned int i = 0; i < wcl; i++) {
-               if (((unsigned char) mbs[i] >31) &&
-                ((unsigned char) mbs[i] < 127)) {
-
-                       retval += wide_chars[(unsigned char) mbs[i] -32];
+       for (size_t i = 0; i < mbl; i++) {
+               if (((unsigned char) mbs[i] > 31) &&
+                               ((unsigned char) mbs[i] < 127)) {
+                       wcs[i] = wide_chars[(unsigned char) mbs[i] - 32];
                }
                //handle newline
                else if (mbs[i] == '\n') {
-                       retval += L'\n';
+                       wcs[i] = L'\n';
                }
        }
 
-       return retval;
+       return wcs;
 }
+
 #else
 
-std::wstring narrow_to_wide(const std::string& mbs)
+// You must free the returned string!
+const wchar_t *narrow_to_wide_c(const char *mbs)
 {
-       size_t wcl = mbs.size();
-       Buffer<wchar_t> wcs(wcl+1);
-       size_t l = mbstowcs(*wcs, mbs.c_str(), wcl);
-       if(l == (size_t)(-1))
-               return L"<invalid multibyte string>";
-       wcs[l] = 0;
-       return *wcs;
+       wchar_t *wcs = NULL;
+#if defined(_WIN32)
+       int wcl = MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) mbs, -1, NULL, 0);
+       if (!wcl)
+               return NULL;
+       wcs = new wchar_t[wcl];
+       MultiByteToWideChar(CP_UTF8, 0, (LPCSTR) mbs, -1, (WCHAR *) wcs, wcl);
+#else
+       size_t wcl = mbstowcs(NULL, mbs, 0);
+       if (wcl == (size_t) -1)
+               return NULL;
+       wcs = new wchar_t[wcl + 1];
+       size_t l = mbstowcs(wcs, mbs, wcl);
+       assert(l != (size_t) -1); // Should never happen if the last call worked
+       wcs[l] = '\0';
+#endif
+
+       return wcs;
 }
 
 #endif
 
+std::wstring narrow_to_wide(const std::string& mbs)
+{
+       const wchar_t *wcs = narrow_to_wide_c(mbs.c_str());
+       if (!wcs)
+               return L"<invalid multibyte string>";
+       std::wstring wstr(wcs);
+       delete [] wcs;
+       return wstr;
+}
+
 #ifdef __ANDROID__
 std::string wide_to_narrow(const std::wstring& wcs) {
        size_t mbl = wcs.size()*4;