]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/string.cpp
fixed header include guard position (patch 992443)
[wxWidgets.git] / src / common / string.cpp
index f02faad0daf1418a207fb04c078812b530b986cd..ffddc7611e070cc014c8bbb923fe4d5033dfb0fb 100644 (file)
@@ -9,7 +9,7 @@
 // Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
-#ifdef __GNUG__
+#if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
   #pragma implementation "string.h"
 #endif
 
@@ -100,6 +100,8 @@ extern const wxChar WXDLLIMPEXP_BASE *wxEmptyString = &g_strEmpty.dummy;
 //
 // ATTN: you can _not_ use both of these in the same program!
 
+#include <iostream>
+
 wxSTD istream& operator>>(wxSTD istream& is, wxString& WXUNUSED(str))
 {
 #if 0
@@ -168,6 +170,8 @@ wxSTD ostream& operator<<(wxSTD ostream& os, const wxString& str)
   #define STATISTICS_ADD(av, val)
 #endif // WXSTRING_STATISTICS
 
+#if !wxUSE_STL
+
 // ===========================================================================
 // wxStringData class deallocation
 // ===========================================================================
@@ -180,8 +184,6 @@ void wxStringData::Free()
 }
 #endif
 
-#if !wxUSE_STL
-
 // ===========================================================================
 // wxStringBase
 // ===========================================================================
@@ -405,6 +407,20 @@ bool wxStringBase::Alloc(size_t nLen)
   //else: we've already got enough
   return TRUE;
 }
+  
+wxStringBase::iterator wxStringBase::begin()
+{
+    if (length() > 0)
+        CopyBeforeWrite();
+    return m_pchData;
+}
+
+wxStringBase::iterator wxStringBase::end()
+{
+    if (length() > 0)
+        CopyBeforeWrite();
+    return m_pchData + length();
+}
 
 wxStringBase::iterator wxStringBase::erase(iterator it)
 {
@@ -479,18 +495,35 @@ size_t wxStringBase::find(wxChar ch, size_t nStart) const
 
 size_t wxStringBase::rfind(const wxStringBase& str, size_t nStart) const
 {
-  wxASSERT( str.GetStringData()->IsValid() );
-  wxASSERT( nStart == npos || nStart <= length() );
-
-  // TODO could be made much quicker than that
-  const wxChar *p = c_str() + (nStart == npos ? length() : nStart);
-  while ( p >= c_str() + str.length() ) {
-    if ( wxStrncmp(p - str.length(), str.c_str(), str.length()) == 0 )
-      return p - str.length() - c_str();
-    p--;
-  }
+    wxASSERT( str.GetStringData()->IsValid() );
+    wxASSERT( nStart == npos || nStart <= length() );
+
+    if ( length() >= str.length() )
+    {
+        // avoids a corner case later
+        if ( length() == 0 && str.length() == 0 )
+            return 0;
+
+        // "top" is the point where search starts from
+        size_t top = length() - str.length();
 
-  return npos;
+        if ( nStart == npos )
+            nStart = length() - 1;
+        if ( nStart < top )
+            top = nStart;
+
+        const wxChar *cursor = c_str() + top;
+        do
+        {
+            if ( memcmp(cursor, str.c_str(),
+                        str.length() * sizeof(wxChar)) == 0 )
+            {
+                return cursor - c_str();
+            }
+        } while ( cursor-- > c_str() );
+    }
+    
+    return npos;
 }
 
 size_t wxStringBase::rfind(const wxChar* sz, size_t nStart, size_t n) const
@@ -509,13 +542,15 @@ size_t wxStringBase::rfind(wxChar ch, size_t nStart) const
         wxASSERT( nStart <= length() );
     }
 
-    const wxChar *p = wxStrrchr(c_str(), ch);
-
-    if ( p == NULL )
-        return npos;
+    const wxChar *actual;
+    for ( actual = c_str() + ( nStart == npos ? length() : nStart + 1 );
+          actual > c_str(); --actual )
+    {
+        if ( *(actual - 1) == ch )
+            return (actual - 1) - c_str();
+    }
 
-    size_t result = p - c_str();
-    return ( result > nStart ) ? npos : result;
+    return npos;
 }
 
 size_t wxStringBase::find_first_of(const wxChar* sz, size_t nStart) const
@@ -528,18 +563,25 @@ size_t wxStringBase::find_first_of(const wxChar* sz, size_t nStart) const
         return npos;
 }
 
+size_t wxStringBase::find_first_of(const wxChar* sz, size_t nStart,
+                                   size_t n) const
+{
+    return find_first_of(wxStringBase(sz, n), nStart);
+}
+
 size_t wxStringBase::find_last_of(const wxChar* sz, size_t nStart) const
 {
     if ( nStart == npos )
     {
-        nStart = length();
+        nStart = length() - 1;
     }
     else
     {
-        wxASSERT( nStart <= length() );
+        wxASSERT_MSG( nStart <= length(),
+                        _T("invalid index in find_last_of()") );
     }
 
-    for ( const wxChar *p = c_str() + length() - 1; p >= c_str(); p-- )
+    for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
     {
         if ( wxStrchr(sz, *p) )
             return p - c_str();
@@ -548,6 +590,12 @@ size_t wxStringBase::find_last_of(const wxChar* sz, size_t nStart) const
     return npos;
 }
 
+size_t wxStringBase::find_last_of(const wxChar* sz, size_t nStart,
+                                   size_t n) const
+{
+    return find_last_of(wxStringBase(sz, n), nStart);
+}
+
 size_t wxStringBase::find_first_not_of(const wxChar* sz, size_t nStart) const
 {
     if ( nStart == npos )
@@ -563,7 +611,13 @@ size_t wxStringBase::find_first_not_of(const wxChar* sz, size_t nStart) const
     if ( nAccept >= length() - nStart )
         return npos;
     else
-        return nAccept;
+        return nStart + nAccept;
+}
+
+size_t wxStringBase::find_first_not_of(const wxChar* sz, size_t nStart,
+                                       size_t n) const
+{
+    return find_first_not_of(wxStringBase(sz, n), nStart);
 }
 
 size_t wxStringBase::find_first_not_of(wxChar ch, size_t nStart) const
@@ -583,14 +637,14 @@ size_t wxStringBase::find_last_not_of(const wxChar* sz, size_t nStart) const
 {
     if ( nStart == npos )
     {
-        nStart = length();
+        nStart = length() - 1;
     }
     else
     {
         wxASSERT( nStart <= length() );
     }
 
-    for ( const wxChar *p = c_str() + nStart - 1; p >= c_str(); p-- )
+    for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
     {
         if ( !wxStrchr(sz, *p) )
             return p - c_str();
@@ -599,18 +653,24 @@ size_t wxStringBase::find_last_not_of(const wxChar* sz, size_t nStart) const
     return npos;
 }
 
+size_t wxStringBase::find_last_not_of(const wxChar* sz, size_t nStart,
+                                      size_t n) const
+{
+    return find_last_not_of(wxStringBase(sz, n), nStart);
+}
+
 size_t wxStringBase::find_last_not_of(wxChar ch, size_t nStart) const
 {
     if ( nStart == npos )
     {
-        nStart = length();
+        nStart = length() - 1;
     }
     else
     {
         wxASSERT( nStart <= length() );
     }
 
-    for ( const wxChar *p = c_str() + nStart - 1; p >= c_str(); p-- )
+    for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
     {
         if ( *p != ch )
             return p - c_str();
@@ -902,12 +962,25 @@ int STRINGCLASS::compare(size_t nStart, size_t nLen,
 // from multibyte string
 wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength)
 {
+    // if nLength != npos, then we have to make a NULL-terminated copy
+    // of first nLength bytes of psz first because the input buffer to MB2WC
+    // must always be NULL-terminated:
+    wxCharBuffer inBuf((const char *)NULL);
+    if (nLength != npos)
+    {
+        wxCharBuffer tmp(nLength);
+        memcpy(tmp.data(), psz, nLength);
+        tmp.data()[nLength] = '\0';
+        inBuf = tmp;
+        psz = inBuf.data();
+    }
+    
     // first get the size of the buffer we need
     size_t nLen;
     if ( psz )
     {
         // calculate the needed size ourselves or use the provided one
-        nLen = nLength == npos ? conv.MB2WC(NULL, psz, 0) : nLength;
+        nLen = conv.MB2WC(NULL, psz, 0);
     }
     else
     {
@@ -924,7 +997,7 @@ wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength)
         }
         else
         {
-            wxWCharBuffer buf(nLen + 1);
+            wxWCharBuffer buf(nLen);
             // MB2WC wants the buffer size, not the string length hence +1
             nLen = conv.MB2WC(buf.data(), psz, nLen + 1);
 
@@ -946,12 +1019,25 @@ wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength)
 // from wide string
 wxString::wxString(const wchar_t *pwz, wxMBConv& conv, size_t nLength)
 {
+    // if nLength != npos, then we have to make a NULL-terminated copy
+    // of first nLength chars of psz first because the input buffer to WC2MB
+    // must always be NULL-terminated:
+    wxWCharBuffer inBuf((const wchar_t *)NULL);
+    if (nLength != npos)
+    {
+        wxWCharBuffer tmp(nLength);
+        memcpy(tmp.data(), pwz, nLength * sizeof(wchar_t));
+        tmp.data()[nLength] = '\0';
+        inBuf = tmp;
+        pwz = inBuf.data();
+    }
+    
     // first get the size of the buffer we need
     size_t nLen;
     if ( pwz )
     {
         // calculate the needed size ourselves or use the provided one
-        nLen = nLength == npos ? conv.WC2MB(NULL, pwz, 0) : nLength;
+        nLen = conv.WC2MB(NULL, pwz, 0);
     }
     else
     {
@@ -1641,7 +1727,10 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr)
             buf[size] = _T('\0');
         }
 
-        if ( len >= 0 )
+        // vsnprintf() may return either -1 (traditional Unix behaviour) or the
+        // total number of characters which would have been written if the
+        // buffer were large enough
+        if ( len >= 0 && len <= size )
         {
             // ok, there was enough space
             break;
@@ -1960,6 +2049,11 @@ wxArrayString::~wxArrayString()
   wxDELETEA(m_pItems);
 }
 
+void wxArrayString::reserve(size_t nSize)
+{
+    Alloc(nSize);
+}
+
 // pre-allocates memory (frees the previous data!)
 void wxArrayString::Alloc(size_t nSize)
 {
@@ -2127,6 +2221,30 @@ void wxArrayString::Insert(const wxString& str, size_t nIndex, size_t nInsert)
   m_nCount += nInsert;
 }
 
+// range insert (STL 23.2.4.3)
+void
+wxArrayString::insert(iterator it, const_iterator first, const_iterator last)
+{
+    const int idx = it - begin();
+
+    // grow it once
+    Grow(last - first);
+
+    // reset "it" since it can change inside Grow()
+    it = begin() + idx;
+
+    while ( first != last )
+    {
+        it = insert(it, *first);
+
+        // insert returns an iterator to the last element inserted but we need
+        // insert the next after this one, that is before the next one
+        ++it;
+
+        ++first;
+    }
+} 
+
 // expand the array
 void wxArrayString::SetCount(size_t count)
 {
@@ -2164,6 +2282,13 @@ void wxArrayString::Remove(const wxChar *sz)
   RemoveAt(iIndex);
 }
 
+void wxArrayString::assign(const_iterator first, const_iterator last)
+{
+    reserve(last - first);
+    for(; first != last; ++first)
+        push_back(*first);
+}
+
 // ----------------------------------------------------------------------------
 // sorting
 // ----------------------------------------------------------------------------
@@ -2266,12 +2391,12 @@ bool wxArrayString::operator==(const wxArrayString& a) const
 
 #endif // !wxUSE_STL
 
-int wxStringSortAscending(wxString* s1, wxString* s2)
+int wxCMPFUNC_CONV wxStringSortAscending(wxString* s1, wxString* s2)
 {
     return wxStrcmp(s1->c_str(), s2->c_str());
 }
 
-int wxStringSortDescending(wxString* s1, wxString* s2)
+int wxCMPFUNC_CONV wxStringSortDescending(wxString* s1, wxString* s2)
 {
     return -wxStrcmp(s1->c_str(), s2->c_str());
 }