// 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
// portable strcasecmp/_stricmp
wxDEPRECATED( inline int Stricmp(const char *psz1, const char *psz2) );
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
inline ~wxCStrData();
- // methods defined inline below must be declared inline or mingw32 3.4.5
- // warns about "<symbol> defined locally after being referenced with
- // dllimport linkage"
-#if wxUSE_UNICODE_WCHAR
- inline
-#endif
- const wchar_t* AsWChar() const;
+ // AsWChar() and AsChar() can't be defined here as they use wxString and so
+ // must come after it and because of this won't be inlined when called from
+ // wxString methods (without a lot of work to extract these wxString methods
+ // from inside the class itself). But we still define them being inline
+ // below to let compiler inline them from elsewhere. And because of this we
+ // must declare them as inline here because otherwise some compilers give
+ // warnings about them, e.g. mingw32 3.4.5 warns about "<symbol> defined
+ // locally after being referenced with dllimport linkage" while IRIX
+ // mipsPro 7.4 warns about "function declared inline after being called".
+ inline const wchar_t* AsWChar() const;
operator const wchar_t*() const { return AsWChar(); }
-#if !wxUSE_UNICODE || wxUSE_UTF8_LOCALE_ONLY
- inline
-#endif
- const char* AsChar() const;
+ inline const char* AsChar() const;
const unsigned char* AsUnsignedChar() const
{ return (const unsigned char *) AsChar(); }
operator const char*() const { return AsChar(); }
wxCStrData operator-(ptrdiff_t n) const
{
wxASSERT_MSG( n <= (ptrdiff_t)m_offset,
- _T("attempt to construct address before the beginning of the string") );
+ wxT("attempt to construct address before the beginning of the string") );
return wxCStrData(m_str, m_offset - n, m_owned);
}
#ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
// "non dll-interface class 'wxStringPrintfMixin' used as base interface
// for dll-interface class 'wxString'" -- this is OK in our case
+ #pragma warning (push)
#pragma warning (disable:4275)
#endif
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*:
-#if wxUSE_STL
+ // 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:
#if wxUSE_UNICODE_WCHAR && wxUSE_STL_BASED_WXSTRING
- // wxStringImpl is std::string in the encoding we want
- operator const wxStdWideString&() const { return m_impl; }
+ #define wxStringToStdWstringRetType const wxStdWideString&
+ const wxStdWideString& ToStdWstring() const { return m_impl; }
#else
// wxStringImpl is either not std::string or needs conversion
- operator wxStdWideString() const
+ #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
#if (!wxUSE_UNICODE || wxUSE_UTF8_LOCALE_ONLY) && wxUSE_STL_BASED_WXSTRING
// wxStringImpl is std::string in the encoding we want
- operator const std::string&() const { return m_impl; }
+ #define wxStringToStdStringRetType const std::string&
+ const std::string& ToStdString() const { return m_impl; }
#else
// wxStringImpl is either not std::string or needs conversion
- operator std::string() const
+ #define wxStringToStdStringRetType std::string
+ std::string ToStdString() const
{
wxScopedCharBuffer buf(mb_str());
return std::string(buf.data(), buf.length());
}
#endif
-#endif // wxUSE_STL
+
+#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_STD_STRING_CONV_IN_WXSTRING
+
+#undef wxStringToStdStringRetType
+#undef wxStringToStdWstringRetType
+
+#endif // wxUSE_STD_STRING
wxString Clone() const
{
// get last character
wxUniChar Last() const
{
- wxASSERT_MSG( !empty(), _T("wxString: index out of bounds") );
+ wxASSERT_MSG( !empty(), wxT("wxString: index out of bounds") );
return *rbegin();
}
// get writable last character
wxUniCharRef Last()
{
- wxASSERT_MSG( !empty(), _T("wxString: index out of bounds") );
+ wxASSERT_MSG( !empty(), wxT("wxString: index out of bounds") );
return *rbegin();
}
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
{
#if WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
wxASSERT_MSG( s.IsValid(),
- _T("did you forget to call UngetWriteBuf()?") );
+ wxT("did you forget to call UngetWriteBuf()?") );
#endif
append(s);
// stream-like functions
// insert an int into string
wxString& operator<<(int i)
- { return (*this) << Format(_T("%d"), i); }
+ { return (*this) << Format(wxT("%d"), i); }
// insert an unsigned int into string
wxString& operator<<(unsigned int ui)
- { return (*this) << Format(_T("%u"), ui); }
+ { return (*this) << Format(wxT("%u"), ui); }
// insert a long into string
wxString& operator<<(long l)
- { return (*this) << Format(_T("%ld"), l); }
+ { return (*this) << Format(wxT("%ld"), l); }
// insert an unsigned long into string
wxString& operator<<(unsigned long ul)
- { return (*this) << Format(_T("%lu"), ul); }
-#if defined wxLongLong_t && !defined wxLongLongIsLong
+ { return (*this) << Format(wxT("%lu"), ul); }
+#ifdef wxHAS_LONG_LONG_T_DIFFERENT_FROM_LONG
// insert a long long if they exist and aren't longs
wxString& operator<<(wxLongLong_t ll)
{
- const wxChar *fmt = _T("%") wxLongLongFmtSpec _T("d");
- return (*this) << Format(fmt, ll);
+ return (*this) << Format("%" wxLongLongFmtSpec "d", ll);
}
// insert an unsigned long long
wxString& operator<<(wxULongLong_t ull)
{
- const wxChar *fmt = _T("%") wxLongLongFmtSpec _T("u");
- return (*this) << Format(fmt , ull);
+ 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(_T("%f"), f); }
+ { return (*this) << Format(wxT("%f"), f); }
// insert a double into string
wxString& operator<<(double d)
- { return (*this) << Format(_T("%g"), d); }
+ { return (*this) << Format(wxT("%g"), d); }
// string comparison
// case-sensitive comparison (returns a value < 0, = 0 or > 0)
// 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 ToDouble(double *val) const;
-#if wxUSE_XLOCALE
// conversions to numbers using C locale
// convert to a signed integer
bool ToCLong(long *val, int base = 10) const;
bool ToCULong(unsigned long *val, int base = 10) const;
// convert to a double
bool ToCDouble(double *val) const;
-#endif
-
+
+ // 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
CreateConstIterator(last).impl())
{
wxASSERT_MSG( first.m_str == last.m_str,
- _T("pointers must be into the same string") );
+ wxT("pointers must be into the same string") );
}
#endif // WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER
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);
}
};
#ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
- #pragma warning (default:4275)
+ #pragma warning (pop)
#endif
// string iterator operators that satisfy STL Random Access Iterator
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
inline wxUniChar wxCStrData::operator*() const
{
if ( m_str->empty() )
- return wxUniChar(_T('\0'));
+ return wxUniChar(wxT('\0'));
else
return (*m_str)[m_offset];
}