X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/04abe4bc8fbddf68ecc9950e2e743e3746ab26b6..7708a267207473783f88cae047b78adaecf83675:/src/common/string.cpp diff --git a/src/common/string.cpp b/src/common/string.cpp index 6cdcaef003..aa045dc5ff 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -45,6 +45,7 @@ #include #endif +#include // 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 +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, @@ -210,29 +294,9 @@ void wxString::UngetWriteBuf(size_t nLen) // all functions are inline in string.h // --------------------------------------------------------------------------- -// assignment operators +// concatenation operators // --------------------------------------------------------------------------- -#if !wxUSE_UNICODE - -// same as 'signed char' variant -wxString& wxString::operator=(const unsigned char* psz) -{ - *this = (const char *)psz; - return *this; -} - -#if wxUSE_WCHAR_T -wxString& wxString::operator=(const wchar_t *pwz) -{ - wxString str(pwz); - swap(str); - return *this; -} -#endif - -#endif - /* * concatenation functions come in 5 flavours: * string + string @@ -961,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; @@ -1151,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 // ---------------------------------------------------------------------------- @@ -1376,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 @@ -1427,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; @@ -1529,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(); } -