]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/string.cpp
add the ToCLong, ToCULong and ToCDouble functions, with docs and test units
[wxWidgets.git] / src / common / string.cpp
index fcdca45d58a08aa3c98e32844a8293d93d144946..ed7a6a8670f42d467fd72028e22a8cefdc8d4eac 100644 (file)
@@ -36,6 +36,8 @@
 #include <stdlib.h>
 
 #include "wx/hashmap.h"
+#include "wx/vector.h"
+#include "wx/xlocale.h"
 
 // string handling functions used by wxString:
 #if wxUSE_UNICODE_UTF8
     #define wxStringStrlen   wxStrlen
 #endif
 
+// ----------------------------------------------------------------------------
+// global variables
+// ----------------------------------------------------------------------------
+
+namespace wxPrivate
+{
+
+static UntypedBufferData s_untypedNullData(NULL);
+
+UntypedBufferData * const untypedNullDataPtr = &s_untypedNullData;
+
+} // namespace wxPrivate
 
 // ---------------------------------------------------------------------------
 // static class variables definition
@@ -1103,6 +1117,7 @@ size_t wxString::find_last_not_of(const wxOtherCharType* sz, size_t nStart,
 
 int wxString::CmpNoCase(const wxString& s) const
 {
+#if wxUSE_UNICODE_UTF8
     // FIXME-UTF8: use wxUniChar::ToLower/ToUpper once added
 
     const_iterator i1 = begin();
@@ -1126,6 +1141,9 @@ int wxString::CmpNoCase(const wxString& s) const
     else if ( len1 > len2 )
         return 1;
     return 0;
+#else // wxUSE_UNICODE_WCHAR or ANSI
+    return wxStricmp(m_impl.c_str(), s.m_impl.c_str());
+#endif
 }
 
 
@@ -1381,30 +1399,62 @@ size_t wxString::Replace(const wxString& strOld,
                 break;
         }
     }
-    else // general case
+    else if ( !bReplaceAll)
+    {
+        size_t pos = m_impl.find(strOld, 0);
+        if ( pos != npos )
+        {
+            m_impl.replace(pos, strOld.m_impl.length(), strNew.m_impl);
+            uiCount = 1;
+        }
+    }
+    else // replace all occurrences
     {
         const size_t uiOldLen = strOld.m_impl.length();
         const size_t uiNewLen = strNew.m_impl.length();
 
-        for ( size_t pos = 0; ; )
+        // first scan the string to find all positions at which the replacement
+        // should be made
+        wxVector<size_t> replacePositions;
+
+        size_t pos;
+        for ( pos = m_impl.find(strOld.m_impl, 0);
+              pos != npos;
+              pos = m_impl.find(strOld.m_impl, pos + uiOldLen))
         {
-            pos = m_impl.find(strOld.m_impl, pos);
-            if ( pos == npos )
-                break;
+            replacePositions.push_back(pos);
+            ++uiCount;
+        }
 
-            // replace this occurrence of the old string with the new one
-            m_impl.replace(pos, uiOldLen, strNew.m_impl);
+        if ( !uiCount )
+            return 0;
 
-            // move up pos past the string that was replaced
-            pos += uiNewLen;
+        // allocate enough memory for the whole new string
+        wxString tmp;
+        tmp.m_impl.reserve(m_impl.length() + uiCount*(uiNewLen - uiOldLen));
 
-            // increase replace count
-            uiCount++;
+        // copy this string to tmp doing replacements on the fly
+        size_t replNum = 0;
+        for ( pos = 0; replNum < uiCount; replNum++ )
+        {
+            const size_t nextReplPos = replacePositions[replNum];
 
-            // stop after the first one?
-            if ( !bReplaceAll )
-                break;
+            if ( pos != nextReplPos )
+            {
+                tmp.m_impl.append(m_impl, pos, nextReplPos - pos);
+            }
+
+            tmp.m_impl.append(strNew.m_impl);
+            pos = nextReplPos + uiOldLen;
         }
+
+        if ( pos != m_impl.length() )
+        {
+            // append the rest of the string unchanged
+            tmp.m_impl.append(m_impl, pos, m_impl.length() - pos);
+        }
+
+        swap(tmp);
     }
 
     return uiCount;
@@ -1595,64 +1645,105 @@ int wxString::Find(wxUniChar ch, bool bFromEnd) const
     #define DO_IF_NOT_WINCE(x)
 #endif
 
-#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") );  \
-                                                                            \
+#define WX_STRING_TO_X_TYPE_START                                           \
+    wxCHECK_MSG( pVal, false, _T("NULL output pointer") );                  \
     DO_IF_NOT_WINCE( errno = 0; )                                           \
-                                                                            \
     const wxStringCharType *start = wx_str();                               \
-    wxStringCharType *end;                                                  \
-    T val = func(start, &end, base);                                        \
-                                                                            \
+    wxStringCharType *end;
+
+#define WX_STRING_TO_X_TYPE_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: */                                                         \
     if ( *end || end == start DO_IF_NOT_WINCE(|| errno == ERANGE) )         \
         return false;                                                       \
-    *out = val;                                                             \
-    return true
+    *pVal = val;                                                            \
+    return true;
 
 bool wxString::ToLong(long *pVal, int base) const
 {
-    WX_STRING_TO_INT_TYPE(pVal, base, wxStrtol, long);
+    wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
+
+    WX_STRING_TO_X_TYPE_START
+    long val = wxStrtol(start, &end, base);
+    WX_STRING_TO_X_TYPE_END
 }
 
 bool wxString::ToULong(unsigned long *pVal, int base) const
 {
-    WX_STRING_TO_INT_TYPE(pVal, base, wxStrtoul, unsigned long);
+    wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
+
+    WX_STRING_TO_X_TYPE_START
+    unsigned long val = wxStrtoul(start, &end, base);
+    WX_STRING_TO_X_TYPE_END
 }
 
 bool wxString::ToLongLong(wxLongLong_t *pVal, int base) const
 {
-    WX_STRING_TO_INT_TYPE(pVal, base, wxStrtoll, wxLongLong_t);
+    wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
+
+    WX_STRING_TO_X_TYPE_START
+    wxLongLong_t val = wxStrtoll(start, &end, base);
+    WX_STRING_TO_X_TYPE_END
 }
 
 bool wxString::ToULongLong(wxULongLong_t *pVal, int base) const
 {
-    WX_STRING_TO_INT_TYPE(pVal, base, wxStrtoull, wxULongLong_t);
+    wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
+
+    WX_STRING_TO_X_TYPE_START
+    wxULongLong_t val = wxStrtoull(start, &end, base);
+    WX_STRING_TO_X_TYPE_END
 }
 
 bool wxString::ToDouble(double *pVal) const
 {
-    wxCHECK_MSG( pVal, false, _T("NULL output pointer") );
+    WX_STRING_TO_X_TYPE_START
+    double val = wxStrtod(start, &end);
+    WX_STRING_TO_X_TYPE_END
+}
 
-    DO_IF_NOT_WINCE( errno = 0; )
+#if wxUSE_XLOCALE
 
-    const wxChar *start = c_str();
-    wxChar *end;
-    double val = wxStrtod(start, &end);
+bool wxString::ToCLong(long *pVal, int base) const
+{
+    wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid 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
-    if ( *end || end == start DO_IF_NOT_WINCE(|| errno == ERANGE) )
-        return false;
+    WX_STRING_TO_X_TYPE_START
+#if wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE
+    long val = wxStrtol_lA(start, &end, base, wxCLocale);
+#else
+    long val = wxStrtol_l(start, &end, base, wxCLocale);
+#endif
+    WX_STRING_TO_X_TYPE_END
+}
 
-    *pVal = val;
+bool wxString::ToCULong(unsigned long *pVal, int base) const
+{
+    wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
 
-    return true;
+    WX_STRING_TO_X_TYPE_START
+#if wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE
+    unsigned long val = wxStrtoul_lA(start, &end, base, wxCLocale);
+#else
+    unsigned long val = wxStrtoul_l(start, &end, base, wxCLocale);
+#endif
+    WX_STRING_TO_X_TYPE_END
+}
+
+bool wxString::ToCDouble(double *pVal) const
+{
+    WX_STRING_TO_X_TYPE_START
+#if wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE
+    double val = wxStrtod_lA(start, &end, wxCLocale);
+#else
+    double val = wxStrtod_l(start, &end, wxCLocale);
+#endif
+    WX_STRING_TO_X_TYPE_END
 }
 
+#endif  // wxUSE_XLOCALE
+
 // ---------------------------------------------------------------------------
 // formatted output
 // ---------------------------------------------------------------------------
@@ -2096,3 +2187,4 @@ int wxString::Freq(wxUniChar ch) const
     }
     return count;
 }
+