]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/strconv.cpp
simplify code so it always returns the same object
[wxWidgets.git] / src / common / strconv.cpp
index 599048e9e212ca34ca3808274d9a771af780d2e2..54df1ff70ab2a94495b1257ca22c6a848b94185f 100644 (file)
@@ -28,8 +28,6 @@
 
 #include "wx/strconv.h"
 
-#if wxUSE_WCHAR_T
-
 #ifndef __WXWINCE__
 #include <errno.h>
 #endif
@@ -539,7 +537,7 @@ const wxWCharBuffer wxMBConv::cMB2WC(const wxScopedCharBuffer& buf) const
         }
     }
 
-    return wxWCharBuffer();
+    return wxScopedWCharBuffer::CreateNonOwned(L"", 0);
 }
 
 const wxCharBuffer wxMBConv::cWC2MB(const wxScopedWCharBuffer& wbuf) const
@@ -557,7 +555,7 @@ const wxCharBuffer wxMBConv::cWC2MB(const wxScopedWCharBuffer& wbuf) const
         }
     }
 
-    return wxCharBuffer();
+    return wxScopedCharBuffer::CreateNonOwned("", 0);
 }
 
 // ----------------------------------------------------------------------------
@@ -997,7 +995,7 @@ wxMBConvStrictUTF8::ToWChar(wchar_t *dst, size_t dstLen,
 
     for ( const char *p = src; ; p++ )
     {
-        if ( !(srcLen == wxNO_LEN ? *p : srcLen) )
+        if ( (srcLen == wxNO_LEN ? !*p : !srcLen) )
         {
             // all done successfully, just add the trailing NULL if we are not
             // using explicit length
@@ -1117,7 +1115,7 @@ wxMBConvStrictUTF8::FromWChar(char *dst, size_t dstLen,
 
     for ( const wchar_t *wp = src; ; wp++ )
     {
-        if ( !(srcLen == wxNO_LEN ? *wp : srcLen) )
+        if ( (srcLen == wxNO_LEN ? !*wp : !srcLen) )
         {
             // all done successfully, just add the trailing NULL if we are not
             // using explicit length
@@ -1147,6 +1145,8 @@ wxMBConvStrictUTF8::FromWChar(char *dst, size_t dstLen,
         {
             // skip the next char too as we decoded a surrogate
             wp++;
+            if ( srcLen != wxNO_LEN )
+                srcLen--;
         }
 #else // wchar_t is UTF-32
         code = *wp & 0x7fffffff;
@@ -1232,7 +1232,10 @@ size_t wxMBConvUTF8::ToWChar(wchar_t *buf, size_t n,
 
     size_t len = 0;
 
-    while ((srcLen == wxNO_LEN ? *psz : srcLen--) && ((!buf) || (len < n)))
+    // The length can be either given explicitly or computed implicitly for the
+    // NUL-terminated strings.
+    const bool isNulTerminated = srcLen == wxNO_LEN;
+    while ((isNulTerminated ? *psz : srcLen--) && ((!buf) || (len < n)))
     {
         const char *opsz = psz;
         bool invalid = false;
@@ -1366,10 +1369,17 @@ size_t wxMBConvUTF8::ToWChar(wchar_t *buf, size_t n,
         }
     }
 
-    if (srcLen == wxNO_LEN && buf && (len < n))
-        *buf = 0;
+    if ( isNulTerminated )
+    {
+        // Add the trailing NUL in this case if we have a large enough buffer.
+        if ( buf && (len < n) )
+            *buf = 0;
+
+        // And count it in any case.
+        len++;
+    }
 
-    return len + 1;
+    return len;
 }
 
 static inline bool isoctal(wchar_t wch)
@@ -1385,7 +1395,10 @@ size_t wxMBConvUTF8::FromWChar(char *buf, size_t n,
 
     size_t len = 0;
 
-    while ((srcLen == wxNO_LEN ? *psz : srcLen--) && ((!buf) || (len < n)))
+    // The length can be either given explicitly or computed implicitly for the
+    // NUL-terminated strings.
+    const bool isNulTerminated = srcLen == wxNO_LEN;
+    while ((isNulTerminated ? *psz : srcLen--) && ((!buf) || (len < n)))
     {
         wxUint32 cc;
 
@@ -1453,10 +1466,17 @@ size_t wxMBConvUTF8::FromWChar(char *buf, size_t n,
         }
     }
 
-    if (srcLen == wxNO_LEN && buf && (len < n))
-        *buf = 0;
+    if ( isNulTerminated )
+    {
+        // Add the trailing NUL in this case if we have a large enough buffer.
+        if ( buf && (len < n) )
+            *buf = 0;
 
-    return len + 1;
+        // And count it in any case.
+        len++;
+    }
+
+    return len;
 }
 
 // ============================================================================
@@ -1647,7 +1667,7 @@ wxMBConvUTF16straight::FromWChar(char *dst, size_t dstLen,
     wxUint16 *outBuff = reinterpret_cast<wxUint16 *>(dst);
     for ( size_t n = 0; n < srcLen; n++ )
     {
-        wxUint16 cc[2];
+        wxUint16 cc[2] = { 0 };
         const size_t numChars = encode_utf16(*src++, cc);
         if ( numChars == wxCONV_FAILED )
             return wxCONV_FAILED;
@@ -1730,7 +1750,7 @@ wxMBConvUTF16swap::FromWChar(char *dst, size_t dstLen,
     wxUint16 *outBuff = reinterpret_cast<wxUint16 *>(dst);
     for ( const wchar_t *srcEnd = src + srcLen; src < srcEnd; src++ )
     {
-        wxUint16 cc[2];
+        wxUint16 cc[2] = { 0 };
         const size_t numChars = encode_utf16(*src, cc);
         if ( numChars == wxCONV_FAILED )
             return wxCONV_FAILED;
@@ -1814,7 +1834,7 @@ wxMBConvUTF32straight::ToWChar(wchar_t *dst, size_t dstLen,
     size_t outLen = 0;
     for ( size_t n = 0; n < inLen; n++ )
     {
-        wxUint16 cc[2];
+        wxUint16 cc[2] = { 0 };
         const size_t numChars = encode_utf16(*inBuff++, cc);
         if ( numChars == wxCONV_FAILED )
             return wxCONV_FAILED;
@@ -1892,7 +1912,7 @@ wxMBConvUTF32swap::ToWChar(wchar_t *dst, size_t dstLen,
     size_t outLen = 0;
     for ( size_t n = 0; n < inLen; n++, inBuff++ )
     {
-        wxUint16 cc[2];
+        wxUint16 cc[2] = { 0 };
         const size_t numChars = encode_utf16(wxUINT32_SWAP_ALWAYS(*inBuff), cc);
         if ( numChars == wxCONV_FAILED )
             return wxCONV_FAILED;
@@ -2115,7 +2135,7 @@ public:
 
     virtual wxMBConv *Clone() const
     {
-        wxMBConv_iconv *p = new wxMBConv_iconv(m_name.ToAscii());
+        wxMBConv_iconv *p = new wxMBConv_iconv(m_name);
         p->m_minMBCharWidth = m_minMBCharWidth;
         return p;
     }
@@ -2145,7 +2165,7 @@ private:
 
 
     // name of the encoding handled by this conversion
-    wxString m_name;
+    const char *m_name;
 
     // cached result of GetMBNulLen(); set to 0 meaning "unknown"
     // initially
@@ -2169,7 +2189,7 @@ wxString wxMBConv_iconv::ms_wcCharsetName;
 bool wxMBConv_iconv::ms_wcNeedsSwap = false;
 
 wxMBConv_iconv::wxMBConv_iconv(const char *name)
-              : m_name(name)
+              : m_name(wxStrdup(name))
 {
     m_minMBCharWidth = 0;
 
@@ -2185,7 +2205,7 @@ wxMBConv_iconv::wxMBConv_iconv(const char *name)
         {
 #if SIZEOF_WCHAR_T == 4
             wxT("UCS-4"),
-#elif SIZEOF_WCHAR_T = 2
+#elif SIZEOF_WCHAR_T == 2
             wxT("UCS-2"),
 #endif
             NULL
@@ -2286,6 +2306,8 @@ wxMBConv_iconv::wxMBConv_iconv(const char *name)
 
 wxMBConv_iconv::~wxMBConv_iconv()
 {
+    free(const_cast<char *>(m_name));
+
     if ( m2w != ICONV_T_INVALID )
         iconv_close(m2w);
     if ( w2m != ICONV_T_INVALID )
@@ -2945,7 +2967,41 @@ void wxCSConv::Init()
 {
     m_name = NULL;
     m_convReal =  NULL;
-    m_deferred = true;
+}
+
+void wxCSConv::SetEncoding(wxFontEncoding encoding)
+{
+    switch ( encoding )
+    {
+        case wxFONTENCODING_MAX:
+        case wxFONTENCODING_SYSTEM:
+            if ( m_name )
+            {
+                // It's ok to not have encoding value if we have a name for it.
+                m_encoding = wxFONTENCODING_SYSTEM;
+            }
+            else // No name neither.
+            {
+                // Fall back to the system default encoding in this case (not
+                // sure how much sense does this make but this is how the old
+                // code used to behave).
+#if wxUSE_INTL
+                m_encoding = wxLocale::GetSystemEncoding();
+                if ( m_encoding == wxFONTENCODING_SYSTEM )
+#endif // wxUSE_INTL
+                    m_encoding = wxFONTENCODING_ISO8859_1;
+            }
+            break;
+
+        case wxFONTENCODING_DEFAULT:
+            // wxFONTENCODING_DEFAULT is same as US-ASCII in this context
+            m_encoding = wxFONTENCODING_ISO8859_1;
+            break;
+
+        default:
+            // Just use the provided encoding.
+            m_encoding = encoding;
+    }
 }
 
 wxCSConv::wxCSConv(const wxString& charset)
@@ -2958,20 +3014,12 @@ wxCSConv::wxCSConv(const wxString& charset)
     }
 
 #if wxUSE_FONTMAP
-    m_encoding = wxFontMapperBase::GetEncodingFromName(charset);
-    if ( m_encoding == wxFONTENCODING_MAX )
-    {
-        // set to unknown/invalid value
-        m_encoding = wxFONTENCODING_SYSTEM;
-    }
-    else if ( m_encoding == wxFONTENCODING_DEFAULT )
-    {
-        // wxFONTENCODING_DEFAULT is same as US-ASCII in this context
-        m_encoding = wxFONTENCODING_ISO8859_1;
-    }
+    SetEncoding(wxFontMapperBase::GetEncodingFromName(charset));
 #else
-    m_encoding = wxFONTENCODING_SYSTEM;
+    SetEncoding(wxFONTENCODING_SYSTEM);
 #endif
+
+    m_convReal = DoCreate();
 }
 
 wxCSConv::wxCSConv(wxFontEncoding encoding)
@@ -2985,7 +3033,9 @@ wxCSConv::wxCSConv(wxFontEncoding encoding)
 
     Init();
 
-    m_encoding = encoding;
+    SetEncoding(encoding);
+
+    m_convReal = DoCreate();
 }
 
 wxCSConv::~wxCSConv()
@@ -2999,7 +3049,9 @@ wxCSConv::wxCSConv(const wxCSConv& conv)
     Init();
 
     SetName(conv.m_name);
-    m_encoding = conv.m_encoding;
+    SetEncoding(conv.m_encoding);
+
+    m_convReal = DoCreate();
 }
 
 wxCSConv& wxCSConv::operator=(const wxCSConv& conv)
@@ -3007,7 +3059,9 @@ wxCSConv& wxCSConv::operator=(const wxCSConv& conv)
     Clear();
 
     SetName(conv.m_name);
-    m_encoding = conv.m_encoding;
+    SetEncoding(conv.m_encoding);
+
+    m_convReal = DoCreate();
 
     return *this;
 }
@@ -3015,19 +3069,15 @@ wxCSConv& wxCSConv::operator=(const wxCSConv& conv)
 void wxCSConv::Clear()
 {
     free(m_name);
-    delete m_convReal;
-
     m_name = NULL;
-    m_convReal = NULL;
+
+    wxDELETE(m_convReal);
 }
 
 void wxCSConv::SetName(const char *charset)
 {
-    if (charset)
-    {
+    if ( charset )
         m_name = wxStrdup(charset);
-        m_deferred = true;
-    }
 }
 
 #if wxUSE_FONTMAP
@@ -3050,8 +3100,7 @@ wxMBConv *wxCSConv::DoCreate() const
     // check for the special case of ASCII or ISO8859-1 charset: as we have
     // special knowledge of it anyhow, we don't need to create a special
     // conversion object
-    if ( m_encoding == wxFONTENCODING_ISO8859_1 ||
-            m_encoding == wxFONTENCODING_DEFAULT )
+    if ( m_encoding == wxFONTENCODING_ISO8859_1 )
     {
         // don't convert at all
         return NULL;
@@ -3226,33 +3275,8 @@ wxMBConv *wxCSConv::DoCreate() const
     return NULL;
 }
 
-void wxCSConv::CreateConvIfNeeded() const
-{
-    if ( m_deferred )
-    {
-        wxCSConv *self = (wxCSConv *)this; // const_cast
-
-        // if we don't have neither the name nor the encoding, use the default
-        // encoding for this system
-        if ( !m_name && m_encoding == wxFONTENCODING_SYSTEM )
-        {
-#if wxUSE_INTL
-            self->m_encoding = wxLocale::GetSystemEncoding();
-#else
-            // fallback to some reasonable default:
-            self->m_encoding = wxFONTENCODING_ISO8859_1;
-#endif // wxUSE_INTL
-        }
-
-        self->m_convReal = DoCreate();
-        self->m_deferred = false;
-    }
-}
-
 bool wxCSConv::IsOk() const
 {
-    CreateConvIfNeeded();
-
     // special case: no convReal created for wxFONTENCODING_ISO8859_1
     if ( m_encoding == wxFONTENCODING_ISO8859_1 )
         return true; // always ok as we do it ourselves
@@ -3265,8 +3289,6 @@ bool wxCSConv::IsOk() const
 size_t wxCSConv::ToWChar(wchar_t *dst, size_t dstLen,
                          const char *src, size_t srcLen) const
 {
-    CreateConvIfNeeded();
-
     if (m_convReal)
         return m_convReal->ToWChar(dst, dstLen, src, srcLen);
 
@@ -3289,8 +3311,6 @@ size_t wxCSConv::ToWChar(wchar_t *dst, size_t dstLen,
 size_t wxCSConv::FromWChar(char *dst, size_t dstLen,
                            const wchar_t *src, size_t srcLen) const
 {
-    CreateConvIfNeeded();
-
     if (m_convReal)
         return m_convReal->FromWChar(dst, dstLen, src, srcLen);
 
@@ -3326,12 +3346,8 @@ size_t wxCSConv::FromWChar(char *dst, size_t dstLen,
 
 size_t wxCSConv::GetMBNulLen() const
 {
-    CreateConvIfNeeded();
-
     if ( m_convReal )
-    {
         return m_convReal->GetMBNulLen();
-    }
 
     // otherwise, we are ISO-8859-1
     return 1;
@@ -3340,12 +3356,8 @@ size_t wxCSConv::GetMBNulLen() const
 #if wxUSE_UNICODE_UTF8
 bool wxCSConv::IsUTF8() const
 {
-    CreateConvIfNeeded();
-
     if ( m_convReal )
-    {
         return m_convReal->IsUTF8();
-    }
 
     // otherwise, we are ISO-8859-1
     return false;
@@ -3444,8 +3456,9 @@ WXDLLIMPEXP_DATA_BASE(wxMBConv *) wxConvCurrent = wxGet_wxConvLibcPtr();
 WXDLLIMPEXP_DATA_BASE(wxMBConv *) wxConvUI = wxGet_wxConvLocalPtr();
 
 #ifdef __DARWIN__
-// The xnu kernel always communicates file paths in decomposed UTF-8.
-// WARNING: Are we sure that CFString's conversion will cause decomposition?
+// It is important to use this conversion object under Darwin as it ensures
+// that Unicode strings are (re)composed correctly even though xnu kernel uses
+// decomposed form internally (at least for the file names).
 static wxMBConv_cf wxConvMacUTF8DObj(wxFONTENCODING_UTF8);
 #endif
 
@@ -3455,14 +3468,3 @@ WXDLLIMPEXP_DATA_BASE(wxMBConv *) wxConvFileName =
 #else // !__DARWIN__
                                     wxGet_wxConvLibcPtr();
 #endif // __DARWIN__/!__DARWIN__
-
-#else // !wxUSE_WCHAR_T
-
-// FIXME-UTF8: remove this, wxUSE_WCHAR_T is required now
-// stand-ins in absence of wchar_t
-WXDLLIMPEXP_DATA_BASE(wxMBConv) wxConvLibc,
-                                wxConvISO8859_1,
-                                wxConvLocal,
-                                wxConvUTF8;
-
-#endif // wxUSE_WCHAR_T/!wxUSE_WCHAR_T