//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
// ----------------------------------------------------------------------------
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();
}
}
}
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
return *this;
}
+wxString& wxString::MakeCapitalized()
+{
+ const iterator en = end();
+ iterator it = begin();
+ if ( it != en )
+ {
+ *it = (wxChar)wxToupper(*it);
+ for ( ++it; it != en; ++it )
+ *it = (wxChar)wxTolower(*it);
+ }
+
+ return *this;
+}
+
// ---------------------------------------------------------------------------
// trimming and padding
// ---------------------------------------------------------------------------
return count;
}
-// convert to upper case, return the copy of the string
-wxString wxString::Upper() const
-{ wxString s(*this); return s.MakeUpper(); }
-
-// convert to lower case, return the copy of the string
-wxString wxString::Lower() const { wxString s(*this); return s.MakeLower(); }
-
// ----------------------------------------------------------------------------
// wxUTF8StringBuffer
// ----------------------------------------------------------------------------
wbuf.SetLength(wlen);
}
#endif // wxUSE_UNICODE_WCHAR
+
+// ----------------------------------------------------------------------------
+// wxCharBufferType<T>
+// ----------------------------------------------------------------------------
+
+#ifndef __VMS_BROKEN_TEMPLATES
+template<>
+#endif
+wxCharTypeBuffer<char>::Data
+wxCharTypeBuffer<char>::NullData(NULL);
+
+#ifndef __VMS_BROKEN_TEMPLATES
+template<>
+#endif
+wxCharTypeBuffer<wchar_t>::Data
+wxCharTypeBuffer<wchar_t>::NullData(NULL);