From 69373110a5708901801ebf2c7d2d4ee76754e866 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 2 Apr 2006 20:03:42 +0000 Subject: [PATCH] fixed wxMBConv_iconv to work with UTF-16/32 git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@38529 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/common/strconv.cpp | 51 ++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 14 deletions(-) diff --git a/src/common/strconv.cpp b/src/common/strconv.cpp index 00ab2fc8f5..1d702be11c 100644 --- a/src/common/strconv.cpp +++ b/src/common/strconv.cpp @@ -86,6 +86,15 @@ // 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; } -- 2.45.2