]> git.saurik.com Git - wxWidgets.git/blobdiff - src/common/string.cpp
don't build wxscintilla lib if wxSTC is not built
[wxWidgets.git] / src / common / string.cpp
index ae7d1af85cbcf371256f63083134664e4d3f1d20..aa045dc5ff31501c48732b70c56b6d6fe4609bf8 100644 (file)
@@ -45,6 +45,7 @@
     #include <clib.h>
 #endif
 
+#include <wx/hashmap.h>
 
 // string handling functions used by wxString:
 #if wxUSE_UNICODE_UTF8
@@ -104,6 +105,78 @@ wxSTD ostream& operator<<(wxSTD ostream& os, const wxWCharBuffer& str)
 
 #endif // wxUSE_STD_IOSTREAM
 
+// ----------------------------------------------------------------------------
+// wxCStrData converted strings caching
+// ----------------------------------------------------------------------------
+
+// For backward compatibility reasons, it must be possible to assign the value
+// returned by wxString::c_str() to a char* or wchar_t* variable and work with
+// it. Returning wxCharBuffer from (const char*)c_str() wouldn't do the trick,
+// because the memory would be freed immediately, but it has to be valid as long
+// as the string is not modified, so that code like this still works:
+//
+// const wxChar *s = str.c_str();
+// while ( s ) { ... }
+
+// FIXME-UTF8: not thread safe!
+// FIXME-UTF8: we currently clear the cached conversion only when the string is
+//             destroyed, but we should do it when the string is modified, to
+//             keep memory usage down
+// FIXME-UTF8: we do the conversion every time As[W]Char() is called, but if we
+//             invalidated the cache on every change, we could keep the previous
+//             conversion
+// FIXME-UTF8: add tracing of usage of these two methods - new code is supposed
+//             to use mb_str() or wc_str() instead of (const [w]char*)c_str()
+
+template<typename T>
+static inline void DeleteStringFromConversionCache(T& hash, const wxString *s)
+{
+    typename T::iterator i = hash.find(wxConstCast(s, wxString));
+    if ( i != hash.end() )
+    {
+        free(i->second);
+        hash.erase(i);
+    }
+}
+
+#if wxUSE_UNICODE
+// NB: non-STL implementation doesn't compile with "const wxString*" key type,
+//     so we have to use wxString* here and const-cast when used
+WX_DECLARE_HASH_MAP(wxString*, char*, wxPointerHash, wxPointerEqual,
+                    wxStringCharConversionCache);
+static wxStringCharConversionCache gs_stringsCharCache;
+
+const char* wxCStrData::AsChar() const
+{
+    // remove previously cache value, if any (see FIXMEs above):
+    DeleteStringFromConversionCache(gs_stringsCharCache, m_str);
+
+    // convert the string and keep it:
+    const char *s = gs_stringsCharCache[wxConstCast(m_str, wxString)] =
+        m_str->mb_str().release();
+
+    return s + m_offset;
+}
+#endif // wxUSE_UNICODE
+
+#if !wxUSE_UNICODE_WCHAR
+WX_DECLARE_HASH_MAP(wxString*, wchar_t*, wxPointerHash, wxPointerEqual,
+                    wxStringWCharConversionCache);
+static wxStringWCharConversionCache gs_stringsWCharCache;
+
+const wchar_t* wxCStrData::AsWChar() const
+{
+    // remove previously cache value, if any (see FIXMEs above):
+    DeleteStringFromConversionCache(gs_stringsWCharCache, m_str);
+
+    // convert the string and keep it:
+    const wchar_t *s = gs_stringsWCharCache[wxConstCast(m_str, wxString)] =
+        m_str->wc_str().release();
+
+    return s + m_offset;
+}
+#endif // !wxUSE_UNICODE_WCHAR
+
 // ===========================================================================
 // wxString class core
 // ===========================================================================
@@ -112,6 +185,17 @@ wxSTD ostream& operator<<(wxSTD ostream& os, const wxWCharBuffer& str)
 // construction and conversion
 // ---------------------------------------------------------------------------
 
+wxString::~wxString()
+{
+#if wxUSE_UNICODE
+    // FIXME-UTF8: do this only if locale is not UTF8 if wxUSE_UNICODE_UTF8
+    DeleteStringFromConversionCache(gs_stringsCharCache, this);
+#endif
+#if !wxUSE_UNICODE_WCHAR
+    DeleteStringFromConversionCache(gs_stringsWCharCache, this);
+#endif
+}
+
 #if wxUSE_UNICODE
 /* static */
 wxString::SubstrBufFromMB wxString::ConvertStr(const char *psz, size_t nLength,
@@ -941,32 +1025,32 @@ wxString wxString::AfterFirst(wxUniChar ch) const
 }
 
 // replace first (or all) occurences of some substring with another one
-size_t wxString::Replace(const wxChar *szOld,
-                  const wxChar *szNew, bool bReplaceAll)
+size_t wxString::Replace(const wxString& strOld,
+                         const wxString& strNew, bool bReplaceAll)
 {
     // if we tried to replace an empty string we'd enter an infinite loop below
-    wxCHECK_MSG( szOld && *szOld && szNew, 0,
+    wxCHECK_MSG( !strOld.empty(), 0,
                  _T("wxString::Replace(): invalid parameter") );
 
     size_t uiCount = 0;   // count of replacements made
 
-    size_t uiOldLen = wxStrlen(szOld);
-    size_t uiNewLen = wxStrlen(szNew);
+    size_t uiOldLen = strOld.length();
+    size_t uiNewLen = strNew.length();
 
     size_t dwPos = 0;
 
-    while ( this->c_str()[dwPos] != wxT('\0') )
+    while ( (*this)[dwPos] != wxT('\0') )
     {
         //DO NOT USE STRSTR HERE
         //this string can contain embedded null characters,
         //so strstr will function incorrectly
-        dwPos = find(szOld, dwPos);
+        dwPos = find(strOld, dwPos);
         if ( dwPos == npos )
             break;                  // exit the loop
         else
         {
             //replace this occurance of the old string with the new one
-            replace(dwPos, uiOldLen, szNew, uiNewLen);
+            replace(dwPos, uiOldLen, strNew, uiNewLen);
 
             //move up pos past the string that was replaced
             dwPos += uiNewLen;
@@ -1131,14 +1215,6 @@ int wxString::Find(wxUniChar ch, bool bFromEnd) const
     return (idx == npos) ? wxNOT_FOUND : (int)idx;
 }
 
-// find a sub-string (like strstr)
-int wxString::Find(const wxChar *pszSub) const
-{
-    size_type idx = find(pszSub);
-
-    return (idx == npos) ? wxNOT_FOUND : (int)idx;
-}
-
 // ----------------------------------------------------------------------------
 // conversion to numbers
 // ----------------------------------------------------------------------------
@@ -1356,7 +1432,7 @@ int wxString::PrintfV(const wxString& format, va_list argptr)
 // returns true if the string matches the pattern which may contain '*' and
 // '?' metacharacters (as usual, '?' matches any character and '*' any number
 // of them)
-bool wxString::Matches(const wxChar *pszMask) const
+bool wxString::Matches(const wxString& mask) const
 {
     // I disable this code as it doesn't seem to be faster (in fact, it seems
     // to be much slower) than the old, hand-written code below and using it
@@ -1407,8 +1483,17 @@ bool wxString::Matches(const wxChar *pszMask) const
 #else // !wxUSE_REGEX
   // TODO: this is, of course, awfully inefficient...
 
+  // FIXME-UTF8: implement using iterators, remove #if
+#if wxUSE_UNICODE_UTF8
+  wxWCharBuffer maskBuf = mask.wc_str();
+  wxWCharBuffer txtBuf = wc_str();
+  const wxChar *pszMask = maskBuf.data();
+  const wxChar *pszTxt = txtBuf.data();
+#else
+  const wxChar *pszMask = mask.wx_str();
   // the char currently being checked
-  const wxChar *pszTxt = c_str();
+  const wxChar *pszTxt = wx_str();
+#endif
 
   // the last location where '*' matched
   const wxChar *pszLastStarInText = NULL;
@@ -1509,4 +1594,3 @@ wxString wxString::Upper() const
 
 // convert to lower case, return the copy of the string
 wxString wxString::Lower() const { wxString s(*this); return s.MakeLower(); }
-