]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/string.cpp
option for no close button for wxAuiNotebook in aui demo
[wxWidgets.git] / src / common / string.cpp
index 98a635bc49d24c45a96db207566518d985b4be37..4551c669318d178426b6ff5b4f0629ad125781f6 100644 (file)
 #endif
 
 #include <ctype.h>
+
+#ifndef __WXWINCE__
+    #include <errno.h>
+#endif
+
 #include <string.h>
 #include <stdlib.h>
 
@@ -174,8 +179,16 @@ void wxStringBase::InitWith(const wxChar *psz, size_t nPos, size_t nLength)
 // poor man's iterators are "void *" pointers
 wxStringBase::wxStringBase(const void *pStart, const void *pEnd)
 {
-  InitWith((const wxChar *)pStart, 0,
-           (const wxChar *)pEnd - (const wxChar *)pStart);
+  if ( pEnd >= pStart )
+  {
+    InitWith((const wxChar *)pStart, 0,
+             (const wxChar *)pEnd - (const wxChar *)pStart);
+  }
+  else
+  {
+    wxFAIL_MSG( _T("pStart is not before pEnd") );
+    Init();
+  }
 }
 
 wxStringBase::wxStringBase(size_type n, wxChar ch)
@@ -434,36 +447,47 @@ void wxStringBase::swap(wxStringBase& str)
 
 size_t wxStringBase::find(const wxStringBase& str, size_t nStart) const
 {
+    // deal with the special case of empty string first
+    const size_t nLen = length();
+    const size_t nLenOther = str.length();
+
+    if ( !nLenOther )
+    {
+        // empty string is a substring of anything
+        return 0;
+    }
+
+    if ( !nLen )
+    {
+        // the other string is non empty so can't be our substring
+        return npos;
+    }
+
     wxASSERT( str.GetStringData()->IsValid() );
-    wxASSERT( nStart <= length() );
+    wxASSERT( nStart <= nLen );
+
+    const wxChar * const other = str.c_str();
 
-    //anchor
+    // anchor
     const wxChar* p = (const wxChar*)wxTmemchr(c_str() + nStart,
-                                               str.c_str()[0],
-                                               length() - nStart);
+                                               *other,
+                                               nLen - nStart);
 
-    if(!p)
+    if ( !p )
         return npos;
 
-    while(p - c_str() + str.length() <= length() &&
-          wxTmemcmp(p, str.c_str(), str.length()) )
+    while ( p - c_str() + nLenOther <= nLen && wxTmemcmp(p, other, nLenOther) )
     {
-        //Previosly passed as the first argument to wxTmemchr,
-        //but C/C++ standard does not specify evaluation order
-        //of arguments to functions -
-        //http://embedded.com/showArticle.jhtml?articleID=9900607
-        ++p;
-
-        //anchor again
-        p = (const wxChar*)wxTmemchr(p,
-                                     str.c_str()[0],
-                                     length() - (p - c_str()));
-
-        if(!p)
+        p++;
+
+        // anchor again
+        p = (const wxChar*)wxTmemchr(p, *other, nLen - (p - c_str()));
+
+        if ( !p )
             return npos;
     }
 
-    return (p - c_str() + str.length() <= length()) ? p - c_str() : npos;
+    return p - c_str() + nLenOther <= nLen ? p - c_str() : npos;
 }
 
 size_t wxStringBase::find(const wxChar* sz, size_t nStart, size_t n) const
@@ -1584,7 +1608,7 @@ wxString& wxString::Trim(bool bFromRight)
             reverse_iterator psz = rbegin();
             while ( (psz != rend()) && wxSafeIsspace(*psz) )
                 psz++;
-            
+
             // truncate at trailing space start
             erase(psz.base(), end());
         }
@@ -1655,45 +1679,93 @@ int wxString::Find(const wxChar *pszSub) const
 // conversion to numbers
 // ----------------------------------------------------------------------------
 
-bool wxString::ToLong(long *val, int base) const
+// the implementation of all the functions below is exactly the same so factor
+// it out
+
+#ifdef __WATCOMC__
+    #define STR2INTLINK _WCRTLINK
+#else
+    #define STR2INTLINK
+#endif
+
+template <typename T>
+bool wxStringToIntType(const wxChar *start,
+                       T *val,
+                       int base,
+                       T STR2INTLINK (*func)(const wxChar *, wxChar **, int))
 {
-    wxCHECK_MSG( val, false, _T("NULL pointer in wxString::ToLong") );
+    wxCHECK_MSG( val, false, _T("NULL output pointer") );
     wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
 
-    const wxChar *start = c_str();
+#ifndef __WXWINCE__
+    errno = 0;
+#endif
+
     wxChar *end;
-    *val = wxStrtol(start, &end, base);
+    *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
-    return !*end && (end != start);
+    // string was not empty to start with and no under/overflow occurred
+    return !*end && (end != start)
+#ifndef __WXWINCE__
+        && (errno != ERANGE)
+#endif
+    ;
+}
+
+bool wxString::ToLong(long *val, int base) const
+{
+    return wxStringToIntType(c_str(), val, base, wxStrtol);
 }
 
 bool wxString::ToULong(unsigned long *val, int base) const
 {
-    wxCHECK_MSG( val, false, _T("NULL pointer in wxString::ToULong") );
-    wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") );
+    return wxStringToIntType(c_str(), val, base, wxStrtoul);
+}
 
-    const wxChar *start = c_str();
-    wxChar *end;
-    *val = wxStrtoul(start, &end, base);
+bool wxString::ToLongLong(wxLongLong_t *val, int base) const
+{
+#ifdef wxHAS_STRTOLL
+    return wxStringToIntType(c_str(), val, base, wxStrtoll);
+#else
+    // TODO: implement this ourselves
+    wxUnusedVar(val);
+    wxUnusedVar(base);
+    return false;
+#endif // wxHAS_STRTOLL
+}
 
-    // return true only if scan was stopped by the terminating NUL and if the
-    // string was not empty to start with
-    return !*end && (end != start);
+bool wxString::ToULongLong(wxULongLong_t *val, int base) const
+{
+#ifdef wxHAS_STRTOLL
+    return wxStringToIntType(c_str(), val, base, wxStrtoull);
+#else
+    // TODO: implement this ourselves
+    wxUnusedVar(val);
+    wxUnusedVar(base);
+    return false;
+#endif
 }
 
 bool wxString::ToDouble(double *val) const
 {
     wxCHECK_MSG( val, false, _T("NULL pointer in wxString::ToDouble") );
 
+#ifndef __WXWINCE__
+    errno = 0;
+#endif
+
     const wxChar *start = c_str();
     wxChar *end;
     *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
-    return !*end && (end != start);
+    // string was not empty to start with and no under/overflow occurred
+    return !*end && (end != start)
+#ifndef __WXWINCE__
+        && (errno != ERANGE)
+#endif
+    ;
 }
 
 // ---------------------------------------------------------------------------
@@ -1770,9 +1842,11 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr)
             // current size of the buffer
             size *= 2;
         }
-        else if ( len > size )
+        else if ( len >= size )
         {
-            size = len;
+            // some vsnprintf() implementations NUL-terminate the buffer and
+            // some don't in len == size case, to be safe always add 1
+            size = len + 1;
         }
         else // ok, there was enough space
         {