// Author: Vadim Zeitlin
// Modified by:
// Created: 29/01/98
-// RCS-ID: $Id$
// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
// Licence: wxWindows licence
///////////////////////////////////////////////////////////////////////////////
#include "wx/defs.h" // everybody should include this
-#ifndef __WXPALMOS5__
#if defined(__WXMAC__) || defined(__VISAGECPP__)
#include <ctype.h>
#endif
# include <stdlib.h>
#endif
-#ifdef HAVE_STRCASECMP_IN_STRINGS_H
- #include <strings.h> // for strcasecmp()
-#endif // HAVE_STRCASECMP_IN_STRINGS_H
-#endif // ! __WXPALMOS5__
-
#include "wx/wxcrtbase.h" // for wxChar, wxStrlen() etc.
#include "wx/strvararg.h"
#include "wx/buffer.h" // for wxCharBuffer
// it would have to be re-tested and probably corrected
// CS: under OSX release builds the string destructor/cache cleanup sometimes
// crashes, disable until we find the true reason or a better workaround
-#if wxUSE_UNICODE_UTF8 && !defined(__WXMSW__) && !defined(__WXOSX__)
+#if wxUSE_UNICODE_UTF8 && !defined(__WINDOWS__) && !defined(__WXOSX__)
#define wxUSE_STRING_POS_CACHE 1
#else
#define wxUSE_STRING_POS_CACHE 0
// backwards compatibility only.
// checks whether the passed in pointer is NULL and if the string is empty
-wxDEPRECATED( inline bool IsEmpty(const char *p) );
+wxDEPRECATED_MSG("use wxIsEmpty() instead")
inline bool IsEmpty(const char *p) { return (!p || !*p); }
// safe version of strlen() (returns 0 if passed NULL pointer)
-wxDEPRECATED( inline size_t Strlen(const char *psz) );
+wxDEPRECATED_MSG("use wxStrlen() instead")
inline size_t Strlen(const char *psz)
{ return psz ? strlen(psz) : 0; }
// portable strcasecmp/_stricmp
-wxDEPRECATED( inline int Stricmp(const char *psz1, const char *psz2) );
+wxDEPRECATED_MSG("use wxStricmp() instead")
inline int Stricmp(const char *psz1, const char *psz2)
-{
-#if defined(__VISUALC__) && defined(__WXWINCE__)
- register char c1, c2;
- do {
- c1 = tolower(*psz1++);
- c2 = tolower(*psz2++);
- } while ( c1 && (c1 == c2) );
-
- return c1 - c2;
-#elif defined(__VISUALC__) || ( defined(__MWERKS__) && defined(__INTEL__) )
- return _stricmp(psz1, psz2);
-#elif defined(__SC__)
- return _stricmp(psz1, psz2);
-#elif defined(__BORLANDC__)
- return stricmp(psz1, psz2);
-#elif defined(__WATCOMC__)
- return stricmp(psz1, psz2);
-#elif defined(__DJGPP__)
- return stricmp(psz1, psz2);
-#elif defined(__EMX__)
- return stricmp(psz1, psz2);
-#elif defined(__WXPM__)
- return stricmp(psz1, psz2);
-#elif defined(__WXPALMOS__) || \
- defined(HAVE_STRCASECMP_IN_STRING_H) || \
- defined(HAVE_STRCASECMP_IN_STRINGS_H) || \
- defined(__GNUWIN32__)
- return strcasecmp(psz1, psz2);
-#elif defined(__MWERKS__) && !defined(__INTEL__)
- register char c1, c2;
- do {
- c1 = tolower(*psz1++);
- c2 = tolower(*psz2++);
- } while ( c1 && (c1 == c2) );
-
- return c1 - c2;
-#else
- // almost all compilers/libraries provide this function (unfortunately under
- // different names), that's why we don't implement our own which will surely
- // be more efficient than this code (uncomment to use):
- /*
- register char c1, c2;
- do {
- c1 = tolower(*psz1++);
- c2 = tolower(*psz2++);
- } while ( c1 && (c1 == c2) );
-
- return c1 - c2;
- */
-
- #error "Please define string case-insensitive compare for your OS/compiler"
-#endif // OS/compiler
-}
+ { return wxCRT_StricmpA(psz1, psz2); }
#endif // WXWIN_COMPATIBILITY_2_8
public: \
WX_DEFINE_ITERATOR_CATEGORY(WX_STR_ITERATOR_TAG) \
typedef wxUniChar value_type; \
- typedef int difference_type; \
+ typedef ptrdiff_t difference_type; \
typedef reference_type reference; \
typedef pointer_type pointer; \
\
iterator operator-(ptrdiff_t n) const
{ return iterator(str(), wxStringOperations::AddToIter(m_cur, -n)); }
+ // Normal iterators need to be comparable with the const_iterators so
+ // declare the comparison operators and implement them below after the
+ // full const_iterator declaration.
+ bool operator==(const const_iterator& i) const;
+ bool operator!=(const const_iterator& i) const;
+ bool operator<(const const_iterator& i) const;
+ bool operator>(const const_iterator& i) const;
+ bool operator<=(const const_iterator& i) const;
+ bool operator>=(const const_iterator& i) const;
+
private:
iterator(wxString *wxstr, underlying_iterator ptr)
: m_cur(ptr), m_node(wxstr, &m_cur) {}
const_iterator operator-(ptrdiff_t n) const
{ return const_iterator(str(), wxStringOperations::AddToIter(m_cur, -n)); }
+ // Notice that comparison operators taking non-const iterator are not
+ // needed here because of the implicit conversion from non-const iterator
+ // to const ones ensure that the versions for const_iterator declared
+ // inside WX_STR_ITERATOR_IMPL can be used.
+
private:
// for internal wxString use only:
const_iterator(const wxString *wxstr, underlying_iterator ptr)
iterator operator-(ptrdiff_t n) const
{ return iterator(wxStringOperations::AddToIter(m_cur, -n)); }
+ // As in UTF-8 case above, define comparison operators taking
+ // const_iterator too.
+ bool operator==(const const_iterator& i) const;
+ bool operator!=(const const_iterator& i) const;
+ bool operator<(const const_iterator& i) const;
+ bool operator>(const const_iterator& i) const;
+ bool operator<=(const const_iterator& i) const;
+ bool operator>=(const const_iterator& i) const;
+
private:
// for internal wxString use only:
iterator(underlying_iterator ptr) : m_cur(ptr) {}
const_iterator operator-(ptrdiff_t n) const
{ return const_iterator(wxStringOperations::AddToIter(m_cur, -n)); }
+ // As in UTF-8 case above, we don't need comparison operators taking
+ // iterator because we have an implicit conversion from iterator to
+ // const_iterator so the operators declared by WX_STR_ITERATOR_IMPL will
+ // be used.
+
private:
// for internal wxString use only:
const_iterator(underlying_iterator ptr) : m_cur(ptr) {}
#undef WX_STR_ITERATOR_TAG
#undef WX_STR_ITERATOR_IMPL
+ // This method is mostly used by wxWidgets itself and return the offset of
+ // the given iterator in bytes relative to the start of the buffer
+ // representing the current string contents in the current locale encoding.
+ //
+ // It is inefficient as it involves converting part of the string to this
+ // encoding (and also unsafe as it simply returns 0 if the conversion fails)
+ // and so should be avoided if possible, wx itself only uses it to implement
+ // backwards-compatible API.
+ ptrdiff_t IterOffsetInMBStr(const const_iterator& i) const
+ {
+ const wxString str(begin(), i);
+
+ // This is logically equivalent to strlen(str.mb_str()) but avoids
+ // actually converting the string to multibyte and just computes the
+ // length that it would have after conversion.
+ size_t ofs = wxConvLibc.FromWChar(NULL, 0, str.wc_str(), str.length());
+ return ofs == wxCONV_FAILED ? 0 : static_cast<ptrdiff_t>(ofs);
+ }
+
friend class iterator;
friend class const_iterator;
}
#endif // wxUSE_STRING_POS_CACHE
- // even if we're not built with wxUSE_STL == 1 it is very convenient to allow
- // implicit conversions from std::string to wxString and vice verse as this
- // allows to use the same strings in non-GUI and GUI code, however we don't
- // want to unconditionally add this ctor as it would make wx lib dependent on
- // libstdc++ on some Linux versions which is bad, so instead we ask the
- // client code to define this wxUSE_STD_STRING symbol if they need it
+ // even if we're not built with wxUSE_STD_STRING_CONV_IN_WXSTRING == 1 it is
+ // very convenient to allow implicit conversions from std::string to wxString
+ // and vice verse as this allows to use the same strings in non-GUI and GUI
+ // code, however we don't want to unconditionally add this ctor as it would
+ // make wx lib dependent on libstdc++ on some Linux versions which is bad, so
+ // instead we ask the client code to define this wxUSE_STD_STRING symbol if
+ // they need it
#if wxUSE_STD_STRING
#if wxUSE_UNICODE_WCHAR
wxString(const wxStdWideString& str) : m_impl(str) {}
#endif
#endif // wxUSE_STD_STRING
- // Unlike ctor from std::string, we provide conversion to std::string only
- // if wxUSE_STL and not merely wxUSE_STD_STRING (which is on by default),
- // because it conflicts with operator const char/wchar_t* but we still
- // provide explicit conversions to std::[w]string for convenience in any case
+ // Also always provide explicit conversions to std::[w]string in any case,
+ // see below for the implicit ones.
#if wxUSE_STD_STRING
// We can avoid a copy if we already use this string type internally,
// otherwise we create a copy on the fly:
#define wxStringToStdWstringRetType wxStdWideString
wxStdWideString ToStdWstring() const
{
+#if wxUSE_UNICODE_WCHAR
+ wxScopedWCharBuffer buf =
+ wxScopedWCharBuffer::CreateNonOwned(m_impl.c_str(), m_impl.length());
+#else // !wxUSE_UNICODE_WCHAR
wxScopedWCharBuffer buf(wc_str());
+#endif
+
return wxStdWideString(buf.data(), buf.length());
}
#endif
}
#endif
-#if wxUSE_STL
- // In wxUSE_STL case we also provide implicit conversions as there is no
- // ambiguity with the const char/wchar_t* ones as they are disabled in this
- // build (for consistency with std::basic_string<>)
+#if wxUSE_STD_STRING_CONV_IN_WXSTRING
+ // Implicit conversions to std::[w]string are not provided by default as
+ // they conflict with the implicit conversions to "const char/wchar_t *"
+ // which we use for backwards compatibility but do provide them if
+ // explicitly requested.
operator wxStringToStdStringRetType() const { return ToStdString(); }
operator wxStringToStdWstringRetType() const { return ToStdWstring(); }
-#endif // wxUSE_STL
+#endif // wxUSE_STD_STRING_CONV_IN_WXSTRING
#undef wxStringToStdStringRetType
#undef wxStringToStdWstringRetType
operator wxCStrData() const { return c_str(); }
// the first two operators conflict with operators for conversion to
- // std::string and they must be disabled in STL build; the next one only
- // makes sense if conversions to char* are also defined and not defining it
- // in STL build also helps us to get more clear error messages for the code
- // which relies on implicit conversion to char* in STL build
-#if !wxUSE_STL
+ // std::string and they must be disabled if those conversions are enabled;
+ // the next one only makes sense if conversions to char* are also defined
+ // and not defining it in STL build also helps us to get more clear error
+ // messages for the code which relies on implicit conversion to char* in
+ // STL build
+#if !wxUSE_STD_STRING_CONV_IN_WXSTRING
operator const char*() const { return c_str(); }
operator const wchar_t*() const { return c_str(); }
// wxWidgets versions: this is the same as conversion to const char * so it
// may fail!
operator const void*() const { return c_str(); }
-#endif // wxUSE_STL
+#endif // !wxUSE_STD_STRING_CONV_IN_WXSTRING
// identical to c_str(), for MFC compatibility
const wxCStrData GetData() const { return c_str(); }
// version for NUL-terminated data:
static wxString From8BitData(const char *data)
{ return wxString(data); }
- const char *To8BitData() const { return c_str(); }
+ const wxScopedCharBuffer To8BitData() const
+ { return wxScopedCharBuffer::CreateNonOwned(wx_str(), length()); }
#endif // Unicode/ANSI
// conversions with (possible) format conversions: have to return a
// insert an unsigned long into string
wxString& operator<<(unsigned long ul)
{ return (*this) << Format(wxT("%lu"), ul); }
-#if defined wxLongLong_t && !defined wxLongLongIsLong
+#ifdef wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG
// insert a long long if they exist and aren't longs
wxString& operator<<(wxLongLong_t ll)
{
{
return (*this) << Format("%" wxLongLongFmtSpec "u" , ull);
}
-#endif // wxLongLong_t && !wxLongLongIsLong
+#endif // wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG
// insert a float into string
wxString& operator<<(float f)
{ return (*this) << Format(wxT("%f"), f); }
// get last nCount characters
wxString Right(size_t nCount) const;
// get all characters before the first occurrence of ch
- // (returns the whole string if ch not found)
- wxString BeforeFirst(wxUniChar ch) const;
+ // (returns the whole string if ch not found) and also put everything
+ // following the first occurrence of ch into rest if it's non-NULL
+ wxString BeforeFirst(wxUniChar ch, wxString *rest = NULL) const;
// get all characters before the last occurrence of ch
- // (returns empty string if ch not found)
- wxString BeforeLast(wxUniChar ch) const;
+ // (returns empty string if ch not found) and also put everything
+ // following the last occurrence of ch into rest if it's non-NULL
+ wxString BeforeLast(wxUniChar ch, wxString *rest = NULL) const;
// get all characters after the first occurrence of ch
// (returns empty string if ch not found)
wxString AfterFirst(wxUniChar ch) const;
// convert to a double
bool ToCDouble(double *val) const;
+ // create a string representing the given floating point number with the
+ // default (like %g) or fixed (if precision >=0) precision
+ // in the current locale
+ static wxString FromDouble(double val, int precision = -1);
+ // in C locale
+ static wxString FromCDouble(double val, int precision = -1);
+
#ifndef wxNEEDS_WXSTRING_PRINTF_MIXIN
// formatted input/output
// as sprintf(), returns the number of characters written or < 0 on error
return *this;
}
+ // This is a non-standard-compliant overload taking the first "len"
+ // characters of the source string.
wxString& assign(const wxString& str, size_t len)
{
+#if wxUSE_STRING_POS_CACHE
+ // It is legal to pass len > str.length() to wxStringImpl::assign() but
+ // by restricting it here we save some work for that function so it's not
+ // really less efficient and, at the same time, ensure that we don't
+ // cache invalid length.
+ const size_t lenSrc = str.length();
+ if ( len > lenSrc )
+ len = lenSrc;
+
wxSTRING_SET_CACHED_LENGTH(len);
+#endif // wxUSE_STRING_POS_CACHE
m_impl.assign(str.m_impl, 0, str.LenToImpl(len));
wxString& assign(const char *sz, size_t n)
{
- wxSTRING_SET_CACHED_LENGTH(n);
+ wxSTRING_INVALIDATE_CACHE();
SubstrBufFromMB str(ImplStr(sz, n));
m_impl.assign(str.data, str.len);
void DoUngetWriteBuf(size_t nLen)
{
- wxSTRING_SET_CACHED_LENGTH(nLen);
+ wxSTRING_INVALIDATE_CACHE();
m_impl.DoUngetWriteBuf(nLen);
}
inline bool operator!=(const wxString& s, char c) { return !s.IsSameAs(c); }
inline bool operator!=(const wxString& s, wchar_t c) { return !s.IsSameAs(c); }
+
+// wxString iterators comparisons
+inline bool wxString::iterator::operator==(const const_iterator& i) const
+ { return i == *this; }
+inline bool wxString::iterator::operator!=(const const_iterator& i) const
+ { return i != *this; }
+inline bool wxString::iterator::operator<(const const_iterator& i) const
+ { return i > *this; }
+inline bool wxString::iterator::operator>(const const_iterator& i) const
+ { return i < *this; }
+inline bool wxString::iterator::operator<=(const const_iterator& i) const
+ { return i >= *this; }
+inline bool wxString::iterator::operator>=(const const_iterator& i) const
+ { return i <= *this; }
+
// comparison with C string in Unicode build
#if wxUSE_UNICODE