]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/string.cpp
remove wxWINT_T_IS_TYPEDEF as it seems wint_t is always a typedef (although it can...
[wxWidgets.git] / src / common / string.cpp
index 7b3805d3a37f91a9ccf1059fb39009fa47419fc0..f26486112aaee9a34233162cf96f6271a4f60495 100644 (file)
@@ -56,7 +56,7 @@
 // static class variables definition
 // ---------------------------------------------------------------------------
 
-#if !wxUSE_STL
+#if !wxUSE_STL_BASED_WXSTRING
   //According to STL _must_ be a -1 size_t
   const size_t wxStringBase::npos = (size_t) -1;
 #endif
@@ -65,7 +65,7 @@
 // static data
 // ----------------------------------------------------------------------------
 
-#if wxUSE_STL
+#if wxUSE_STL_BASED_WXSTRING
 
 extern const wxChar WXDLLIMPEXP_BASE *wxEmptyString = _T("");
 
@@ -95,12 +95,16 @@ extern const wxChar WXDLLIMPEXP_BASE *wxEmptyString = &g_strEmpty.dummy;
 
 wxSTD ostream& operator<<(wxSTD ostream& os, const wxString& str)
 {
-#ifdef __BORLANDC__
-    os << str.mb_str();
+    return os << str.c_str();
+}
+
+wxSTD ostream& operator<<(wxSTD ostream& os, const wxCStrData& str)
+{
+#if wxUSE_UNICODE && !defined(__BORLANDC__)
+    return os << str.AsWChar();
 #else
-    os << str.c_str();
+    return os << str.AsChar();
 #endif
-    return os;
 }
 
 #endif // wxUSE_STD_IOSTREAM
@@ -134,7 +138,7 @@ wxSTD ostream& operator<<(wxSTD ostream& os, const wxString& str)
   #define STATISTICS_ADD(av, val)
 #endif // WXSTRING_STATISTICS
 
-#if !wxUSE_STL
+#if !wxUSE_STL_BASED_WXSTRING
 
 // ===========================================================================
 // wxStringData class deallocation
@@ -191,7 +195,7 @@ wxStringBase::wxStringBase(const void *pStart, const void *pEnd)
   }
 }
 
-wxStringBase::wxStringBase(size_type n, wxChar ch)
+wxStringBase::wxStringBase(size_type n, wxUniChar ch)
 {
   Init();
   append(n, ch);
@@ -300,7 +304,7 @@ bool wxStringBase::AllocBeforeWrite(size_t nLen)
   return true;
 }
 
-wxStringBase& wxStringBase::append(size_t n, wxChar ch)
+wxStringBase& wxStringBase::append(size_t n, wxUniChar ch)
 {
     size_type len = length();
 
@@ -314,7 +318,7 @@ wxStringBase& wxStringBase::append(size_t n, wxChar ch)
     return *this;
 }
 
-void wxStringBase::resize(size_t nSize, wxChar ch)
+void wxStringBase::resize(size_t nSize, wxUniChar ch)
 {
     size_t len = length();
 
@@ -495,7 +499,7 @@ size_t wxStringBase::find(const wxChar* sz, size_t nStart, size_t n) const
     return find(wxStringBase(sz, n), nStart);
 }
 
-size_t wxStringBase::find(wxChar ch, size_t nStart) const
+size_t wxStringBase::find(wxUniChar ch, size_t nStart) const
 {
     wxASSERT( nStart <= length() );
 
@@ -542,7 +546,7 @@ size_t wxStringBase::rfind(const wxChar* sz, size_t nStart, size_t n) const
     return rfind(wxStringBase(sz, n), nStart);
 }
 
-size_t wxStringBase::rfind(wxChar ch, size_t nStart) const
+size_t wxStringBase::rfind(wxUniChar ch, size_t nStart) const
 {
     if ( nStart == npos )
     {
@@ -650,14 +654,14 @@ size_t wxStringBase::find_first_not_of(const wxChar* sz, size_t nStart,
     return find_first_not_of(wxStringBase(sz, n), nStart);
 }
 
-size_t wxStringBase::find_first_not_of(wxChar ch, size_t nStart) const
+size_t wxStringBase::find_first_not_of(wxUniChar ch, size_t nStart) const
 {
     wxASSERT( nStart <= length() );
 
-    for ( const wxChar *p = c_str() + nStart; *p; p++ )
+    for ( const_iterator p = begin() + nStart; (bool)*p; ++p ) // FIXME-DMARS
     {
         if ( *p != ch )
-            return p - c_str();
+            return p - begin();
     }
 
     return npos;
@@ -691,7 +695,7 @@ size_t wxStringBase::find_last_not_of(const wxChar* sz, size_t nStart,
     return find_last_not_of(wxStringBase(sz, n), nStart);
 }
 
-size_t wxStringBase::find_last_not_of(wxChar ch, size_t nStart) const
+size_t wxStringBase::find_last_not_of(wxUniChar ch, size_t nStart) const
 {
     if ( nStart == npos )
     {
@@ -702,10 +706,10 @@ size_t wxStringBase::find_last_not_of(wxChar ch, size_t nStart) const
         wxASSERT( nStart <= length() );
     }
 
-    for ( const wxChar *p = c_str() + nStart; p >= c_str(); --p )
+    for ( const_iterator p = begin() + nStart; p != begin(); --p )
     {
         if ( *p != ch )
-            return p - c_str();
+            return p - begin();
     }
 
     return npos;
@@ -744,7 +748,7 @@ wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
 }
 
 wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
-                                    size_t nCount, wxChar ch)
+                                    size_t nCount, wxUniChar ch)
 {
   return replace(nStart, nLen, wxStringBase(nCount, ch).c_str());
 }
@@ -791,9 +795,10 @@ wxStringBase& wxStringBase::operator=(const wxStringBase& stringSrc)
 }
 
 // assigns a single character
-wxStringBase& wxStringBase::operator=(wxChar ch)
+wxStringBase& wxStringBase::operator=(wxUniChar ch)
 {
-  if ( !AssignCopy(1, &ch) ) {
+  wxChar c(ch);
+  if ( !AssignCopy(1, &c) ) {
     wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(wxChar)") );
   }
   return *this;
@@ -906,11 +911,11 @@ bool wxStringBase::AllocCopy(wxString& dest, int nCopyLen, int nCopyIndex) const
   return true;
 }
 
-#endif // !wxUSE_STL
+#endif // !wxUSE_STL_BASED_WXSTRING
 
-#if !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE)
+#if !wxUSE_STL_BASED_WXSTRING || !defined(HAVE_STD_STRING_COMPARE)
 
-#if !wxUSE_STL
+#if !wxUSE_STL_BASED_WXSTRING
     #define STRINGCLASS wxStringBase
 #else
     #define STRINGCLASS wxString
@@ -980,7 +985,7 @@ int STRINGCLASS::compare(size_t nStart, size_t nLen,
 
 #undef STRINGCLASS
 
-#endif // !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE)
+#endif // !wxUSE_STL_BASED_WXSTRING || !defined(HAVE_STD_STRING_COMPARE)
 
 // ===========================================================================
 // wxString class core
@@ -1059,7 +1064,7 @@ bool wxString::Shrink()
   return tmp.length() == length();
 }
 
-#if !wxUSE_STL
+#if !wxUSE_STL_BASED_WXSTRING
 // get the pointer to writable buffer of (at least) nLen bytes
 wxChar *wxString::DoGetWriteBuf(size_t nLen)
 {
@@ -1110,7 +1115,7 @@ void wxString::UngetWriteBuf(size_t nLen)
 }
 #endif // WXWIN_COMPATIBILITY_2_8
 
-#endif // !wxUSE_STL
+#endif // !wxUSE_STL_BASED_WXSTRING
 
 
 // ---------------------------------------------------------------------------
@@ -1152,7 +1157,7 @@ wxString& wxString::operator=(const wchar_t *pwz)
 
 wxString operator+(const wxString& str1, const wxString& str2)
 {
-#if !wxUSE_STL
+#if !wxUSE_STL_BASED_WXSTRING
     wxASSERT( str1.GetStringData()->IsValid() );
     wxASSERT( str2.GetStringData()->IsValid() );
 #endif
@@ -1163,9 +1168,9 @@ wxString operator+(const wxString& str1, const wxString& str2)
     return s;
 }
 
-wxString operator+(const wxString& str, wxChar ch)
+wxString operator+(const wxString& str, wxUniChar ch)
 {
-#if !wxUSE_STL
+#if !wxUSE_STL_BASED_WXSTRING
     wxASSERT( str.GetStringData()->IsValid() );
 #endif
 
@@ -1175,9 +1180,9 @@ wxString operator+(const wxString& str, wxChar ch)
     return s;
 }
 
-wxString operator+(wxChar ch, const wxString& str)
+wxString operator+(wxUniChar ch, const wxString& str)
 {
-#if !wxUSE_STL
+#if !wxUSE_STL_BASED_WXSTRING
     wxASSERT( str.GetStringData()->IsValid() );
 #endif
 
@@ -1189,7 +1194,7 @@ wxString operator+(wxChar ch, const wxString& str)
 
 wxString operator+(const wxString& str, const wxChar *psz)
 {
-#if !wxUSE_STL
+#if !wxUSE_STL_BASED_WXSTRING
     wxASSERT( str.GetStringData()->IsValid() );
 #endif
 
@@ -1205,7 +1210,7 @@ wxString operator+(const wxString& str, const wxChar *psz)
 
 wxString operator+(const wxChar *psz, const wxString& str)
 {
-#if !wxUSE_STL
+#if !wxUSE_STL_BASED_WXSTRING
     wxASSERT( str.GetStringData()->IsValid() );
 #endif
 
@@ -1415,7 +1420,7 @@ bool wxString::EndsWith(const wxChar *suffix, wxString *rest) const
     wxASSERT_MSG( suffix, _T("invalid parameter in wxString::EndssWith") );
 
     int start = length() - wxStrlen(suffix);
-    if ( start < 0 || wxStrcmp(c_str() + start, suffix) != 0 )
+    if ( start < 0 || wxStrcmp(wx_str() + start, suffix) != 0 )
         return false;
 
     if ( rest )
@@ -1443,14 +1448,14 @@ wxString wxString::Right(size_t nCount) const
 
 // get all characters after the last occurence of ch
 // (returns the whole string if ch not found)
-wxString wxString::AfterLast(wxChar ch) const
+wxString wxString::AfterLast(wxUniChar ch) const
 {
   wxString str;
   int iPos = Find(ch, true);
   if ( iPos == wxNOT_FOUND )
     str = *this;
   else
-    str = c_str() + iPos + 1;
+    str = wx_str() + iPos + 1;
 
   return str;
 }
@@ -1470,7 +1475,7 @@ wxString wxString::Left(size_t nCount) const
 
 // get all characters before the first occurence of ch
 // (returns the whole string if ch not found)
-wxString wxString::BeforeFirst(wxChar ch) const
+wxString wxString::BeforeFirst(wxUniChar ch) const
 {
   int iPos = Find(ch);
   if ( iPos == wxNOT_FOUND ) iPos = length();
@@ -1479,7 +1484,7 @@ wxString wxString::BeforeFirst(wxChar ch) const
 
 /// get all characters before the last occurence of ch
 /// (returns empty string if ch not found)
-wxString wxString::BeforeLast(wxChar ch) const
+wxString wxString::BeforeLast(wxUniChar ch) const
 {
   wxString str;
   int iPos = Find(ch, true);
@@ -1491,12 +1496,12 @@ wxString wxString::BeforeLast(wxChar ch) const
 
 /// get all characters after the first occurence of ch
 /// (returns empty string if ch not found)
-wxString wxString::AfterFirst(wxChar ch) const
+wxString wxString::AfterFirst(wxUniChar ch) const
 {
   wxString str;
   int iPos = Find(ch);
   if ( iPos != wxNOT_FOUND )
-    str = c_str() + iPos + 1;
+    str = wx_str() + iPos + 1;
 
   return str;
 }
@@ -1653,7 +1658,7 @@ wxString& wxString::Trim(bool bFromRight)
 }
 
 // adds nCount characters chPad to the string from either side
-wxString& wxString::Pad(size_t nCount, wxChar chPad, bool bFromRight)
+wxString& wxString::Pad(size_t nCount, wxUniChar chPad, bool bFromRight)
 {
     wxString s(chPad, nCount);
 
@@ -1685,7 +1690,7 @@ wxString& wxString::Truncate(size_t uiLen)
 // ---------------------------------------------------------------------------
 
 // find a character
-int wxString::Find(wxChar ch, bool bFromEnd) const
+int wxString::Find(wxUniChar ch, bool bFromEnd) const
 {
     size_type idx = bFromEnd ? find_last_of(ch) : find_first_of(ch);
 
@@ -1734,18 +1739,18 @@ bool wxStringToIntType(const wxChar *start,
 
 bool wxString::ToLong(long *val, int base) const
 {
-    return wxStringToIntType(c_str(), val, base, wxStrtol);
+    return wxStringToIntType((const wxChar*)c_str(), val, base, wxStrtol);
 }
 
 bool wxString::ToULong(unsigned long *val, int base) const
 {
-    return wxStringToIntType(c_str(), val, base, wxStrtoul);
+    return wxStringToIntType((const wxChar*)c_str(), val, base, wxStrtoul);
 }
 
 bool wxString::ToLongLong(wxLongLong_t *val, int base) const
 {
 #ifdef wxHAS_STRTOLL
-    return wxStringToIntType(c_str(), val, base, wxStrtoll);
+    return wxStringToIntType((const wxChar*)c_str(), val, base, wxStrtoll);
 #else
     // TODO: implement this ourselves
     wxUnusedVar(val);
@@ -1757,7 +1762,7 @@ bool wxString::ToLongLong(wxLongLong_t *val, int base) const
 bool wxString::ToULongLong(wxULongLong_t *val, int base) const
 {
 #ifdef wxHAS_STRTOLL
-    return wxStringToIntType(c_str(), val, base, wxStrtoull);
+    return wxStringToIntType((const wxChar*)c_str(), val, base, wxStrtoull);
 #else
     // TODO: implement this ourselves
     wxUnusedVar(val);
@@ -1792,13 +1797,17 @@ bool wxString::ToDouble(double *val) const
 // ---------------------------------------------------------------------------
 
 /* static */
-wxString wxString::Format(const wxChar *pszFormat, ...)
+#ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
+wxString wxStringPrintfMixinBase::DoFormat(const wxChar *format, ...)
+#else
+wxString wxString::DoFormat(const wxChar *format, ...)
+#endif
 {
     va_list argptr;
-    va_start(argptr, pszFormat);
+    va_start(argptr, format);
 
     wxString s;
-    s.PrintfV(pszFormat, argptr);
+    s.PrintfV(format, argptr);
 
     va_end(argptr);
 
@@ -1806,26 +1815,39 @@ wxString wxString::Format(const wxChar *pszFormat, ...)
 }
 
 /* static */
-wxString wxString::FormatV(const wxChar *pszFormat, va_list argptr)
+wxString wxString::FormatV(const wxString& format, va_list argptr)
 {
     wxString s;
-    s.PrintfV(pszFormat, argptr);
+    s.PrintfV(format, argptr);
     return s;
 }
 
-int wxString::Printf(const wxChar *pszFormat, ...)
+#ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
+int wxStringPrintfMixinBase::DoPrintf(const wxChar *format, ...)
+#else
+int wxString::DoPrintf(const wxChar *format, ...)
+#endif
 {
     va_list argptr;
-    va_start(argptr, pszFormat);
+    va_start(argptr, format);
+
+#ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
+    // get a pointer to the wxString instance; we have to use dynamic_cast<>
+    // because it's the only cast that works safely for downcasting when
+    // multiple inheritance is used:
+    wxString *str = static_cast<wxString*>(this);
+#else
+    wxString *str = this;
+#endif
 
-    int iLen = PrintfV(pszFormat, argptr);
+    int iLen = str->PrintfV(format, argptr);
 
     va_end(argptr);
 
     return iLen;
 }
 
-int wxString::PrintfV(const wxChar* pszFormat, va_list argptr)
+int wxString::PrintfV(const wxString& format, va_list argptr)
 {
     int size = 1024;
 
@@ -1844,7 +1866,7 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr)
         // only a copy
         va_list argptrcopy;
         wxVaCopy(argptrcopy, argptr);
-        int len = wxVsnprintf(buf, size, pszFormat, argptrcopy);
+        int len = wxVsnprintf(buf, size, format, argptrcopy);
         va_end(argptrcopy);
 
         // some implementations of vsnprintf() don't NUL terminate
@@ -2036,7 +2058,7 @@ match:
 }
 
 // Count the number of chars
-int wxString::Freq(wxChar ch) const
+int wxString::Freq(wxUniChar ch) const
 {
     int count = 0;
     int len = length();
@@ -2055,15 +2077,6 @@ wxString wxString::Upper() const
 // convert to lower case, return the copy of the string
 wxString wxString::Lower() const { wxString s(*this); return s.MakeLower(); }
 
-int wxString::sprintf(const wxChar *pszFormat, ...)
-  {
-    va_list argptr;
-    va_start(argptr, pszFormat);
-    int iLen = PrintfV(pszFormat, argptr);
-    va_end(argptr);
-    return iLen;
-  }
-
 // ============================================================================
 // ArrayString
 // ============================================================================
@@ -2514,3 +2527,106 @@ int wxCMPFUNC_CONV wxStringSortDescending(wxString* s1, wxString* s2)
 {
     return -s1->Cmp(*s2);
 }
+
+
+
+// ===========================================================================
+// wxJoin and wxSplit
+// ===========================================================================
+
+#include "wx/tokenzr.h"
+
+wxString wxJoin(const wxArrayString& arr, const wxChar sep, const wxChar escape)
+{
+    size_t count = arr.size();
+    if ( count == 0 )
+        return wxEmptyString;
+
+    wxString str;
+
+    // pre-allocate memory using the estimation of the average length of the
+    // strings in the given array: this is very imprecise, of course, but
+    // better than nothing
+    str.reserve(count*(arr[0].length() + arr[count-1].length()) / 2);
+
+    if ( escape == wxT('\0') )
+    {
+        // escaping is disabled:
+        for ( size_t i = 0; i < count; i++ )
+        {
+            if ( i )
+                str += sep;
+            str += arr[i];
+        }
+    }
+    else // use escape character
+    {
+        for ( size_t n = 0; n < count; n++ )
+        {
+            if ( n )
+                str += sep;
+
+            for ( wxString::const_iterator i = arr[n].begin(),
+                                         end = arr[n].end();
+                  i != end;
+                  ++i )
+            {
+                const wxChar ch = *i;
+                if ( ch == sep )
+                    str += escape;      // escape this separator
+                str += ch;
+            }
+        }
+    }
+
+    str.Shrink(); // release extra memory if we allocated too much
+    return str;
+}
+
+wxArrayString wxSplit(const wxString& str, const wxChar sep, const wxChar escape)
+{
+    if ( escape == wxT('\0') )
+    {
+        // simple case: we don't need to honour the escape character
+        return wxStringTokenize(str, sep, wxTOKEN_RET_EMPTY_ALL);
+    }
+
+    wxArrayString ret;
+    wxString curr;
+    wxChar prev = wxT('\0');
+
+    for ( wxString::const_iterator i = str.begin(),
+                                 end = str.end();
+          i != end;
+          ++i )
+    {
+        const wxChar ch = *i;
+
+        if ( ch == sep )
+        {
+            if ( prev == escape )
+            {
+                // remove the escape character and don't consider this
+                // occurrence of 'sep' as a real separator
+                *curr.rbegin() = sep;
+            }
+            else // real separator
+            {
+                ret.push_back(curr);
+                curr.clear();
+            }
+        }
+        else // normal character
+        {
+            curr += ch;
+        }
+
+        prev = ch;
+    }
+
+    // add the last token
+    if ( !curr.empty() || prev == sep )
+        ret.Add(curr);
+
+    return ret;
+}