]> git.saurik.com Git - wxWidgets.git/commitdiff
fixed wxMBConv_iconv to work with UTF-16/32
authorVadim Zeitlin <vadim@wxwidgets.org>
Sun, 2 Apr 2006 20:03:42 +0000 (20:03 +0000)
committerVadim Zeitlin <vadim@wxwidgets.org>
Sun, 2 Apr 2006 20:03:42 +0000 (20:03 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@38529 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

src/common/strconv.cpp

index 00ab2fc8f51348f0d442a13e651583455fc91037..1d702be11c4236eac49e5f5947cf6db0c48e10fd 100644 (file)
 // implementation
 // ============================================================================
 
+// helper function of cMB2WC(): check if n bytes at this location are all NUL
+static bool NotAllNULs(const char *p, size_t n)
+{
+    while ( n && *p++ == '\0' )
+        n--;
+
+    return n != 0;
+}
+
 // ----------------------------------------------------------------------------
 // UTF-16 en/decoding to/from UCS-4
 // ----------------------------------------------------------------------------
@@ -187,15 +196,6 @@ const wxCharBuffer wxMBConv::cWC2MB(const wchar_t *pwz) const
     return buf;
 }
 
-// helper of cMB2WC(): check if n bytes at this location are all NUL
-static bool NotAllNULs(const char *p, size_t n)
-{
-    while ( n && *p++ == '\0' )
-        n--;
-
-    return n != 0;
-}
-
 const wxWCharBuffer
 wxMBConv::cMB2WC(const char *in, size_t inLen, size_t *outLen) const
 {
@@ -1540,6 +1540,31 @@ wxMBConv_iconv::~wxMBConv_iconv()
 
 size_t wxMBConv_iconv::MB2WC(wchar_t *buf, const char *psz, size_t n) const
 {
+    // find the string length: notice that must be done differently for
+    // NUL-terminated strings and UTF-16/32 which are terminated with 2/4 NULs
+    size_t inbuf;
+    const size_t nulLen = GetMinMBCharWidth();
+    switch ( nulLen )
+    {
+        default:
+            return (size_t)-1;
+
+        case 1:
+            inbuf = strlen(psz); // arguably more optimized than our version
+            break;
+
+        case 2:
+        case 4:
+            // for UTF-16/32 not only we need to have 2/4 consecutive NULs but
+            // they also have to start at character boundary and not span two
+            // adjacent characters
+            const char *p;
+            for ( p = psz; NotAllNULs(p, nulLen); p += nulLen )
+                ;
+            inbuf = p - psz;
+            break;
+    }
+
 #if wxUSE_THREADS
     // NB: iconv() is MT-safe, but each thread must use it's own iconv_t handle.
     //     Unfortunately there is a couple of global wxCSConv objects such as
@@ -1548,9 +1573,9 @@ size_t wxMBConv_iconv::MB2WC(wchar_t *buf, const char *psz, size_t n) const
     //     only a few wx classes would be safe to use from non-main threads
     //     as MB<->WC conversion would fail "randomly".
     wxMutexLocker lock(wxConstCast(this, wxMBConv_iconv)->m_iconvMutex);
-#endif
+#endif // wxUSE_THREADS
+
 
-    size_t inbuf = strlen(psz);
     size_t outbuf = n * SIZEOF_WCHAR_T;
     size_t res, cres;
     // VS: Use these instead of psz, buf because iconv() modifies its arguments:
@@ -1572,9 +1597,7 @@ size_t wxMBConv_iconv::MB2WC(wchar_t *buf, const char *psz, size_t n) const
                 buf[n] = WC_BSWAP(buf[i]);
         }
 
-        // NB: iconv was given only strlen(psz) characters on input, and so
-        //     it couldn't convert the trailing zero. Let's do it ourselves
-        //     if there's some room left for it in the output buffer.
+        // NUL-terminate the string if there is any space left
         if (res < n)
             buf[res] = 0;
     }