X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/dd79ca2fd85daac3dd2238043193a5af8b623a85..697c314b162ff4758db0047e548d5401994d2c70:/src/common/string.cpp diff --git a/src/common/string.cpp b/src/common/string.cpp index 16f764f44a..595caf7125 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -58,6 +58,105 @@ //According to STL _must_ be a -1 size_t const size_t wxString::npos = (size_t) -1; +#if wxUSE_STRING_POS_CACHE + +#ifdef wxHAS_COMPILER_TLS + +wxTLS_TYPE(wxString::Cache) wxString::ms_cache; + +#else // !wxHAS_COMPILER_TLS + +struct wxStrCacheInitializer +{ + wxStrCacheInitializer() + { + // calling this function triggers s_cache initialization in it, and + // from now on it becomes safe to call from multiple threads + wxString::GetCache(); + } +}; + +/* +wxString::Cache& wxString::GetCache() +{ + static wxTLS_TYPE(Cache) s_cache; + + return wxTLS_VALUE(s_cache); +} +*/ + +static wxStrCacheInitializer gs_stringCacheInit; + +#endif // wxHAS_COMPILER_TLS/!wxHAS_COMPILER_TLS + +// gdb seems to be unable to display thread-local variables correctly, at least +// not my 6.4.98 version under amd64, so provide this debugging helper to do it +#ifdef __WXDEBUG__ + +struct wxStrCacheDumper +{ + static void ShowAll() + { + puts("*** wxString cache dump:"); + for ( unsigned n = 0; n < wxString::Cache::SIZE; n++ ) + { + const wxString::Cache::Element& + c = wxString::GetCacheBegin()[n]; + + printf("\t%u%s\t%p: pos=(%lu, %lu), len=%ld\n", + n, + n == wxString::LastUsedCacheElement() ? " [*]" : "", + c.str, + (unsigned long)c.pos, + (unsigned long)c.impl, + (long)c.len); + } + } +}; + +void wxDumpStrCache() { wxStrCacheDumper::ShowAll(); } + +#endif // __WXDEBUG__ + +#ifdef wxPROFILE_STRING_CACHE + +wxString::CacheStats wxString::ms_cacheStats; + +struct wxStrCacheStatsDumper +{ + ~wxStrCacheStatsDumper() + { + const wxString::CacheStats& stats = wxString::ms_cacheStats; + + if ( stats.postot ) + { + puts("*** wxString cache statistics:"); + printf("\tTotal non-trivial calls to PosToImpl(): %u\n", + stats.postot); + printf("\tHits %u (of which %u not used) or %.2f%%\n", + stats.poshits, + stats.mishits, + 100.*float(stats.poshits - stats.mishits)/stats.postot); + printf("\tAverage position requested: %.2f\n", + float(stats.sumpos) / stats.postot); + printf("\tAverage offset after cached hint: %.2f\n", + float(stats.sumofs) / stats.postot); + } + + if ( stats.lentot ) + { + printf("\tNumber of calls to length(): %u, hits=%.2f%%\n", + stats.lentot, 100.*float(stats.lenhits)/stats.lentot); + } + } +}; + +static wxStrCacheStatsDumper s_showCacheStats; + +#endif // wxPROFILE_STRING_CACHE + +#endif // wxUSE_STRING_POS_CACHE + // ---------------------------------------------------------------------------- // global functions // ---------------------------------------------------------------------------- @@ -123,22 +222,30 @@ void wxString::PosLenToImpl(size_t pos, size_t len, size_t *implPos, size_t *implLen) const { if ( pos == npos ) + { *implPos = npos; - else + } + else // have valid start position { - const_iterator i = begin() + pos; - *implPos = wxStringImpl::const_iterator(i.impl()) - m_impl.begin(); + const const_iterator b = GetIterForNthChar(pos); + *implPos = wxStringImpl::const_iterator(b.impl()) - m_impl.begin(); if ( len == npos ) + { *implLen = npos; - else + } + else // have valid length too { - // too large length is interpreted as "to the end of the string" - // FIXME-UTF8: verify this is the case in std::string, assert - // otherwise - if ( pos + len > length() ) - len = length() - pos; - - *implLen = (i + len).impl() - i.impl(); + // we need to handle the case of length specifying a substring + // going beyond the end of the string, just as std::string does + const const_iterator e(end()); + const_iterator i(b); + while ( len && i <= e ) + { + ++i; + --len; + } + + *implLen = i.impl() - b.impl(); } } } @@ -1237,6 +1344,8 @@ size_t wxString::Replace(const wxString& strOld, wxCHECK_MSG( !strOld.empty(), 0, _T("wxString::Replace(): invalid parameter") ); + wxSTRING_INVALIDATE_CACHE(); + size_t uiCount = 0; // count of replacements made // optimize the special common case: replacement of one character by @@ -2009,3 +2118,19 @@ wxUTF8StringBufferLength::~wxUTF8StringBufferLength() wbuf.SetLength(wlen); } #endif // wxUSE_UNICODE_WCHAR + +// ---------------------------------------------------------------------------- +// wxCharBufferType +// ---------------------------------------------------------------------------- + +#ifndef __VMS_BROKEN_TEMPLATES +template<> +#endif +wxCharTypeBuffer::Data +wxCharTypeBuffer::NullData(NULL); + +#ifndef __VMS_BROKEN_TEMPLATES +template<> +#endif +wxCharTypeBuffer::Data +wxCharTypeBuffer::NullData(NULL);