]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/string.cpp
pen and brush are platform neutral on osx
[wxWidgets.git] / src / common / string.cpp
index 5db2ba07a60fb909748ff456fdf5e6b1f6fd3ae6..362d682fb2eef1bba8264c871cf7a1b5b57c1d8c 100644 (file)
 #include <string.h>
 #include <stdlib.h>
 
-#ifdef __SALFORDC__
-    #include <clib.h>
-#endif
-
 #include "wx/hashmap.h"
 
 // string handling functions used by wxString:
@@ -373,6 +369,9 @@ wxString::SubstrBufFromMB wxString::ConvertStr(const char *psz, size_t nLength,
         // UTF-8 sequence and psz may be invalid:
         if ( wxStringOperations::IsValidUtf8String(psz, nLength) )
         {
+            // we must pass the real string length to SubstrBufFromMB ctor
+            if ( nLength == npos )
+                nLength = psz ? strlen(psz) : 0;
             return SubstrBufFromMB(wxCharBuffer::CreateNonOwned(psz), nLength);
         }
         // else: do the roundtrip through wchar_t*
@@ -1240,33 +1239,55 @@ size_t wxString::Replace(const wxString& strOld,
 
     size_t uiCount = 0;   // count of replacements made
 
-    size_t uiOldLen = strOld.length();
-    size_t uiNewLen = strNew.length();
+    // optimize the special common case: replacement of one character by
+    // another one (in UTF-8 case we can only do this for ASCII characters)
+    //
+    // benchmarks show that this special version is around 3 times faster
+    // (depending on the proportion of matching characters and UTF-8/wchar_t
+    // build)
+    if ( strOld.m_impl.length() == 1 && strNew.m_impl.length() == 1 )
+    {
+        const wxStringCharType chOld = strOld.m_impl[0],
+                               chNew = strNew.m_impl[0];
+
+        // this loop is the simplified version of the one below
+        for ( size_t pos = 0; ; )
+        {
+            pos = m_impl.find(chOld, pos);
+            if ( pos == npos )
+                break;
 
-    size_t dwPos = 0;
+            m_impl[pos++] = chNew;
 
-    while ( (*this)[dwPos] != wxT('\0') )
+            uiCount++;
+
+            if ( !bReplaceAll )
+                break;
+        }
+    }
+    else // general case
     {
-        //DO NOT USE STRSTR HERE
-        //this string can contain embedded null characters,
-        //so strstr will function incorrectly
-        dwPos = find(strOld, dwPos);
-        if ( dwPos == npos )
-            break;                  // exit the loop
-        else
+        const size_t uiOldLen = strOld.m_impl.length();
+        const size_t uiNewLen = strNew.m_impl.length();
+
+        for ( size_t pos = 0; ; )
         {
-            //replace this occurance of the old string with the new one
-            replace(dwPos, uiOldLen, strNew, uiNewLen);
+            pos = m_impl.find(strOld.m_impl, pos);
+            if ( pos == npos )
+                break;
 
-            //move up pos past the string that was replaced
-            dwPos += uiNewLen;
+            // replace this occurrence of the old string with the new one
+            m_impl.replace(pos, uiOldLen, strNew.m_impl);
 
-            //increase replace count
-            ++uiCount;
+            // move up pos past the string that was replaced
+            pos += uiNewLen;
 
-            // stop now?
+            // increase replace count
+            uiCount++;
+
+            // stop after the first one?
             if ( !bReplaceAll )
-                break;                  // exit the loop
+                break;
         }
     }
 
@@ -1347,9 +1368,9 @@ wxString& wxString::MakeLower()
 // ---------------------------------------------------------------------------
 
 // some compilers (VC++ 6.0 not to name them) return true for a call to
-// isspace('ê') in the C locale which seems to be broken to me, but we have to
-// live with this by checking that the character is a 7 bit one - even if this
-// may fail to detect some spaces (I don't know if Unicode doesn't have
+// isspace('\xEA') in the C locale which seems to be broken to me, but we have
+// to live with this by checking that the character is a 7 bit one - even if
+// this may fail to detect some spaces (I don't know if Unicode doesn't have
 // space-like symbols somewhere except in the first 128 chars), it is arguably
 // still better than trimming away accented letters
 inline int wxSafeIsspace(wxChar ch) { return (ch < 127) && wxIsspace(ch); }
@@ -1444,61 +1465,62 @@ int wxString::Find(wxUniChar ch, bool bFromEnd) const
     #define DO_IF_NOT_WINCE(x)
 #endif
 
-#define WX_STRING_TO_INT_TYPE(val, base, func)                              \
-    wxCHECK_MSG( val, false, _T("NULL output pointer") );                   \
+#define WX_STRING_TO_INT_TYPE(out, base, func, T)                           \
+    wxCHECK_MSG( out, false, _T("NULL output pointer") );                   \
     wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );  \
                                                                             \
     DO_IF_NOT_WINCE( errno = 0; )                                           \
                                                                             \
     const wxStringCharType *start = wx_str();                               \
     wxStringCharType *end;                                                  \
-    *val = func(start, &end, base);                                         \
+    T val = func(start, &end, base);                                        \
                                                                             \
     /* return true only if scan was stopped by the terminating NUL and */   \
     /* if the string was not empty to start with and no under/overflow */   \
     /* occurred: */                                                         \
-    return !*end && (end != start)                                          \
-        DO_IF_NOT_WINCE( && (errno != ERANGE) )
+    if ( *end || end == start DO_IF_NOT_WINCE(|| errno == ERANGE) )         \
+        return false;                                                       \
+    *out = val;                                                             \
+    return true
 
-bool wxString::ToLong(long *val, int base) const
+bool wxString::ToLong(long *pVal, int base) const
 {
-    WX_STRING_TO_INT_TYPE(val, base, wxStrtol);
+    WX_STRING_TO_INT_TYPE(pVal, base, wxStrtol, long);
 }
 
-bool wxString::ToULong(unsigned long *val, int base) const
+bool wxString::ToULong(unsigned long *pVal, int base) const
 {
-    WX_STRING_TO_INT_TYPE(val, base, wxStrtoul);
+    WX_STRING_TO_INT_TYPE(pVal, base, wxStrtoul, unsigned long);
 }
 
-bool wxString::ToLongLong(wxLongLong_t *val, int base) const
+bool wxString::ToLongLong(wxLongLong_t *pVal, int base) const
 {
-    WX_STRING_TO_INT_TYPE(val, base, wxStrtoll);
+    WX_STRING_TO_INT_TYPE(pVal, base, wxStrtoll, wxLongLong_t);
 }
 
-bool wxString::ToULongLong(wxULongLong_t *val, int base) const
+bool wxString::ToULongLong(wxULongLong_t *pVal, int base) const
 {
-    WX_STRING_TO_INT_TYPE(val, base, wxStrtoull);
+    WX_STRING_TO_INT_TYPE(pVal, base, wxStrtoull, wxULongLong_t);
 }
 
-bool wxString::ToDouble(double *val) const
+bool wxString::ToDouble(double *pVal) const
 {
-    wxCHECK_MSG( val, false, _T("NULL pointer in wxString::ToDouble") );
+    wxCHECK_MSG( pVal, false, _T("NULL output pointer") );
 
-#ifndef __WXWINCE__
-    errno = 0;
-#endif
+    DO_IF_NOT_WINCE( errno = 0; )
 
     const wxChar *start = c_str();
     wxChar *end;
-    *val = wxStrtod(start, &end);
+    double val = wxStrtod(start, &end);
 
     // return true only if scan was stopped by the terminating NUL and if the
     // string was not empty to start with and no under/overflow occurred
-    return !*end && (end != start)
-#ifndef __WXWINCE__
-        && (errno != ERANGE)
-#endif
-    ;
+    if ( *end || end == start DO_IF_NOT_WINCE(|| errno == ERANGE) )
+        return false;
+
+    *pVal = val;
+
+    return true;
 }
 
 // ---------------------------------------------------------------------------
@@ -1620,7 +1642,7 @@ int wxString::DoPrintfUtf8(const char *format, ...)
     an undersized buffer and no other errno are defined we treat those two
     as meaning hard errors and everything else gets the old behavior which
     is to keep looping and increasing buffer size until the function succeeds.
+
     In practice it's impossible to determine before compilation which behavior
     may be used.  The vswprintf function may have vsnprintf-like behavior or
     vice-versa.  Behavior detected on one release can theoretically change
@@ -1730,7 +1752,7 @@ static int DoStringPrintfV(wxString& str,
         else if ( len >= size )
         {
 #if wxUSE_WXVSNPRINTF
-            // we know that our own implementation of wxVsnprintf() returns 
+            // we know that our own implementation of wxVsnprintf() returns
             // size+1 when there's not enough space but that's not the size
             // of the required buffer!
             size *= 2;      // so we just double the current size of the buffer