fi
+if test "$wxUSE_STL" = "yes"; then
+ ac_ext=cc
+ac_cpp='$CXXCPP $CPPFLAGS'
+ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_cxx_compiler_gnu
+
+
+ echo "$as_me:$LINENO: checking for basic STL functionality" >&5
+echo $ECHO_N "checking for basic STL functionality... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string>
+ #include <functional>
+ #include <algorithm>
+ #include <vector>
+ #include <list>
+int
+main ()
+{
+std::vector<int> moo;
+ std::list<int> foo;
+ std::vector<int>::iterator it =
+ std::find_if(moo.begin(), moo.end(),
+ std::bind2nd(std::less<int>(), 3));
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+ { { echo "$as_me:$LINENO: error: Basic STL functionality missing" >&5
+echo "$as_me: error: Basic STL functionality missing" >&2;}
+ { (exit 1); exit 1; }; }
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+
+ echo "$as_me:$LINENO: checking for std::wstring in <string>" >&5
+echo $ECHO_N "checking for std::wstring in <string>... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string>
+int
+main ()
+{
+std::wstring foo;
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_STD_WSTRING 1
+_ACEOF
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+
+ echo "$as_me:$LINENO: checking for compliant std::string::compare" >&5
+echo $ECHO_N "checking for compliant std::string::compare... $ECHO_C" >&6
+ cat >conftest.$ac_ext <<_ACEOF
+#line $LINENO "configure"
+/* confdefs.h. */
+_ACEOF
+cat confdefs.h >>conftest.$ac_ext
+cat >>conftest.$ac_ext <<_ACEOF
+/* end confdefs.h. */
+#include <string>
+int
+main ()
+{
+std::string foo, bar;
+ foo.compare(bar);
+ foo.compare(1, 1, bar);
+ foo.compare(1, 1, bar, 1, 1);
+ foo.compare("");
+ foo.compare(1, 1, "");
+ foo.compare(1, 1, "", 2);
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.$ac_objext
+if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
+ (eval $ac_compile) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); } &&
+ { ac_try='test -s conftest.$ac_objext'
+ { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ echo "$as_me:$LINENO: \$? = $ac_status" >&5
+ (exit $ac_status); }; }; then
+ echo "$as_me:$LINENO: result: yes" >&5
+echo "${ECHO_T}yes" >&6
+ cat >>confdefs.h <<\_ACEOF
+#define HAVE_STD_STRING_COMPARE 1
+_ACEOF
+
+else
+ echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+echo "$as_me:$LINENO: result: no" >&5
+echo "${ECHO_T}no" >&6
+fi
+rm -f conftest.$ac_objext conftest.$ac_ext
+
+ ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+fi
+
SEARCH_INCLUDE="\
/usr/local/include \
dnl check whether C++ compiler supports C++ casts
AC_CXX_CONST_CAST
+dnl check various STL features
+if test "$wxUSE_STL" = "yes"; then
+ AC_LANG_PUSH(C++)
+
+ dnl check for basic STL functionality
+ AC_MSG_CHECKING([for basic STL functionality])
+ AC_TRY_COMPILE([#include <string>
+ #include <functional>
+ #include <algorithm>
+ #include <vector>
+ #include <list>],
+ [std::vector<int> moo;
+ std::list<int> foo;
+ std::vector<int>::iterator it =
+ std::find_if(moo.begin(), moo.end(),
+ std::bind2nd(std::less<int>(), 3));],
+ [AC_MSG_RESULT([yes])],
+ [AC_MSG_RESULT([no])
+ AC_MSG_ERROR([Basic STL functionality missing])])
+
+ dnl check if <string> declares std::wstring
+ AC_MSG_CHECKING([for std::wstring in <string>])
+ AC_TRY_COMPILE([#include <string>],
+ [std::wstring foo;],
+ [AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_STD_WSTRING)],
+ [AC_MSG_RESULT(no)])
+
+ dnl check for compliant std::string::compare
+ AC_MSG_CHECKING([for compliant std::string::compare])
+ AC_TRY_COMPILE([#include <string>],
+ [std::string foo, bar;
+ foo.compare(bar);
+ foo.compare(1, 1, bar);
+ foo.compare(1, 1, bar, 1, 1);
+ foo.compare("");
+ foo.compare(1, 1, "");
+ foo.compare(1, 1, "", 2);],
+ [AC_MSG_RESULT(yes)
+ AC_DEFINE(HAVE_STD_STRING_COMPARE)],
+ [AC_MSG_RESULT(no)])
+
+ AC_LANG_POP
+fi
+
dnl ---------------------------------------------------------------------------
dnl Define search path for includes and libraries: all headers and libs will be
dnl looked for in all directories of this path
// check for explicit keyword support
#ifndef HAVE_EXPLICIT
#if defined(__VISUALC__) && (__VISUALC__ >= 1100)
- // VC++ 6.0 and 5.0 have explicit (what about the earlier versions?)
+ // VC++ 6.0 and 5.0 have explicit (what about earlier versions?)
#define HAVE_EXPLICIT
#elif ( defined(__MINGW32__) || defined(__CYGWIN32__) ) \
&& wxCHECK_GCC_VERSION(2, 95)
// check for static/const/reinterpret_cast<>()
#ifndef HAVE_STATIC_CAST
#if defined(__VISUALC__) && (__VISUALC__ >= 1100)
- // VC++ 6.0 and 5.0 have C++ casts (what about the earlier versions?)
+ // VC++ 6.0 and 5.0 have C++ casts (what about earlier versions?)
#define HAVE_CXX_CASTS
#elif ( defined(__MINGW32__) || defined(__CYGWIN32__) ) \
&& wxCHECK_GCC_VERSION(2, 95)
#endif
#endif // HAVE_CXX_CASTS
+#ifndef HAVE_STD_WSTRING
+ #if defined(__VISUALC__) && (__VISUALC__ >= 1100)
+ // VC++ 6.0 and 5.0 have std::wstring (what about earlier versions?)
+ #define HAVE_STD_WSTRING
+ #elif ( defined(__MINGW32__) || defined(__CYGWIN32__) ) \
+ && wxCHECK_GCC_VERSION(3, 1)
+ // GCC 3.1 has std::wstring; 3.0 never was in MinGW, 2.95 hasn't it
+ #define HAVE_STD_WSTRING
+ #endif
+#endif
+
+#ifndef HAVE_STD_STRING_COMPARE
+ #if defined(__VISUALC__) && (__VISUALC__ >= 1100)
+ // VC++ 6.0 and 5.0 have std::string::compare
+ // (what about earlier versions?)
+ #define HAVE_STD_STRING_COMPARE
+ #elif ( defined(__MINGW32__) || defined(__CYGWIN32__) ) \
+ && wxCHECK_GCC_VERSION(3, 1)
+ // GCC 3.1 has std::string::compare;
+ // 3.0 never was in MinGW, 2.95 hasn't it
+ #define HAVE_STD_STRING_COMPARE
+ #endif
+#endif
+
// ----------------------------------------------------------------------------
// portable calling conventions macros
// ----------------------------------------------------------------------------
#pragma interface "string.h"
#endif
-// ----------------------------------------------------------------------------
-// conditinal compilation
-// ----------------------------------------------------------------------------
-
-// compile the std::string compatibility functions if defined
-#define wxSTD_STRING_COMPATIBILITY
-
// ----------------------------------------------------------------------------
// headers
// ----------------------------------------------------------------------------
// implementation only
#define wxASSERT_VALID_INDEX(i) \
- wxASSERT_MSG( (size_t)(i) <= Len(), _T("invalid index in wxString") )
+ wxASSERT_MSG( (size_t)(i) <= length(), _T("invalid index in wxString") )
// ----------------------------------------------------------------------------
// constants
class WXDLLIMPEXP_BASE wxString; // not yet defined
inline const wxString& wxGetEmptyString() { return *(wxString *)&wxEmptyString; }
+#if wxUSE_STL
+
+#include "wx/beforestd.h"
+#include <string>
+#include "wx/afterstd.h"
+
+#if wxUSE_UNICODE
+ #if HAVE_STD_WSTRING
+ typedef std::wstring wxStringBase;
+ #else
+ typedef std::basic_string<wxChar> wxStringBase;
+ #endif
+#else
+ typedef std::string wxStringBase;
+#endif
+
+#if (defined(__GNUG__) && (__GNUG__ < 3)) || \
+ (defined(_MSC_VER) && (_MSC_VER <= 1100))
+ #define wxSTRING_BASE_HASNT_CLEAR
+#endif
+
+#else // if !wxUSE_STL
+
+#ifndef HAVE_STD_STRING_COMPARE
+ #define HAVE_STD_STRING_COMPARE
+#endif
+
// ---------------------------------------------------------------------------
// string data prepended with some housekeeping info (used by wxString class),
// is never used directly (but had to be put here to allow inlining)
bool IsValid() const { return (nRefs != 0); }
};
-// ---------------------------------------------------------------------------
-// This is (yet another one) String class for C++ programmers. It doesn't use
-// any of "advanced" C++ features (i.e. templates, exceptions, namespaces...)
-// thus you should be able to compile it with practicaly any C++ compiler.
-// This class uses copy-on-write technique, i.e. identical strings share the
-// same memory as long as neither of them is changed.
-//
-// This class aims to be as compatible as possible with the new standard
-// std::string class, but adds some additional functions and should be at
-// least as efficient than the standard implementation.
-//
-// Performance note: it's more efficient to write functions which take "const
-// String&" arguments than "const char *" if you assign the argument to
-// another string.
-//
-// It was compiled and tested under Win32, Linux (libc 5 & 6), Solaris 5.5.
-//
-// To do:
-// - ressource support (string tables in ressources)
-// - more wide character (UNICODE) support
-// - regular expressions support
-// ---------------------------------------------------------------------------
-
-class WXDLLIMPEXP_BASE wxString
+class WXDLLIMPEXP_BASE wxStringBase
{
#if !wxUSE_STL
friend class WXDLLIMPEXP_BASE wxArrayString;
#endif
-
- // NB: special care was taken in arranging the member functions in such order
- // that all inline functions can be effectively inlined, verify that all
- // performace critical functions are still inlined if you change order!
-private:
+protected:
// points to data preceded by wxStringData structure with ref count info
wxChar *m_pchData;
// ctors, use Reinit() otherwise)
void Init() { m_pchData = (wxChar *)wxEmptyString; }
// initializaes the string with (a part of) C-string
- void InitWith(const wxChar *psz, size_t nPos = 0, size_t nLen = wxSTRING_MAXLEN);
+ void InitWith(const wxChar *psz, size_t nPos = 0, size_t nLen = npos);
// as Init, but also frees old data
void Reinit() { GetStringData()->Unlock(); Init(); }
bool AssignCopy(size_t, const wxChar *);
// append a (sub)string
- bool ConcatSelf(size_t nLen, const wxChar *src);
+ bool ConcatSelf(size_t nLen, const wxChar *src, size_t nMaxLen);
+ bool ConcatSelf(size_t nLen, const wxChar *src)
+ { return ConcatSelf(nLen, src, nLen); }
// functions called before writing to the string: they copy it if there
// are other references to our data (should be the only owner when writing)
bool CopyBeforeWrite();
bool AllocBeforeWrite(size_t);
- // if we hadn't made these operators private, it would be possible to
- // compile "wxString s; s = 17;" without any warnings as 17 is implicitly
- // converted to char in C and we do have operator=(char)
- //
- // NB: we don't need other versions (short/long and unsigned) as attempt
- // to assign another numeric type to wxString will now result in
- // ambiguity between operator=(char) and operator=(int)
- wxString& operator=(int);
+ // compatibility with wxString
+ bool Alloc(size_t nLen);
+public:
+ // standard types
+ typedef wxChar value_type;
+ typedef wxChar char_type;
+ typedef size_t size_type;
+ typedef value_type& reference;
+ typedef const value_type& const_reference;
+ typedef value_type* pointer;
+ typedef const value_type* const_pointer;
+ typedef value_type *iterator;
+ typedef const value_type *const_iterator;
- // these methods are not implemented - there is _no_ conversion from int to
- // string, you're doing something wrong if the compiler wants to call it!
- //
- // try `s << i' or `s.Printf("%d", i)' instead
- wxString(int);
+ // an 'invalid' value for string index
+ static const size_t npos;
-public:
// constructors and destructor
// ctor for an empty string
- wxString() : m_pchData(NULL) { Init(); }
+ wxStringBase() { Init(); }
// copy ctor
- wxString(const wxString& stringSrc) : m_pchData(NULL)
+ wxStringBase(const wxStringBase& stringSrc)
{
wxASSERT_MSG( stringSrc.GetStringData()->IsValid(),
_T("did you forget to call UngetWriteBuf()?") );
- if ( stringSrc.IsEmpty() ) {
+ if ( stringSrc.empty() ) {
// nothing to do for an empty string
Init();
}
}
}
// string containing nRepeat copies of ch
- wxString(wxChar ch, size_t nRepeat = 1);
+ wxStringBase(size_type nRepeat, wxChar ch);
// ctor takes first nLength characters from C string
- // (default value of wxSTRING_MAXLEN means take all the string)
- wxString(const wxChar *psz, size_t nLength = wxSTRING_MAXLEN)
- : m_pchData(NULL)
+ // (default value of npos means take all the string)
+ wxStringBase(const wxChar *psz)
+ { InitWith(psz, 0, npos); }
+ wxStringBase(const wxChar *psz, size_t nLength)
{ InitWith(psz, 0, nLength); }
- wxString(const wxChar *psz, wxMBConv& WXUNUSED(conv), size_t nLength = wxSTRING_MAXLEN)
- : m_pchData(NULL)
+ wxStringBase(const wxChar *psz, wxMBConv& WXUNUSED(conv), size_t nLength = npos)
{ InitWith(psz, 0, nLength); }
+ // take nLen chars starting at nPos
+ wxStringBase(const wxStringBase& str, size_t nPos, size_t nLen)
+ {
+ wxASSERT_MSG( str.GetStringData()->IsValid(),
+ _T("did you forget to call UngetWriteBuf()?") );
+ Init();
+ size_t strLen = str.length() - nPos; nLen = strLen < nLen ? strLen : nLen;
+ InitWith(str.c_str(), nPos, nLen);
+ }
+ // take all characters from pStart to pEnd
+ wxStringBase(const void *pStart, const void *pEnd);
+
+ // dtor is not virtual, this class must not be inherited from!
+ ~wxStringBase() { GetStringData()->Unlock(); }
+
+ // overloaded assignment
+ // from another wxString
+ wxStringBase& operator=(const wxStringBase& stringSrc);
+ // from a character
+ wxStringBase& operator=(wxChar ch);
+ // from a C string
+ wxStringBase& operator=(const wxChar *psz);
+
+ // return the length of the string
+ size_type size() const { return GetStringData()->nDataLength; }
+ // return the length of the string
+ size_type length() const { return size(); }
+ // return the maximum size of the string
+ size_type max_size() const { return wxSTRING_MAXLEN; }
+ // resize the string, filling the space with c if c != 0
+ void resize(size_t nSize, wxChar ch = wxT('\0'));
+ // delete the contents of the string
+ void clear() { erase(0, npos); }
+ // returns true if the string is empty
+ bool empty() const { return size() == 0; }
+ // inform string about planned change in size
+ void reserve(size_t sz) { Alloc(sz); }
+ size_type capacity() const { return GetStringData()->nAllocLength; }
+
+ // lib.string.access
+ // return the character at position n
+ value_type at(size_type n) const
+ { wxASSERT_VALID_INDEX( n ); return m_pchData[n]; }
+ value_type operator[](size_type n) const { return at(n); }
+ // returns the writable character at position n
+ reference at(size_type n)
+ { wxASSERT_VALID_INDEX( n ); CopyBeforeWrite(); return m_pchData[n]; }
+ reference operator[](size_type n)
+ { wxASSERT_VALID_INDEX( n ); CopyBeforeWrite(); return m_pchData[n]; }
+
+ // lib.string.modifiers
+ // append elements str[pos], ..., str[pos+n]
+ wxStringBase& append(const wxStringBase& str, size_t pos, size_t n)
+ {
+ wxASSERT(pos <= str.length());
+ ConcatSelf(n, str.c_str() + pos, str.length() - pos);
+ return *this;
+ }
+ // append a string
+ wxStringBase& append(const wxStringBase& str)
+ { ConcatSelf(str.length(), str.c_str()); return *this; }
+ // append first n (or all if n == npos) characters of sz
+ wxStringBase& append(const wxChar *sz)
+ { ConcatSelf(wxStrlen(sz), sz); return *this; }
+ wxStringBase& append(const wxChar *sz, size_t n)
+ { ConcatSelf(n, sz); return *this; }
+ // append n copies of ch
+ wxStringBase& append(size_t n, wxChar ch);
+ // append from first to last
+ wxStringBase& append(const_iterator first, const_iterator last)
+ { ConcatSelf(last - first, first); return *this; }
+
+ // same as `this_string = str'
+ wxStringBase& assign(const wxStringBase& str)
+ { return *this = str; }
+ // same as ` = str[pos..pos + n]
+ wxStringBase& assign(const wxStringBase& str, size_t pos, size_t n)
+ { clear(); return append(str, pos, n); }
+ // same as `= first n (or all if n == npos) characters of sz'
+ wxStringBase& assign(const wxChar *sz)
+ { clear(); return append(sz, wxStrlen(sz)); }
+ wxStringBase& assign(const wxChar *sz, size_t n)
+ { clear(); return append(sz, n); }
+ // same as `= n copies of ch'
+ wxStringBase& assign(size_t n, wxChar ch)
+ { clear(); return append(n, ch); }
+ // assign from first to last
+ wxStringBase& assign(const_iterator first, const_iterator last)
+ { clear(); return append(first, last); }
+
+ // first valid index position
+ const_iterator begin() const { return m_pchData; }
+ // position one after the last valid one
+ const_iterator end() const { return m_pchData + length(); }
+
+ // first valid index position
+ iterator begin() { CopyBeforeWrite(); return m_pchData; }
+ // position one after the last valid one
+ iterator end() { CopyBeforeWrite(); return m_pchData + length(); }
+
+ // insert another string
+ wxStringBase& insert(size_t nPos, const wxStringBase& str)
+ {
+ wxASSERT( str.GetStringData()->IsValid() );
+ return insert(nPos, str.c_str(), str.length());
+ }
+ // insert n chars of str starting at nStart (in str)
+ wxStringBase& insert(size_t nPos, const wxStringBase& str, size_t nStart, size_t n)
+ {
+ wxASSERT( str.GetStringData()->IsValid() );
+ wxASSERT( nStart < str.length() );
+ size_t strLen = str.length() - nStart;
+ n = strLen < n ? strLen : n;
+ return insert(nPos, str.c_str() + nStart, n);
+ }
+ // insert first n (or all if n == npos) characters of sz
+ wxStringBase& insert(size_t nPos, const wxChar *sz, size_t n = npos);
+ // insert n copies of ch
+ wxStringBase& insert(size_t nPos, size_t n, wxChar ch)
+ { return insert(nPos, wxStringBase(n, ch)); }
+ iterator insert(iterator it, wxChar ch)
+ { size_t idx = it - begin(); insert(idx, 1, ch); return begin() + idx; }
+ void insert(iterator it, const_iterator first, const_iterator last)
+ { insert(it - begin(), first, last - first); }
+ void insert(iterator it, size_type n, wxChar ch)
+ { insert(it - begin(), n, ch); }
+
+ // delete characters from nStart to nStart + nLen
+ wxStringBase& erase(size_type pos = 0, size_type n = npos);
+ iterator erase(iterator first, iterator last)
+ {
+ size_t idx = first - begin();
+ erase(idx, last - first);
+ return begin() + idx;
+ }
+ iterator erase(iterator first);
+
+ // explicit conversion to C string (use this with printf()!)
+ const wxChar* c_str() const { return m_pchData; }
+ const wxChar* data() const { return m_pchData; }
+
+ // replaces the substring of length nLen starting at nStart
+ wxStringBase& replace(size_t nStart, size_t nLen, const wxChar* sz);
+ // replaces the substring of length nLen starting at nStart
+ wxStringBase& replace(size_t nStart, size_t nLen, const wxStringBase& str)
+ { return replace(nStart, nLen, str.c_str()); }
+ // replaces the substring with nCount copies of ch
+ wxStringBase& replace(size_t nStart, size_t nLen, size_t nCount, wxChar ch);
+ // replaces a substring with another substring
+ wxStringBase& replace(size_t nStart, size_t nLen,
+ const wxStringBase& str, size_t nStart2, size_t nLen2);
+ // replaces the substring with first nCount chars of sz
+ wxStringBase& replace(size_t nStart, size_t nLen,
+ const wxChar* sz, size_t nCount);
+ wxStringBase& replace(iterator first, iterator last, const_pointer s)
+ { return replace(first - begin(), last - first, s); }
+ wxStringBase& replace(iterator first, iterator last, const_pointer s,
+ size_type n)
+ { return replace(first - begin(), last - first, s, n); }
+ wxStringBase& replace(iterator first, iterator last, const wxStringBase& s)
+ { return replace(first - begin(), last - first, s); }
+ wxStringBase& replace(iterator first, iterator last, size_type n, wxChar c)
+ { return replace(first - begin(), last - first, n, c); }
+ wxStringBase& replace(iterator first, iterator last,
+ const_iterator first1, const_iterator last1)
+ { return replace(first - begin(), last - first, first1, last1 - first1); }
+
+ // swap two strings
+ void swap(wxStringBase& str);
+
+ // All find() functions take the nStart argument which specifies the
+ // position to start the search on, the default value is 0. All functions
+ // return npos if there were no match.
+
+ // find a substring
+ size_t find(const wxStringBase& str, size_t nStart = 0) const;
+
+ // VC++ 1.5 can't cope with this syntax.
+#if !defined(__VISUALC__) || defined(__WIN32__)
+ // find first n characters of sz
+ size_t find(const wxChar* sz, size_t nStart = 0, size_t n = npos) const;
+#endif // VC++ 1.5
+
+ // Gives a duplicate symbol (presumably a case-insensitivity problem)
+#if !defined(__BORLANDC__)
+ // find the first occurence of character ch after nStart
+ size_t find(wxChar ch, size_t nStart = 0) const;
+#endif
+ // rfind() family is exactly like find() but works right to left
+
+ // as find, but from the end
+ size_t rfind(const wxStringBase& str, size_t nStart = npos) const;
+
+ // VC++ 1.5 can't cope with this syntax.
+ // as find, but from the end
+ size_t rfind(const wxChar* sz, size_t nStart = npos,
+ size_t n = npos) const;
+ // as find, but from the end
+ size_t rfind(wxChar ch, size_t nStart = npos) const;
+
+ // find first/last occurence of any character in the set
+
+ // as strpbrk() but starts at nStart, returns npos if not found
+ size_t find_first_of(const wxStringBase& str, size_t nStart = 0) const
+ { return find_first_of(str.c_str(), nStart); }
+ // same as above
+ size_t find_first_of(const wxChar* sz, size_t nStart = 0) const;
+ // same as find(char, size_t)
+ size_t find_first_of(wxChar c, size_t nStart = 0) const
+ { return find(c, nStart); }
+ // find the last (starting from nStart) char from str in this string
+ size_t find_last_of (const wxStringBase& str, size_t nStart = npos) const
+ { return find_last_of(str.c_str(), nStart); }
+ // same as above
+ size_t find_last_of (const wxChar* sz, size_t nStart = npos) const;
+ // same as above
+ size_t find_last_of(wxChar c, size_t nStart = npos) const
+ { return rfind(c, nStart); }
+
+ // find first/last occurence of any character not in the set
+
+ // as strspn() (starting from nStart), returns npos on failure
+ size_t find_first_not_of(const wxStringBase& str, size_t nStart = 0) const
+ { return find_first_not_of(str.c_str(), nStart); }
+ // same as above
+ size_t find_first_not_of(const wxChar* sz, size_t nStart = 0) const;
+ // same as above
+ size_t find_first_not_of(wxChar ch, size_t nStart = 0) const;
+ // as strcspn()
+ size_t find_last_not_of(const wxStringBase& str, size_t nStart = npos) const
+ { return find_first_not_of(str.c_str(), nStart); }
+ // same as above
+ size_t find_last_not_of(const wxChar* sz, size_t nStart = npos) const;
+ // same as above
+ size_t find_last_not_of(wxChar ch, size_t nStart = npos) const;
+
+ // All compare functions return -1, 0 or 1 if the [sub]string is less,
+ // equal or greater than the compare() argument.
+
+ // just like strcmp()
+ int compare(const wxStringBase& str) const
+ { return wxStrcmp(c_str(), str.c_str()); }
+ // comparison with a substring
+ int compare(size_t nStart, size_t nLen, const wxStringBase& str) const;
+ // comparison of 2 substrings
+ int compare(size_t nStart, size_t nLen,
+ const wxStringBase& str, size_t nStart2, size_t nLen2) const;
+ // just like strcmp()
+ int compare(const wxChar* sz) const
+ { return wxStrcmp(c_str(), sz); }
+ // substring comparison with first nCount characters of sz
+ int compare(size_t nStart, size_t nLen,
+ const wxChar* sz, size_t nCount = npos) const;
+
+ size_type copy(wxChar* s, size_type n, size_type pos = 0);
+
+ // substring extraction
+ wxStringBase substr(size_t nStart = 0, size_t nLen = npos) const;
+
+ // string += string
+ wxStringBase& operator+=(const wxStringBase& s) { return append(s); }
+ // string += C string
+ wxStringBase& operator+=(const wxChar *psz) { return append(psz); }
+ // string += char
+ wxStringBase& operator+=(wxChar ch) { return append(1, ch); }
+};
+
+#endif // !wxUSE_STL
+
+// ---------------------------------------------------------------------------
+// This is (yet another one) String class for C++ programmers. It doesn't use
+// any of "advanced" C++ features (i.e. templates, exceptions, namespaces...)
+// thus you should be able to compile it with practicaly any C++ compiler.
+// This class uses copy-on-write technique, i.e. identical strings share the
+// same memory as long as neither of them is changed.
+//
+// This class aims to be as compatible as possible with the new standard
+// std::string class, but adds some additional functions and should be at
+// least as efficient than the standard implementation.
+//
+// Performance note: it's more efficient to write functions which take "const
+// String&" arguments than "const char *" if you assign the argument to
+// another string.
+//
+// It was compiled and tested under Win32, Linux (libc 5 & 6), Solaris 5.5.
+//
+// To do:
+// - ressource support (string tables in ressources)
+// - more wide character (UNICODE) support
+// - regular expressions support
+// ---------------------------------------------------------------------------
+
+class WXDLLIMPEXP_BASE wxString : public wxStringBase
+{
+#if !wxUSE_STL
+friend class WXDLLIMPEXP_BASE wxArrayString;
+#endif
+
+ // NB: special care was taken in arranging the member functions in such order
+ // that all inline functions can be effectively inlined, verify that all
+ // performace critical functions are still inlined if you change order!
+private:
+ // if we hadn't made these operators private, it would be possible to
+ // compile "wxString s; s = 17;" without any warnings as 17 is implicitly
+ // converted to char in C and we do have operator=(char)
+ //
+ // NB: we don't need other versions (short/long and unsigned) as attempt
+ // to assign another numeric type to wxString will now result in
+ // ambiguity between operator=(char) and operator=(int)
+ wxString& operator=(int);
+
+ // these methods are not implemented - there is _no_ conversion from int to
+ // string, you're doing something wrong if the compiler wants to call it!
+ //
+ // try `s << i' or `s.Printf("%d", i)' instead
+ wxString(int);
+
+public:
+ // constructors and destructor
+ // ctor for an empty string
+ wxString() : wxStringBase() { }
+ // copy ctor
+ wxString(const wxStringBase& stringSrc) : wxStringBase(stringSrc) { }
+ wxString(const wxString& stringSrc) : wxStringBase(stringSrc) { }
+ // string containing nRepeat copies of ch
+ wxString(wxChar ch, size_t nRepeat = 1)
+ : wxStringBase(nRepeat, ch) { }
+ wxString(size_t nRepeat, wxChar ch)
+ : wxStringBase(nRepeat, ch) { }
+ // ctor takes first nLength characters from C string
+ // (default value of npos means take all the string)
+ wxString(const wxChar *psz)
+ : wxStringBase(psz ? psz : wxT("")) { }
+ wxString(const wxChar *psz, size_t nLength)
+ : wxStringBase(psz, nLength) { }
+ wxString(const wxChar *psz, wxMBConv& WXUNUSED(conv), size_t nLength = npos)
+ : wxStringBase(psz, nLength == npos ? wxStrlen(psz) : nLength) { }
#if wxUSE_UNICODE
// from multibyte string
// (NB: nLength is right now number of Unicode characters, not
// characters in psz! So try not to use it yet!)
- wxString(const char *psz, wxMBConv& conv, size_t nLength = wxSTRING_MAXLEN);
+ wxString(const char *psz, wxMBConv& conv, size_t nLength = npos);
// from wxWCharBuffer (i.e. return from wxGetString)
- wxString(const wxWCharBuffer& psz)
- { InitWith(psz, 0, wxSTRING_MAXLEN); }
+ wxString(const wxWCharBuffer& psz) : wxStringBase(psz.data()) { }
#else // ANSI
// from C string (for compilers using unsigned char)
- wxString(const unsigned char* psz, size_t nLength = wxSTRING_MAXLEN)
- : m_pchData(NULL)
- { InitWith((const char*)psz, 0, nLength); }
+ wxString(const unsigned char* psz, size_t nLength = npos)
+ : wxStringBase((const char*)psz, nLength) { }
#if wxUSE_WCHAR_T
// from wide (Unicode) string
- wxString(const wchar_t *pwz, wxMBConv& conv = wxConvLibc, size_t nLength = wxSTRING_MAXLEN);
+ wxString(const wchar_t *pwz, wxMBConv& conv = wxConvLibc, size_t nLength = npos);
#endif // !wxUSE_WCHAR_T
// from wxCharBuffer
wxString(const wxCharBuffer& psz)
- : m_pchData(NULL)
- { InitWith(psz, 0, wxSTRING_MAXLEN); }
+ : wxStringBase(psz, npos) { }
#endif // Unicode/ANSI
- // dtor is not virtual, this class must not be inherited from!
- ~wxString() { GetStringData()->Unlock(); }
-
// generic attributes & operations
// as standard strlen()
- size_t Len() const { return GetStringData()->nDataLength; }
+ size_t Len() const { return length(); }
// string contains any characters?
- bool IsEmpty() const { return Len() == 0; }
+ bool IsEmpty() const { return empty(); }
// empty string is "FALSE", so !str will return TRUE
bool operator!() const { return IsEmpty(); }
// truncate the string to given length
// empty the string and free memory
void Clear()
{
- if ( !GetStringData()->IsEmpty() )
- Reinit();
-
- wxASSERT_MSG( !GetStringData()->nDataLength &&
- !GetStringData()->nAllocLength,
- _T("string should be empty after Clear()") );
+ wxString tmp(wxEmptyString);
+ swap(tmp);
}
// contents test
// data access (all indexes are 0 based)
// read access
wxChar GetChar(size_t n) const
- { wxASSERT_VALID_INDEX( n ); return m_pchData[n]; }
+ { return operator[](n); }
// read/write access
wxChar& GetWritableChar(size_t n)
- { wxASSERT_VALID_INDEX( n ); CopyBeforeWrite(); return m_pchData[n]; }
+ { return operator[](n); }
// write access
void SetChar(size_t n, wxChar ch)
- { wxASSERT_VALID_INDEX( n ); CopyBeforeWrite(); m_pchData[n] = ch; }
+ { operator[](n) = ch; }
// get last character
wxChar Last() const
{
wxASSERT_MSG( !IsEmpty(), _T("wxString: index out of bounds") );
- return m_pchData[Len() - 1];
+ return operator[](length() - 1);
}
// get writable last character
wxChar& Last()
{
wxASSERT_MSG( !IsEmpty(), _T("wxString: index out of bounds") );
- CopyBeforeWrite();
- return m_pchData[Len()-1];
+ return operator[](length() - 1);
}
/*
taking size_t...
*/
- // operator version of GetChar
- wxChar operator[](size_t n) const
- { wxASSERT_VALID_INDEX( n ); return m_pchData[n]; }
-
// operator version of GetChar
wxChar operator[](int n) const
- { wxASSERT_VALID_INDEX( n ); return m_pchData[n]; }
-
- // operator version of GetWriteableChar
- wxChar& operator[](size_t n)
- { wxASSERT_VALID_INDEX( n ); CopyBeforeWrite(); return m_pchData[n]; }
-
+ { return wxStringBase::operator[](n); }
+ wxChar& operator[](size_type n)
+ { return wxStringBase::operator[](n); }
+ wxChar operator[](size_type n) const
+ { return wxStringBase::operator[](n); }
#ifndef wxSIZE_T_IS_UINT
// operator version of GetChar
wxChar operator[](unsigned int n) const
- { wxASSERT_VALID_INDEX( n ); return m_pchData[n]; }
+ { return operator[](n); }
// operator version of GetWriteableChar
wxChar& operator[](unsigned int n)
- { wxASSERT_VALID_INDEX( n ); CopyBeforeWrite(); return m_pchData[n]; }
+ { return operator[](n); }
#endif // size_t != unsigned int
// implicit conversion to C string
- operator const wxChar*() const { return m_pchData; }
+ operator const wxChar*() const { return c_str(); }
- // explicit conversion to C string (use this with printf()!)
- const wxChar* c_str() const { return m_pchData; }
// identical to c_str(), for wxWin 1.6x compatibility
- const wxChar* wx_str() const { return m_pchData; }
+ const wxChar* wx_str() const { return c_str(); }
// identical to c_str(), for MFC compatibility
- const wxChar* GetData() const { return m_pchData; }
+ const wxChar* GetData() const { return c_str(); }
// conversion to/from plain (i.e. 7 bit) ASCII: this is useful for
// converting numbers or strings which are certain not to contain special
// directly or have to use intermediate buffer for translation.
#if wxUSE_UNICODE
const wxCharBuffer mb_str(wxMBConv& conv = wxConvLibc) const
- { return conv.cWC2MB(m_pchData); }
+ { return conv.cWC2MB(c_str()); }
const wxWX2MBbuf mbc_str() const { return mb_str(*wxConvCurrent); }
- const wxChar* wc_str() const { return m_pchData; }
+ const wxChar* wc_str() const { return c_str(); }
// for compatibility with !wxUSE_UNICODE version
- const wxChar* wc_str(wxMBConv& WXUNUSED(conv)) const { return m_pchData; }
+ const wxChar* wc_str(wxMBConv& WXUNUSED(conv)) const { return c_str(); }
#if wxMBFILES
const wxCharBuffer fn_str() const { return mb_str(wxConvFile); }
#else // !wxMBFILES
- const wxChar* fn_str() const { return m_pchData; }
+ const wxChar* fn_str() const { return c_str(); }
#endif // wxMBFILES/!wxMBFILES
#else // ANSI
- const wxChar* mb_str() const { return m_pchData; }
+ const wxChar* mb_str() const { return c_str(); }
// for compatibility with wxUSE_UNICODE version
- const wxChar* mb_str(wxMBConv& WXUNUSED(conv)) const { return m_pchData; }
+ const wxChar* mb_str(wxMBConv& WXUNUSED(conv)) const { return c_str(); }
const wxWX2MBbuf mbc_str() const { return mb_str(); }
#if wxUSE_WCHAR_T
const wxWCharBuffer wc_str(wxMBConv& conv) const
- { return conv.cMB2WC(m_pchData); }
+ { return conv.cMB2WC(c_str()); }
#endif // wxUSE_WCHAR_T
- const wxChar* fn_str() const { return m_pchData; }
+ const wxChar* fn_str() const { return c_str(); }
#endif // Unicode/ANSI
// overloaded assignment
// from another wxString
- wxString& operator=(const wxString& stringSrc);
+ wxString& operator=(const wxStringBase& stringSrc)
+ { return (wxString&)wxStringBase::operator=(stringSrc); }
// from a character
- wxString& operator=(wxChar ch);
+ wxString& operator=(wxChar ch)
+ { return (wxString&)wxStringBase::operator=(ch); }
// from a C string
- wxString& operator=(const wxChar *psz);
+ wxString& operator=(const wxChar *psz)
+ { return (wxString&)wxStringBase::operator=(psz); }
#if wxUSE_UNICODE
// from wxWCharBuffer
wxString& operator=(const wxWCharBuffer& psz)
- { (void) operator=((const wchar_t *)psz); return *this; }
+ { (void) operator=((const wchar_t *)psz); return *this; }
#else // ANSI
// from another kind of C string
wxString& operator=(const unsigned char* psz);
#endif
// from wxCharBuffer
wxString& operator=(const wxCharBuffer& psz)
- { (void) operator=((const char *)psz); return *this; }
+ { (void) operator=((const char *)psz); return *this; }
#endif // Unicode/ANSI
// string concatenation
// string += string
wxString& operator<<(const wxString& s)
{
+#if !wxUSE_STL
wxASSERT_MSG( s.GetStringData()->IsValid(),
_T("did you forget to call UngetWriteBuf()?") );
+#endif
- ConcatSelf(s.Len(), s);
+ append(s);
return *this;
}
// string += C string
wxString& operator<<(const wxChar *psz)
- { ConcatSelf(wxStrlen(psz), psz); return *this; }
+ { append(psz); return *this; }
// string += char
- wxString& operator<<(wxChar ch) { ConcatSelf(1, &ch); return *this; }
-
- // string += string
- void operator+=(const wxString& s) { (void)operator<<(s); }
- // string += C string
- void operator+=(const wxChar *psz) { (void)operator<<(psz); }
- // string += char
- void operator+=(wxChar ch) { (void)operator<<(ch); }
+ wxString& operator<<(wxChar ch) { append(1, ch); return *this; }
// string += buffer (i.e. from wxGetString)
#if wxUSE_UNICODE
if ( IsEmpty() )
*this = s;
else
- ConcatSelf(s.Length(), s.c_str());
+ append(s);
return *this;
}
wxString& Append(const wxChar* psz)
- { ConcatSelf(wxStrlen(psz), psz); return *this; }
+ { append(psz); return *this; }
// append count copies of given character
wxString& Append(wxChar ch, size_t count = 1u)
- { wxString str(ch, count); return *this << str; }
+ { append(count, ch); return *this; }
wxString& Append(const wxChar* psz, size_t nLen)
- { ConcatSelf(nLen, psz); return *this; }
+ { append(psz, nLen); return *this; }
// prepend a string, return the string itself
wxString& Prepend(const wxString& str)
// comparison with a signle character: returns TRUE if equal
bool IsSameAs(wxChar c, bool compareWithCase = TRUE) const
{
- return (Len() == 1) && (compareWithCase ? GetChar(0u) == c
+ return (length() == 1) && (compareWithCase ? GetChar(0u) == c
: wxToupper(GetChar(0u)) == wxToupper(c));
}
// simple sub-string extraction
// return substring starting at nFirst of length nCount (or till the end
// if nCount = default value)
- wxString Mid(size_t nFirst, size_t nCount = wxSTRING_MAXLEN) const;
+ wxString Mid(size_t nFirst, size_t nCount = npos) const;
// operator version of Mid()
wxString operator()(size_t start, size_t len) const
// raw access to string memory
// ensure that string has space for at least nLen characters
// only works if the data of this string is not shared
- bool Alloc(size_t nLen);
+ bool Alloc(size_t nLen) { reserve(nLen); /*return capacity() >= nLen;*/ return true; }
// minimize the string's memory
// only works if the data of this string is not shared
bool Shrink();
+#if !wxUSE_STL
// get writable buffer of at least nLen bytes. Unget() *must* be called
// a.s.a.p. to put string back in a reasonable state!
wxChar *GetWriteBuf(size_t nLen);
// call this immediately after GetWriteBuf() has been used
void UngetWriteBuf();
void UngetWriteBuf(size_t nLen);
+#endif
// wxWindows version 1 compatibility functions
{ return cmp == exact ? Cmp(psz) : CmpNoCase(psz); }
// use Len
- size_t Length() const { return Len(); }
+ size_t Length() const { return length(); }
// Count the number of characters
int Freq(wxChar ch) const;
// use MakeLower
size_t Index(wxChar ch) const { return Find(ch); }
// use Truncate
wxString& Remove(size_t pos) { return Truncate(pos); }
- wxString& RemoveLast(size_t n = 1) { return Truncate(Len() - n); }
+ wxString& RemoveLast(size_t n = 1) { return Truncate(length() - n); }
- wxString& Remove(size_t nStart, size_t nLen) { return erase( nStart, nLen ); }
+ wxString& Remove(size_t nStart, size_t nLen)
+ { return (wxString&)erase( nStart, nLen ); }
// use Find()
int First( const wxChar ch ) const { return Find(ch); }
// use IsEmpty()
bool IsNull() const { return IsEmpty(); }
-#ifdef wxSTD_STRING_COMPATIBILITY
// std::string compatibility functions
- // standard types
- typedef wxChar value_type;
- typedef size_t size_type;
- typedef value_type *iterator;
- typedef const value_type *const_iterator;
-
- // an 'invalid' value for string index
- static const size_t npos;
-
- // constructors
// take nLen chars starting at nPos
wxString(const wxString& str, size_t nPos, size_t nLen)
- : m_pchData(NULL)
- {
- wxASSERT_MSG( str.GetStringData()->IsValid(),
- _T("did you forget to call UngetWriteBuf()?") );
-
- InitWith(str.c_str(), nPos, nLen == npos ? 0 : nLen);
- }
+ : wxStringBase(str, nPos, nLen) { }
// take all characters from pStart to pEnd
- wxString(const void *pStart, const void *pEnd);
-
- // lib.string.capacity
- // return the length of the string
- size_t size() const { return Len(); }
- // return the length of the string
- size_t length() const { return Len(); }
- // return the maximum size of the string
- size_t max_size() const { return wxSTRING_MAXLEN; }
- // resize the string, filling the space with c if c != 0
- void resize(size_t nSize, wxChar ch = wxT('\0'));
- // delete the contents of the string
- void clear() { Empty(); }
- // returns true if the string is empty
- bool empty() const { return IsEmpty(); }
- // inform string about planned change in size
- void reserve(size_t sz) { Alloc(sz); }
-
- // lib.string.access
- // return the character at position n
- wxChar at(size_t n) const { return GetChar(n); }
- // returns the writable character at position n
- wxChar& at(size_t n) { return GetWritableChar(n); }
-
- // first valid index position
- const_iterator begin() const { return wx_str(); }
- // position one after the last valid one
- const_iterator end() const { return wx_str() + length(); }
-
- // first valid index position
- iterator begin() { CopyBeforeWrite(); return m_pchData; }
- // position one after the last valid one
- iterator end() { CopyBeforeWrite(); return m_pchData + length(); }
+ wxString(const void *pStart, const void *pEnd)
+ : wxStringBase((const char*)pStart, (const char*)pEnd) { }
+#if wxUSE_STL
+ wxString(const_iterator first, const_iterator last)
+ : wxStringBase(first, last) { }
+#endif
// lib.string.modifiers
- // append a string
- wxString& append(const wxString& str)
- { *this += str; return *this; }
// append elements str[pos], ..., str[pos+n]
wxString& append(const wxString& str, size_t pos, size_t n)
- { ConcatSelf(n, str.c_str() + pos); return *this; }
+ { return (wxString&)wxStringBase::append(str, pos, n); }
+ // append a string
+ wxString& append(const wxString& str)
+ { return (wxString&)wxStringBase::append(str); }
// append first n (or all if n == npos) characters of sz
- wxString& append(const wxChar *sz, size_t n = npos)
- { ConcatSelf(n == npos ? wxStrlen(sz) : n, sz); return *this; }
-
+ wxString& append(const wxChar *sz)
+ { return (wxString&)wxStringBase::append(sz); }
+ wxString& append(const wxChar *sz, size_t n)
+ { return (wxString&)wxStringBase::append(sz, n); }
// append n copies of ch
- wxString& append(size_t n, wxChar ch) { return Pad(n, ch); }
+ wxString& append(size_t n, wxChar ch)
+ { return (wxString&)wxStringBase::append(n, ch); }
+ // append from first to last
+ wxString& append(const_iterator first, const_iterator last)
+ { return (wxString&)wxStringBase::append(first, last); }
// same as `this_string = str'
wxString& assign(const wxString& str)
- { return *this = str; }
+ { return (wxString&)wxStringBase::assign(str); }
// same as ` = str[pos..pos + n]
wxString& assign(const wxString& str, size_t pos, size_t n)
- { Empty(); return Append(str.c_str() + pos, n); }
+ { return (wxString&)wxStringBase::assign(str, pos, n); }
// same as `= first n (or all if n == npos) characters of sz'
- wxString& assign(const wxChar *sz, size_t n = npos)
- { Empty(); return Append(sz, n == npos ? wxStrlen(sz) : n); }
+ wxString& assign(const wxChar *sz)
+ { return (wxString&)wxStringBase::assign(sz); }
+ wxString& assign(const wxChar *sz, size_t n)
+ { return (wxString&)wxStringBase::assign(sz, n); }
// same as `= n copies of ch'
wxString& assign(size_t n, wxChar ch)
- { Empty(); return Append(ch, n); }
+ { return (wxString&)wxStringBase::assign(n, ch); }
+ // assign from first to last
+ wxString& assign(const_iterator first, const_iterator last)
+ { return (wxString&)wxStringBase::assign(first, last); }
+
+ // string comparison
+#ifndef HAVE_STD_STRING_COMPARE
+ int compare(const wxStringBase& str) const;
+ // comparison with a substring
+ int compare(size_t nStart, size_t nLen, const wxStringBase& str) const;
+ // comparison of 2 substrings
+ int compare(size_t nStart, size_t nLen,
+ const wxStringBase& str, size_t nStart2, size_t nLen2) const;
+ // just like strcmp()
+ int compare(const wxChar* sz) const;
+ // substring comparison with first nCount characters of sz
+ int compare(size_t nStart, size_t nLen,
+ const wxChar* sz, size_t nCount = npos) const;
+#endif // !defined HAVE_STD_STRING_COMPARE
// insert another string
- wxString& insert(size_t nPos, const wxString& str);
+ wxString& insert(size_t nPos, const wxString& str)
+ { return (wxString&)wxStringBase::insert(nPos, str); }
// insert n chars of str starting at nStart (in str)
wxString& insert(size_t nPos, const wxString& str, size_t nStart, size_t n)
- { return insert(nPos, wxString((const wxChar *)str + nStart, n)); }
-
+ { return (wxString&)wxStringBase::insert(nPos, str, nStart, n); }
// insert first n (or all if n == npos) characters of sz
- wxString& insert(size_t nPos, const wxChar *sz, size_t n = npos)
- { return insert(nPos, wxString(sz, n)); }
+ wxString& insert(size_t nPos, const wxChar *sz)
+ { return (wxString&)wxStringBase::insert(nPos, sz); }
+ wxString& insert(size_t nPos, const wxChar *sz, size_t n)
+ { return (wxString&)wxStringBase::insert(nPos, sz, n); }
// insert n copies of ch
wxString& insert(size_t nPos, size_t n, wxChar ch)
- { return insert(nPos, wxString(ch, n)); }
+ { return (wxString&)wxStringBase::insert(nPos, n, ch); }
+ iterator insert(iterator it, wxChar ch)
+ { return wxStringBase::insert(it, ch); }
+ void insert(iterator it, const_iterator first, const_iterator last)
+ { wxStringBase::insert(it, first, last); }
+ void insert(iterator it, size_type n, wxChar ch)
+ { wxStringBase::insert(it, n, ch); }
// delete characters from nStart to nStart + nLen
- wxString& erase(size_t nStart = 0, size_t nLen = npos);
+ wxString& erase(size_type pos = 0, size_type n = npos)
+ { return (wxString&)wxStringBase::erase(pos, n); }
+ iterator erase(iterator first, iterator last)
+ { return wxStringBase::erase(first, last); }
+ iterator erase(iterator first)
+ { return wxStringBase::erase(first); }
+
+#ifdef wxSTRING_BASE_HASNT_CLEAR
+ void clear() { erase(); }
+#endif
// replaces the substring of length nLen starting at nStart
- wxString& replace(size_t nStart, size_t nLen, const wxChar* sz);
+ wxString& replace(size_t nStart, size_t nLen, const wxChar* sz)
+ { return (wxString&)wxStringBase::replace(nStart, nLen, sz); }
+ // replaces the substring of length nLen starting at nStart
+ wxString& replace(size_t nStart, size_t nLen, const wxString& str)
+ { return (wxString&)wxStringBase::replace(nStart, nLen, str); }
// replaces the substring with nCount copies of ch
- wxString& replace(size_t nStart, size_t nLen, size_t nCount, wxChar ch);
+ wxString& replace(size_t nStart, size_t nLen, size_t nCount, wxChar ch)
+ { return (wxString&)wxStringBase::replace(nStart, nLen, nCount, ch); }
// replaces a substring with another substring
wxString& replace(size_t nStart, size_t nLen,
- const wxString& str, size_t nStart2, size_t nLen2);
- // replaces the substring with first nCount chars of sz
+ const wxString& str, size_t nStart2, size_t nLen2)
+ { return (wxString&)wxStringBase::replace(nStart, nLen, str,
+ nStart2, nLen2); }
+ // replaces the substring with first nCount chars of sz
wxString& replace(size_t nStart, size_t nLen,
- const wxChar* sz, size_t nCount);
-
- // swap two strings
- void swap(wxString& str);
+ const wxChar* sz, size_t nCount)
+ { return (wxString&)wxStringBase::replace(nStart, nLen, sz, nCount); }
+ wxString& replace(iterator first, iterator last, const_pointer s)
+ { return (wxString&)wxStringBase::replace(first, last, s); }
+ wxString& replace(iterator first, iterator last, const_pointer s,
+ size_type n)
+ { return (wxString&)wxStringBase::replace(first, last, s, n); }
+ wxString& replace(iterator first, iterator last, const wxString& s)
+ { return (wxString&)wxStringBase::replace(first, last, s); }
+ wxString& replace(iterator first, iterator last, size_type n, wxChar c)
+ { return (wxString&)wxStringBase::replace(first, last, n, c); }
+ wxString& replace(iterator first, iterator last,
+ const_iterator first1, const_iterator last1)
+ { return (wxString&)wxStringBase::replace(first, last, first1, last1); }
- // All find() functions take the nStart argument which specifies the
- // position to start the search on, the default value is 0. All functions
- // return npos if there were no match.
-
- // find a substring
- size_t find(const wxString& str, size_t nStart = 0) const;
-
- // VC++ 1.5 can't cope with this syntax.
-#if !defined(__VISUALC__) || defined(__WIN32__)
- // find first n characters of sz
- size_t find(const wxChar* sz, size_t nStart = 0, size_t n = npos) const;
-#endif // VC++ 1.5
-
- // Gives a duplicate symbol (presumably a case-insensitivity problem)
-#if !defined(__BORLANDC__)
- // find the first occurence of character ch after nStart
- size_t find(wxChar ch, size_t nStart = 0) const;
-#endif
- // rfind() family is exactly like find() but works right to left
-
- // as find, but from the end
- size_t rfind(const wxString& str, size_t nStart = npos) const;
-
- // VC++ 1.5 can't cope with this syntax.
-#if !defined(__VISUALC__) || defined(__WIN32__)
- // as find, but from the end
- size_t rfind(const wxChar* sz, size_t nStart = npos,
- size_t n = npos) const;
- // as find, but from the end
- size_t rfind(wxChar ch, size_t nStart = npos) const;
-#endif // VC++ 1.5
-
- // find first/last occurence of any character in the set
-
- // as strpbrk() but starts at nStart, returns npos if not found
- size_t find_first_of(const wxString& str, size_t nStart = 0) const
- { return find_first_of(str.c_str(), nStart); }
- // same as above
- size_t find_first_of(const wxChar* sz, size_t nStart = 0) const;
- // same as find(char, size_t)
- size_t find_first_of(wxChar c, size_t nStart = 0) const
- { return find(c, nStart); }
- // find the last (starting from nStart) char from str in this string
- size_t find_last_of (const wxString& str, size_t nStart = npos) const
- { return find_last_of(str.c_str(), nStart); }
- // same as above
- size_t find_last_of (const wxChar* sz, size_t nStart = npos) const;
- // same as above
- size_t find_last_of(wxChar c, size_t nStart = npos) const
- { return rfind(c, nStart); }
-
- // find first/last occurence of any character not in the set
-
- // as strspn() (starting from nStart), returns npos on failure
- size_t find_first_not_of(const wxString& str, size_t nStart = 0) const
- { return find_first_not_of(str.c_str(), nStart); }
- // same as above
- size_t find_first_not_of(const wxChar* sz, size_t nStart = 0) const;
- // same as above
- size_t find_first_not_of(wxChar ch, size_t nStart = 0) const;
- // as strcspn()
- size_t find_last_not_of(const wxString& str, size_t nStart = npos) const
- { return find_first_not_of(str.c_str(), nStart); }
- // same as above
- size_t find_last_not_of(const wxChar* sz, size_t nStart = npos) const;
- // same as above
- size_t find_last_not_of(wxChar ch, size_t nStart = npos) const;
-
- // All compare functions return -1, 0 or 1 if the [sub]string is less,
- // equal or greater than the compare() argument.
-
- // just like strcmp()
- int compare(const wxString& str) const { return Cmp(str); }
- // comparison with a substring
- int compare(size_t nStart, size_t nLen, const wxString& str) const
- { return Mid(nStart, nLen).Cmp(str); }
- // comparison of 2 substrings
- int compare(size_t nStart, size_t nLen,
- const wxString& str, size_t nStart2, size_t nLen2) const
- { return Mid(nStart, nLen).Cmp(str.Mid(nStart2, nLen2)); }
- // just like strcmp()
- int compare(const wxChar* sz) const { return Cmp(sz); }
- // substring comparison with first nCount characters of sz
- int compare(size_t nStart, size_t nLen,
- const wxChar* sz, size_t nCount = npos) const
- { return Mid(nStart, nLen).Cmp(wxString(sz, nCount)); }
-
- // substring extraction
- wxString substr(size_t nStart = 0, size_t nLen = npos) const
- { return Mid(nStart, nLen); }
-#endif // wxSTD_STRING_COMPATIBILITY
+ // string += string
+ wxString& operator+=(const wxString& s)
+ { return (wxString&)wxStringBase::operator+=(s); }
+ // string += C string
+ wxString& operator+=(const wxChar *psz)
+ { return (wxString&)wxStringBase::operator+=(psz); }
+ // string += char
+ wxString& operator+=(wxChar ch)
+ { return (wxString&)wxStringBase::operator+=(ch); }
};
// define wxArrayString, for compatibility
{
public:
wxStringBuffer(wxString& str, size_t lenWanted = 1024)
- : m_str(str), m_buf(lenWanted), m_len(lenWanted)
+ : m_str(str), m_buf(lenWanted)
{ }
~wxStringBuffer() { m_str.assign(m_buf.data(), wxStrlen(m_buf.data())); }
#else
wxCharBuffer m_buf;
#endif
- size_t m_len;
DECLARE_NO_COPY_CLASS(wxStringBuffer)
};
// wxString comparison functions: operator versions are always case sensitive
// ---------------------------------------------------------------------------
+#if wxUSE_STL
+
+inline bool operator==(const wxString& s1, const wxString& s2)
+ { return s1.compare(s2) == 0; }
+inline bool operator==(const wxString& s1, const wxChar * s2)
+ { return s1.compare(s2) == 0; }
+inline bool operator==(const wxChar * s1, const wxString& s2)
+ { return s2.compare(s1) == 0; }
+inline bool operator!=(const wxString& s1, const wxString& s2)
+ { return s1.compare(s2) != 0; }
+inline bool operator!=(const wxString& s1, const wxChar * s2)
+ { return s1.compare(s2) != 0; }
+inline bool operator!=(const wxChar * s1, const wxString& s2)
+ { return s2.compare(s1) != 0; }
+inline bool operator< (const wxString& s1, const wxString& s2)
+ { return s1.compare(s2) < 0; }
+inline bool operator< (const wxString& s1, const wxChar * s2)
+ { return s1.compare(s2) < 0; }
+inline bool operator< (const wxChar * s1, const wxString& s2)
+ { return s2.compare(s1) > 0; }
+inline bool operator> (const wxString& s1, const wxString& s2)
+ { return s1.compare(s2) > 0; }
+inline bool operator> (const wxString& s1, const wxChar * s2)
+ { return s1.compare(s2) > 0; }
+inline bool operator> (const wxChar * s1, const wxString& s2)
+ { return s2.compare(s1) < 0; }
+inline bool operator<=(const wxString& s1, const wxString& s2)
+ { return s1.compare(s2) <= 0; }
+inline bool operator<=(const wxString& s1, const wxChar * s2)
+ { return s1.compare(s2) <= 0; }
+inline bool operator<=(const wxChar * s1, const wxString& s2)
+ { return s2.compare(s1) >= 0; }
+inline bool operator>=(const wxString& s1, const wxString& s2)
+ { return s1.compare(s2) >= 0; }
+inline bool operator>=(const wxString& s1, const wxChar * s2)
+ { return s1.compare(s2) >= 0; }
+inline bool operator>=(const wxChar * s1, const wxString& s2)
+ { return s2.compare(s1) <= 0; }
+
+#else // if !wxUSE_STL
+
inline bool operator==(const wxString& s1, const wxString& s2)
{ return (s1.Len() == s2.Len()) && (s1.Cmp(s2) == 0); }
inline bool operator==(const wxString& s1, const wxChar * s2)
inline bool operator>=(const wxChar * s1, const wxString& s2)
{ return s2.Cmp(s1) <= 0; }
+#endif // !wxUSE_STL
+
// comparison with char
inline bool operator==(wxChar c, const wxString& s) { return s.IsSameAs(c); }
inline bool operator==(const wxString& s, wxChar c) { return s.IsSameAs(c); }
{ return (s2.Cmp((const char *)s1) != 0); }
#endif // wxUSE_UNICODE/!wxUSE_UNICODE
+#if !wxUSE_STL
+
wxString WXDLLIMPEXP_BASE operator+(const wxString& string1, const wxString& string2);
wxString WXDLLIMPEXP_BASE operator+(const wxString& string, wxChar ch);
wxString WXDLLIMPEXP_BASE operator+(wxChar ch, const wxString& string);
wxString WXDLLIMPEXP_BASE operator+(const wxString& string, const wxChar *psz);
wxString WXDLLIMPEXP_BASE operator+(const wxChar *psz, const wxString& string);
+
+#endif // !wxUSE_STL
+
#if wxUSE_UNICODE
inline wxString operator+(const wxString& string, const wxWCharBuffer& buf)
{ return string + (const wchar_t *)buf; }
// don't pollute the library user's name space
#undef wxASSERT_VALID_INDEX
-#if defined(wxSTD_STRING_COMPATIBILITY) && wxUSE_STD_IOSTREAM
+#if wxUSE_STD_IOSTREAM
#include "wx/iosfwrap.h"
#undef TEST_ALL
static const bool TEST_ALL = true;
#else
- #define TEST_ARRAYS
- #define TEST_HASH
- #define TEST_LIST
- #define TEST_SCOPEGUARD
+ #define TEST_HASHMAP
static const bool TEST_ALL = false;
#endif
for (int i = 0; i < 1000000; ++i)
{
- a = "Hello";
- b = " world";
- c = "! How'ya doin'?";
+ a = _T("Hello");
+ b = _T(" world");
+ c = _T("! How'ya doin'?");
a += b;
a += c;
- c = "Hello world! What's up?";
+ c = _T("Hello world! What's up?");
if (c != a)
- c = "Doh!";
+ c = _T("Doh!");
}
wxPrintf(_T("TestString elapsed time: %ld\n"), sw.Time());
static void TestStringSub()
{
- wxString s("Hello, world!");
+ wxString s(_T("Hello, world!"));
wxPuts(_T("*** Testing wxString substring extraction ***"));
wxPuts(_T(""));
}
+// Sigh, I want Test::Simple, Test::More and Test::Harness...
+void ok(int line, bool ok, const wxString& msg = wxEmptyString)
+{
+ if( !ok )
+ wxPuts(_T("NOT OK: (") + wxString::Format(_T("%d"), line) +
+ _T(") ") + msg);
+}
+
+void is(int line, const wxString& got, const wxString& expected,
+ const wxString& msg = wxEmptyString)
+{
+ bool isOk = got == expected;
+ ok(line, isOk, msg);
+ if( !isOk )
+ {
+ wxPuts(_T("Got: ") + got);
+ wxPuts(_T("Expected: ") + expected);
+ }
+}
+
+void is(int line, const wxChar& got, const wxChar& expected,
+ const wxString& msg = wxEmptyString)
+{
+ bool isOk = got == expected;
+ ok(line, isOk, msg);
+ if( !isOk )
+ {
+ wxPuts("Got: " + got);
+ wxPuts("Expected: " + expected);
+ }
+}
+
+void TestStdString()
+{
+ wxPuts(_T("*** Testing std::string operations ***\n"));
+
+ // test ctors
+ wxString s1(_T("abcdefgh")),
+ s2(_T("abcdefghijklm"), 8),
+ s3(_T("abcdefghijklm")),
+ s4(8, _T('a'));
+ wxString s5(s1),
+ s6(s3, 0, 8),
+ s7(s3.begin(), s3.begin() + 8);
+ wxString s8(s1, 4, 8), s9, s10, s11;
+
+ is( __LINE__, s1, _T("abcdefgh") );
+ is( __LINE__, s2, s1 );
+ is( __LINE__, s4, _T("aaaaaaaa") );
+ is( __LINE__, s5, _T("abcdefgh") );
+ is( __LINE__, s6, s1 );
+ is( __LINE__, s7, s1 );
+ is( __LINE__, s8, _T("efgh") );
+
+ // test append
+ s1 = s2 = s3 = s4 = s5 = s6 = s7 = s8 = _T("abc");
+ s1.append(_T("def"));
+ s2.append(_T("defgh"), 3);
+ s3.append(wxString(_T("abcdef")), 3, 6);
+ s4.append(s1);
+ s5.append(3, _T('a'));
+ s6.append(s1.begin() + 3, s1.end());
+
+ is( __LINE__, s1, _T("abcdef") );
+ is( __LINE__, s2, _T("abcdef") );
+ is( __LINE__, s3, _T("abcdef") );
+ is( __LINE__, s4, _T("abcabcdef") );
+ is( __LINE__, s5, _T("abcaaa") );
+ is( __LINE__, s6, _T("abcdef") );
+
+ // test assign
+ s1 = s2 = s3 = s4 = s5 = s6 = s7 = s8 = _T("abc");
+ s1.assign(_T("def"));
+ s2.assign(_T("defgh"), 3);
+ s3.assign(wxString(_T("abcdef")), 3, 6);
+ s4.assign(s1);
+ s5.assign(3, _T('a'));
+ s6.assign(s1.begin() + 1, s1.end());
+
+ is( __LINE__, s1, _T("def") );
+ is( __LINE__, s2, _T("def") );
+ is( __LINE__, s3, _T("def") );
+ is( __LINE__, s4, _T("def") );
+ is( __LINE__, s5, _T("aaa") );
+ is( __LINE__, s6, _T("ef") );
+
+ // test compare
+ s1 = _T("abcdefgh");
+ s2 = _T("abcdefgh");
+ s3 = _T("abc");
+ s4 = _T("abcdefghi");
+ s5 = _T("aaa");
+ s6 = _T("zzz");
+ s7 = _T("zabcdefg");
+
+ ok( __LINE__, s1.compare(s2) == 0 );
+ ok( __LINE__, s1.compare(s3) > 0 );
+ ok( __LINE__, s1.compare(s4) < 0 );
+ ok( __LINE__, s1.compare(s5) > 0 );
+ ok( __LINE__, s1.compare(s6) < 0 );
+ ok( __LINE__, s1.compare(1, 12, s1) > 0);
+ ok( __LINE__, s1.compare(_T("abcdefgh")) == 0);
+ ok( __LINE__, s1.compare(1, 7, _T("bcdefgh")) == 0);
+ ok( __LINE__, s1.compare(1, 7, _T("bcdefgh"), 7) == 0);
+
+ // test erase
+ s1.erase(1, 1);
+ s2.erase(4, 12);
+ wxString::iterator it = s3.erase(s3.begin() + 1);
+ wxString::iterator it2 = s4.erase(s4.begin() + 4, s4.begin() + 6);
+ wxString::iterator it3 = s7.erase(s7.begin() + 4, s7.begin() + 8);
+
+ is( __LINE__, s1, _T("acdefgh") );
+ is( __LINE__, s2, _T("abcd") );
+ is( __LINE__, s3, _T("ac") );
+ is( __LINE__, s4, _T("abcdghi") );
+ is( __LINE__, s7, _T("zabc") );
+ is( __LINE__, *it, _T('c') );
+ is( __LINE__, *it2, _T('g') );
+ ok( __LINE__, it3 == s7.end() );
+
+ // test insert
+ s1 = s2 = s3 = s4 = s5 = s6 = s7 = s8 = _T("aaaa");
+ s9 = s10 = _T("cdefg");
+
+ s1.insert(1, _T("cc") );
+ s2.insert(2, _T("cdef"), 3);
+ s3.insert(2, s10);
+ s4.insert(2, s10, 3, 7);
+ s5.insert(1, 2, _T('c'));
+ it = s6.insert(s6.begin() + 3, _T('X'));
+ s7.insert(s7.begin(), s9.begin(), s9.end() - 1);
+ s8.insert(s8.begin(), 2, _T('c'));
+
+ is( __LINE__, s1, _T("accaaa") );
+ is( __LINE__, s2, _T("aacdeaa") );
+ is( __LINE__, s3, _T("aacdefgaa") );
+ is( __LINE__, s4, _T("aafgaa") );
+ is( __LINE__, s5, _T("accaaa") );
+ is( __LINE__, s6, _T("aaaXa") );
+ is( __LINE__, s7, _T("cdefaaaa") );
+ is( __LINE__, s8, _T("ccaaaa") );
+
+ s1 = s2 = s3 = _T("aaaa");
+ s1.insert(0, _T("ccc"), 2);
+ s2.insert(4, _T("ccc"), 2);
+
+ is( __LINE__, s1, _T("ccaaaa") );
+ is( __LINE__, s2, _T("aaaacc") );
+
+ // test replace
+ s1 = s2 = s3 = s4 = s5 = s6 = s7 = s8 = _T("QWERTYUIOP");
+ s9 = s10 = _T("werty");
+
+ s1.replace(3, 4, _T("rtyu"));
+ s1.replace(8, 7, _T("opopop"));
+ s2.replace(10, 12, _T("WWWW"));
+ s3.replace(1, 5, s9);
+ s4.replace(1, 4, s9, 0, 4);
+ s5.replace(1, 2, s9, 1, 12);
+ s6.replace(0, 123, s9, 0, 123);
+ s7.replace(2, 7, s9);
+
+ is( __LINE__, s1, _T("QWErtyuIopopop") );
+ is( __LINE__, s2, _T("QWERTYUIOPWWWW") );
+ is( __LINE__, s3, _T("QwertyUIOP") );
+ is( __LINE__, s4, _T("QwertYUIOP") );
+ is( __LINE__, s5, _T("QertyRTYUIOP") );
+ is( __LINE__, s6, s9);
+ is( __LINE__, s7, _T("QWwertyP") );
+
+ wxPuts(_T("*** Testing std::string operations finished ***\n"));
+}
+
#endif // TEST_STRINGS
// ----------------------------------------------------------------------------
#include "wx/snglinst.h"
#endif // TEST_SNGLINST
-static int MyStringCompare(wxString* s1, wxString* s2)
-{
- return wxStrcmp(s1->c_str(), s2->c_str());
-}
-
-static int MyStringReverseCompare(wxString* s1, wxString* s2)
-{
- return -wxStrcmp(s1->c_str(), s2->c_str());
-}
-
int main(int argc, char **argv)
{
wxApp::CheckBuildOptions(wxBuildOptions());
{
TestStringMatch();
}
+
+ TestStdString();
#endif // TEST_STRINGS
#ifdef TEST_ARRAYS
#endif
wxPuts(_T("*** After sorting a1"));
- a1.Sort(&MyStringCompare);
+ a1.Sort(wxStringCompareAscending);
PrintArray(_T("a1"), a1);
wxPuts(_T("*** After sorting a1 in reverse order"));
- a1.Sort(&MyStringReverseCompare);
+ a1.Sort(wxStringCompareDescending);
PrintArray(_T("a1"), a1);
#if !wxUSE_STL
*/
#undef HAVE_CONST_CAST
+/*
+ * Define if your compiler has std::wstring
+ */
+#undef HAVE_STD_WSTRING
+/*
+ * Define if your compiler has compilant std::string::compare
+ */
+#undef HAVE_STD_STRING_COMPARE
+
/*
* use STL for containers and wxString
*/
const unsigned int wxSTRING_MAXLEN = UINT_MAX - 100;
#endif // Visual Age
-#ifdef wxSTD_STRING_COMPATIBILITY
- const size_t wxString::npos = wxSTRING_MAXLEN;
-#endif // wxSTD_STRING_COMPATIBILITY
+#if !wxUSE_STL
+ const size_t wxStringBase::npos = wxSTRING_MAXLEN;
+#endif
// ----------------------------------------------------------------------------
// static data
// ----------------------------------------------------------------------------
+#if wxUSE_STL
+
+extern const wxChar WXDLLIMPEXP_BASE *wxEmptyString = _T("");
+
+#else
+
// for an empty string, GetStringData() will return this address: this
// structure has the same layout as wxStringData and it's data() method will
// return the empty string (dummy pointer)
// empty C style string: points to 'string data' byte of g_strEmpty
extern const wxChar WXDLLIMPEXP_BASE *wxEmptyString = &g_strEmpty.dummy;
+#endif
+
// ----------------------------------------------------------------------------
// global functions
// ----------------------------------------------------------------------------
-#if defined(wxSTD_STRING_COMPATIBILITY) && wxUSE_STD_IOSTREAM
+#if wxUSE_STD_IOSTREAM
// MS Visual C++ version 5.0 provides the new STL headers as well as the old
// iostream ones.
return os;
}
-#endif //std::string compatibility
+#endif // wxUSE_STD_IOSTREAM
// ----------------------------------------------------------------------------
// private classes
}
#endif
+#if !wxUSE_STL
+
// ===========================================================================
-// wxString class core
+// wxStringBase
// ===========================================================================
-// ---------------------------------------------------------------------------
-// construction
-// ---------------------------------------------------------------------------
-
-// constructs string of <nLength> copies of character <ch>
-wxString::wxString(wxChar ch, size_t nLength)
-{
- Init();
-
- if ( nLength > 0 ) {
- if ( !AllocBuffer(nLength) ) {
- wxFAIL_MSG( _T("out of memory in wxString::wxString") );
- return;
- }
-
-#if wxUSE_UNICODE
- // memset only works on chars
- for ( size_t n = 0; n < nLength; n++ )
- m_pchData[n] = ch;
-#else
- memset(m_pchData, ch, nLength);
-#endif
- }
-}
-
// takes nLength elements of psz starting at nPos
-void wxString::InitWith(const wxChar *psz, size_t nPos, size_t nLength)
+void wxStringBase::InitWith(const wxChar *psz, size_t nPos, size_t nLength)
{
Init();
// if the length is not given, assume the string to be NUL terminated
- if ( nLength == wxSTRING_MAXLEN ) {
+ if ( nLength == npos ) {
wxASSERT_MSG( nPos <= wxStrlen(psz), _T("index out of bounds") );
nLength = wxStrlen(psz + nPos);
if ( nLength > 0 ) {
// trailing '\0' is written in AllocBuffer()
if ( !AllocBuffer(nLength) ) {
- wxFAIL_MSG( _T("out of memory in wxString::InitWith") );
+ wxFAIL_MSG( _T("out of memory in wxStringBase::InitWith") );
return;
}
memcpy(m_pchData, psz + nPos, nLength*sizeof(wxChar));
}
}
-#ifdef wxSTD_STRING_COMPATIBILITY
-
// poor man's iterators are "void *" pointers
-wxString::wxString(const void *pStart, const void *pEnd)
+wxStringBase::wxStringBase(const void *pStart, const void *pEnd)
{
InitWith((const wxChar *)pStart, 0,
(const wxChar *)pEnd - (const wxChar *)pStart);
}
-#endif //std::string compatibility
-
-#if wxUSE_UNICODE
-
-// from multibyte string
-wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength)
-{
- // first get the size of the buffer we need
- size_t nLen;
- if ( psz )
- {
- // calculate the needed size ourselves or use the provided one
- nLen = nLength == wxSTRING_MAXLEN ? conv.MB2WC(NULL, psz, 0) : nLength;
- }
- else
- {
- // nothing to convert
- nLen = 0;
- }
-
- // anything to do?
- if ( (nLen != 0) && (nLen != (size_t)-1) )
- {
- if ( !AllocBuffer(nLen) )
- {
- wxFAIL_MSG( _T("out of memory in wxString::wxString") );
- }
- else
- {
- // MB2WC wants the buffer size, not the string length hence +1
- nLen = conv.MB2WC(m_pchData, psz, nLen + 1);
-
- if ( nLen != (size_t)-1 )
- {
- // initialized ok, set the real length as nLength specified by
- // the caller could be greater than the real string length
- GetStringData()->nDataLength = nLen;
- m_pchData[nLen] = 0;
- return;
- }
- //else: the conversion failed -- leave the string empty (what else?)
- }
- }
-
- Init();
-}
-
-#else // ANSI
-
-#if wxUSE_WCHAR_T
-// from wide string
-wxString::wxString(const wchar_t *pwz, wxMBConv& conv, size_t nLength)
+wxStringBase::wxStringBase(size_type n, wxChar ch)
{
- // first get the size of the buffer we need
- size_t nLen;
- if ( pwz )
- {
- // calculate the needed size ourselves or use the provided one
- nLen = nLength == wxSTRING_MAXLEN ? conv.WC2MB(NULL, pwz, 0) : nLength;
- }
- else
- {
- // nothing to convert
- nLen = 0;
- }
-
- // anything to do?
- if ( (nLen != 0) && (nLen != (size_t)-1) )
- {
- if ( !AllocBuffer(nLen) )
- {
- wxFAIL_MSG( _T("out of memory in wxString::wxString") );
- }
- else
- {
- // WC2MB wants the buffer size, not the string length
- if ( conv.WC2MB(m_pchData, pwz, nLen + 1) != (size_t)-1 )
- {
- // initialized ok
- return;
- }
- //else: the conversion failed -- leave the string empty (what else?)
- }
- }
-
- Init();
+ Init();
+ append(n, ch);
}
-#endif // wxUSE_WCHAR_T
-
-#endif // Unicode/ANSI
// ---------------------------------------------------------------------------
// memory allocation
// ---------------------------------------------------------------------------
// allocates memory needed to store a C string of length nLen
-bool wxString::AllocBuffer(size_t nLen)
+bool wxStringBase::AllocBuffer(size_t nLen)
{
// allocating 0 sized buffer doesn't make sense, all empty strings should
// reuse g_strEmpty
}
// must be called before changing this string
-bool wxString::CopyBeforeWrite()
+bool wxStringBase::CopyBeforeWrite()
{
wxStringData* pData = GetStringData();
}
// must be called before replacing contents of this string
-bool wxString::AllocBeforeWrite(size_t nLen)
+bool wxStringBase::AllocBeforeWrite(size_t nLen)
{
wxASSERT( nLen != 0 ); // doesn't make any sense
return TRUE;
}
+wxStringBase& wxStringBase::append(size_t n, wxChar ch)
+{
+ size_type len = length();
+
+ if ( !CopyBeforeWrite() || !Alloc(len + n) ) {
+ wxFAIL_MSG( _T("out of memory in wxStringBase::append") );
+ }
+ GetStringData()->nDataLength = len + n;
+ m_pchData[len + n] = '\0';
+ for ( size_t i = 0; i < n; ++i )
+ m_pchData[len + i] = ch;
+ return *this;
+}
+
+void wxStringBase::resize(size_t nSize, wxChar ch)
+{
+ size_t len = length();
+
+ if ( nSize < len )
+ {
+ erase(begin() + nSize, end());
+ }
+ else if ( nSize > len )
+ {
+ append(nSize - len, ch);
+ }
+ //else: we have exactly the specified length, nothing to do
+}
+
// allocate enough memory for nLen characters
-bool wxString::Alloc(size_t nLen)
+bool wxStringBase::Alloc(size_t nLen)
{
wxStringData *pData = GetStringData();
if ( pData->nAllocLength <= nLen ) {
return TRUE;
}
-// shrink to minimal size (releasing extra memory)
-bool wxString::Shrink()
+wxStringBase::iterator wxStringBase::erase(iterator it)
{
- wxStringData *pData = GetStringData();
+ size_type idx = it - begin();
+ erase(idx, 1);
+ return begin() + idx;
+}
- size_t nLen = pData->nDataLength;
- void *p = realloc(pData, sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar));
+wxStringBase& wxStringBase::erase(size_t nStart, size_t nLen)
+{
+ wxASSERT(nStart <= length());
+ size_t strLen = length() - nStart;
+ // delete nLen or up to the end of the string characters
+ nLen = strLen < nLen ? strLen : nLen;
+ wxString strTmp(c_str(), nStart);
+ strTmp.append(c_str() + nStart + nLen, length() - nStart - nLen);
- if ( p == NULL) {
- wxFAIL_MSG( _T("out of memory reallocating wxString data") );
- // keep previous data since reallocation failed
- return FALSE;
- }
+ swap(strTmp);
+ return *this;
+}
- if ( p != pData )
- {
- // contrary to what one might believe, some realloc() implementation do
- // move the memory block even when its size is reduced
- pData = (wxStringData *)p;
+wxStringBase& wxStringBase::insert(size_t nPos, const wxChar *sz, size_t n)
+{
+ wxASSERT( nPos <= length() );
- m_pchData = pData->data();
+ if ( n == npos ) n = wxStrlen(sz);
+ if ( n == 0 ) return *this;
+
+ if ( !CopyBeforeWrite() || !Alloc(length() + n) ) {
+ wxFAIL_MSG( _T("out of memory in wxStringBase::insert") );
}
- pData->nAllocLength = nLen;
+ memmove(m_pchData + nPos + n, m_pchData + nPos,
+ (length() - nPos) * sizeof(wxChar));
+ memcpy(m_pchData + nPos, sz, n * sizeof(wxChar));
+ GetStringData()->nDataLength = length() + n;
+ m_pchData[length()] = '\0';
- return TRUE;
+ return *this;
}
-// get the pointer to writable buffer of (at least) nLen bytes
-wxChar *wxString::GetWriteBuf(size_t nLen)
+void wxStringBase::swap(wxStringBase& str)
{
- if ( !AllocBeforeWrite(nLen) ) {
- // allocation failure handled by caller
- return NULL;
- }
-
- wxASSERT( GetStringData()->nRefs == 1 );
- GetStringData()->Validate(FALSE);
-
- return m_pchData;
+ wxChar* tmp = str.m_pchData;
+ str.m_pchData = m_pchData;
+ m_pchData = tmp;
}
-// put string back in a reasonable state after GetWriteBuf
-void wxString::UngetWriteBuf()
+size_t wxStringBase::find(const wxStringBase& str, size_t nStart) const
{
- GetStringData()->nDataLength = wxStrlen(m_pchData);
- GetStringData()->Validate(TRUE);
+ wxASSERT( str.GetStringData()->IsValid() );
+ wxASSERT( nStart <= length() );
+
+ const wxChar *p = wxStrstr(c_str() + nStart, str.c_str());
+
+ return p == NULL ? npos : p - c_str();
}
-void wxString::UngetWriteBuf(size_t nLen)
+size_t wxStringBase::find(const wxChar* sz, size_t nStart, size_t n) const
{
- GetStringData()->nDataLength = nLen;
- GetStringData()->Validate(TRUE);
+ return find(wxStringBase(sz, n), nStart);
}
-// ---------------------------------------------------------------------------
-// data access
-// ---------------------------------------------------------------------------
-
-// all functions are inline in string.h
+// Gives a duplicate symbol (presumably a case-insensitivity problem)
+#if !defined(__BORLANDC__)
+size_t wxStringBase::find(wxChar ch, size_t nStart) const
+{
+ wxASSERT( nStart <= length() );
-// ---------------------------------------------------------------------------
-// assignment operators
-// ---------------------------------------------------------------------------
+ const wxChar *p = wxStrchr(c_str() + nStart, ch);
-// helper function: does real copy
-bool wxString::AssignCopy(size_t nSrcLen, const wxChar *pszSrcData)
-{
- if ( nSrcLen == 0 ) {
- Reinit();
- }
- else {
- if ( !AllocBeforeWrite(nSrcLen) ) {
- // allocation failure handled by caller
- return FALSE;
- }
- memcpy(m_pchData, pszSrcData, nSrcLen*sizeof(wxChar));
- GetStringData()->nDataLength = nSrcLen;
- m_pchData[nSrcLen] = wxT('\0');
- }
- return TRUE;
+ return p == NULL ? npos : p - c_str();
}
+#endif
-// assigns one string to another
-wxString& wxString::operator=(const wxString& stringSrc)
+size_t wxStringBase::rfind(const wxStringBase& str, size_t nStart) const
{
- wxASSERT( stringSrc.GetStringData()->IsValid() );
+ wxASSERT( str.GetStringData()->IsValid() );
+ wxASSERT( nStart == npos || nStart <= length() );
- // don't copy string over itself
- if ( m_pchData != stringSrc.m_pchData ) {
- if ( stringSrc.GetStringData()->IsEmpty() ) {
- Reinit();
- }
- else {
- // adjust references
- GetStringData()->Unlock();
- m_pchData = stringSrc.m_pchData;
- GetStringData()->Lock();
- }
+ // TODO could be made much quicker than that
+ const wxChar *p = c_str() + (nStart == npos ? length() : nStart);
+ while ( p >= c_str() + str.length() ) {
+ if ( wxStrncmp(p - str.length(), str.c_str(), str.length()) == 0 )
+ return p - str.length() - c_str();
+ p--;
}
- return *this;
+ return npos;
}
-// assigns a single character
-wxString& wxString::operator=(wxChar ch)
+size_t wxStringBase::rfind(const wxChar* sz, size_t nStart, size_t n) const
{
- if ( !AssignCopy(1, &ch) ) {
- wxFAIL_MSG( _T("out of memory in wxString::operator=(wxChar)") );
- }
- return *this;
+ return rfind(wxStringBase(sz, n), nStart);
}
-
-// assigns C string
-wxString& wxString::operator=(const wxChar *psz)
+size_t wxStringBase::rfind(wxChar ch, size_t nStart) const
{
- if ( !AssignCopy(wxStrlen(psz), psz) ) {
- wxFAIL_MSG( _T("out of memory in wxString::operator=(const wxChar *)") );
- }
- return *this;
-}
+ if ( nStart == npos )
+ {
+ nStart = length();
+ }
+ else
+ {
+ wxASSERT( nStart <= length() );
+ }
-#if !wxUSE_UNICODE
+ const wxChar *p = wxStrrchr(c_str(), ch);
-// same as 'signed char' variant
-wxString& wxString::operator=(const unsigned char* psz)
-{
- *this = (const char *)psz;
- return *this;
+ if ( p == NULL )
+ return npos;
+
+ size_t result = p - c_str();
+ return ( result > nStart ) ? npos : result;
}
-#if wxUSE_WCHAR_T
-wxString& wxString::operator=(const wchar_t *pwz)
+size_t wxStringBase::find_first_of(const wxChar* sz, size_t nStart) const
{
- wxString str(pwz);
- *this = str;
- return *this;
+ const wxChar *start = c_str() + nStart;
+ const wxChar *firstOf = wxStrpbrk(start, sz);
+ if ( firstOf )
+ return firstOf - c_str();
+ else
+ return npos;
}
-#endif
-
-#endif
-
-// ---------------------------------------------------------------------------
-// string concatenation
-// ---------------------------------------------------------------------------
+
+size_t wxStringBase::find_last_of(const wxChar* sz, size_t nStart) const
+{
+ if ( nStart == npos )
+ {
+ nStart = length();
+ }
+ else
+ {
+ wxASSERT( nStart <= length() );
+ }
+
+ for ( const wxChar *p = c_str() + length() - 1; p >= c_str(); p-- )
+ {
+ if ( wxStrchr(sz, *p) )
+ return p - c_str();
+ }
+
+ return npos;
+}
+
+size_t wxStringBase::find_first_not_of(const wxChar* sz, size_t nStart) const
+{
+ if ( nStart == npos )
+ {
+ nStart = length();
+ }
+ else
+ {
+ wxASSERT( nStart <= length() );
+ }
+
+ size_t nAccept = wxStrspn(c_str() + nStart, sz);
+ if ( nAccept >= length() - nStart )
+ return npos;
+ else
+ return nAccept;
+}
+
+size_t wxStringBase::find_first_not_of(wxChar ch, size_t nStart) const
+{
+ wxASSERT( nStart <= length() );
+
+ for ( const wxChar *p = c_str() + nStart; *p; p++ )
+ {
+ if ( *p != ch )
+ return p - c_str();
+ }
+
+ return npos;
+}
+
+size_t wxStringBase::find_last_not_of(const wxChar* sz, size_t nStart) const
+{
+ if ( nStart == npos )
+ {
+ nStart = length();
+ }
+ else
+ {
+ wxASSERT( nStart <= length() );
+ }
+
+ for ( const wxChar *p = c_str() + nStart - 1; p >= c_str(); p-- )
+ {
+ if ( !wxStrchr(sz, *p) )
+ return p - c_str();
+ }
+
+ return npos;
+}
+
+size_t wxStringBase::find_last_not_of(wxChar ch, size_t nStart) const
+{
+ if ( nStart == npos )
+ {
+ nStart = length();
+ }
+ else
+ {
+ wxASSERT( nStart <= length() );
+ }
+
+ for ( const wxChar *p = c_str() + nStart - 1; p >= c_str(); p-- )
+ {
+ if ( *p != ch )
+ return p - c_str();
+ }
+
+ return npos;
+}
+
+wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
+ const wxChar *sz)
+{
+ wxASSERT_MSG( nStart <= length(),
+ _T("index out of bounds in wxStringBase::replace") );
+ size_t strLen = length() - nStart;
+ nLen = strLen < nLen ? strLen : nLen;
+
+ wxStringBase strTmp;
+ strTmp.reserve(length()); // micro optimisation to avoid multiple mem allocs
+
+ if ( nStart != 0 )
+ strTmp.append(c_str(), nStart);
+ strTmp.append(sz);
+ strTmp.append(c_str() + nStart + nLen);
+
+ swap(strTmp);
+ return *this;
+}
+
+wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
+ size_t nCount, wxChar ch)
+{
+ return replace(nStart, nLen, wxStringBase(ch, nCount).c_str());
+}
+
+wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
+ const wxStringBase& str,
+ size_t nStart2, size_t nLen2)
+{
+ return replace(nStart, nLen, str.substr(nStart2, nLen2));
+}
+
+wxStringBase& wxStringBase::replace(size_t nStart, size_t nLen,
+ const wxChar* sz, size_t nCount)
+{
+ return replace(nStart, nLen, wxStringBase(sz, nCount).c_str());
+}
+
+wxStringBase wxStringBase::substr(size_t nStart, size_t nLen) const
+{
+ if ( nLen == npos )
+ nLen = length() - nStart;
+ return wxStringBase(*this, nStart, nLen);
+}
+
+// assigns one string to another
+wxStringBase& wxStringBase::operator=(const wxStringBase& stringSrc)
+{
+ wxASSERT( stringSrc.GetStringData()->IsValid() );
+
+ // don't copy string over itself
+ if ( m_pchData != stringSrc.m_pchData ) {
+ if ( stringSrc.GetStringData()->IsEmpty() ) {
+ Reinit();
+ }
+ else {
+ // adjust references
+ GetStringData()->Unlock();
+ m_pchData = stringSrc.m_pchData;
+ GetStringData()->Lock();
+ }
+ }
+
+ return *this;
+}
+
+// assigns a single character
+wxStringBase& wxStringBase::operator=(wxChar ch)
+{
+ if ( !AssignCopy(1, &ch) ) {
+ wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(wxChar)") );
+ }
+ return *this;
+}
+
+// assigns C string
+wxStringBase& wxStringBase::operator=(const wxChar *psz)
+{
+ if ( !AssignCopy(wxStrlen(psz), psz) ) {
+ wxFAIL_MSG( _T("out of memory in wxStringBase::operator=(const wxChar *)") );
+ }
+ return *this;
+}
+
+// helper function: does real copy
+bool wxStringBase::AssignCopy(size_t nSrcLen, const wxChar *pszSrcData)
+{
+ if ( nSrcLen == 0 ) {
+ Reinit();
+ }
+ else {
+ if ( !AllocBeforeWrite(nSrcLen) ) {
+ // allocation failure handled by caller
+ return FALSE;
+ }
+ memcpy(m_pchData, pszSrcData, nSrcLen*sizeof(wxChar));
+ GetStringData()->nDataLength = nSrcLen;
+ m_pchData[nSrcLen] = wxT('\0');
+ }
+ return TRUE;
+}
+
+// ---------------------------------------------------------------------------
+// string concatenation
+// ---------------------------------------------------------------------------
// add something to this string
-bool wxString::ConcatSelf(size_t nSrcLen, const wxChar *pszSrcData)
+bool wxStringBase::ConcatSelf(size_t nSrcLen, const wxChar *pszSrcData,
+ size_t nMaxLen)
{
STATISTICS_ADD(SummandLength, nSrcLen);
+ nSrcLen = nSrcLen < nMaxLen ? nSrcLen : nMaxLen;
+
// concatenating an empty string is a NOP
if ( nSrcLen > 0 ) {
wxStringData *pData = GetStringData();
else if ( nNewLen > pData->nAllocLength ) {
STATISTICS_ADD(ConcatHit, 0);
+ reserve(nNewLen);
// we have to grow the buffer
- if ( !Alloc(nNewLen) ) {
+ if ( capacity() < nNewLen ) {
// allocation failure handled by caller
return FALSE;
}
// fast concatenation - all is done in our buffer
memcpy(m_pchData + nLen, pszSrcData, nSrcLen*sizeof(wxChar));
- m_pchData[nNewLen] = wxT('\0'); // put terminating '\0'
- GetStringData()->nDataLength = nNewLen; // and fix the length
- }
- //else: the string to append was empty
- return TRUE;
+ m_pchData[nNewLen] = wxT('\0'); // put terminating '\0'
+ GetStringData()->nDataLength = nNewLen; // and fix the length
+ }
+ //else: the string to append was empty
+ return TRUE;
+}
+
+// ---------------------------------------------------------------------------
+// simple sub-string extraction
+// ---------------------------------------------------------------------------
+
+// helper function: clone the data attached to this string
+bool wxStringBase::AllocCopy(wxString& dest, int nCopyLen, int nCopyIndex) const
+{
+ if ( nCopyLen == 0 ) {
+ dest.Init();
+ }
+ else {
+ if ( !dest.AllocBuffer(nCopyLen) ) {
+ // allocation failure handled by caller
+ return FALSE;
+ }
+ memcpy(dest.m_pchData, m_pchData + nCopyIndex, nCopyLen*sizeof(wxChar));
+ }
+ return TRUE;
+}
+
+#endif // !wxUSE_STL
+
+#if !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE)
+
+#if !wxUSE_STL
+ #define STRINGCLASS wxStringBase
+#else
+ #define STRINGCLASS wxString
+#endif
+
+static inline int wxDoCmp(const wxChar* s1, size_t l1,
+ const wxChar* s2, size_t l2)
+{
+ if( l1 == l2 )
+ return wxStrncmp(s1, s2, l1);
+ else if( l1 < l2 )
+ {
+ int ret = wxStrncmp(s1, s2, l1);
+ return ret == 0 ? -1 : ret;
+ }
+ else if( l1 > l2 )
+ {
+ int ret = wxStrncmp(s1, s2, l2);
+ return ret == 0 ? +1 : ret;
+ }
+
+ wxFAIL; // must never get there
+ return 0; // quiet compilers
+}
+
+#if wxUSE_STL
+
+int STRINGCLASS::compare(const wxStringBase& str) const
+{
+ return ::wxDoCmp(data(), length(), str.data(), str.length());
+}
+
+#endif
+
+int STRINGCLASS::compare(size_t nStart, size_t nLen,
+ const wxStringBase& str) const
+{
+ wxASSERT(nStart <= length());
+ size_type strLen = length() - nStart;
+ nLen = strLen < nLen ? strLen : nLen;
+ return ::wxDoCmp(data() + nStart, nLen, str.data(), str.length());
+}
+
+int STRINGCLASS::compare(size_t nStart, size_t nLen,
+ const wxStringBase& str,
+ size_t nStart2, size_t nLen2) const
+{
+ wxASSERT(nStart <= length());
+ wxASSERT(nStart2 <= str.length());
+ size_type strLen = length() - nStart,
+ strLen2 = str.length() - nStart2;
+ nLen = strLen < nLen ? strLen : nLen;
+ nLen2 = strLen2 < nLen2 ? strLen2 : nLen2;
+ return ::wxDoCmp(data() + nStart, nLen, str.data() + nStart2, nLen2);
+}
+
+#if wxUSE_STL
+
+int STRINGCLASS::compare(const wxChar* sz) const
+{
+ size_t nLen = wxStrlen(sz);
+ return ::wxDoCmp(data(), length(), sz, nLen);
+}
+
+#endif
+
+int STRINGCLASS::compare(size_t nStart, size_t nLen,
+ const wxChar* sz, size_t nCount) const
+{
+ wxASSERT(nStart <= length());
+ size_type strLen = length() - nStart;
+ nLen = strLen < nLen ? strLen : nLen;
+ if( nCount == npos )
+ nCount = wxStrlen(sz);
+
+ return ::wxDoCmp(data() + nStart, nLen, sz, nCount);
+}
+
+#undef STRINGCLASS
+
+#endif // !wxUSE_STL || !defined(HAVE_STD_STRING_COMPARE)
+
+// ===========================================================================
+// wxString class core
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// construction
+// ---------------------------------------------------------------------------
+
+#if wxUSE_UNICODE
+
+// from multibyte string
+wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength)
+{
+ // first get the size of the buffer we need
+ size_t nLen;
+ if ( psz )
+ {
+ // calculate the needed size ourselves or use the provided one
+ nLen = nLength == npos ? conv.MB2WC(NULL, psz, 0) : nLength;
+ }
+ else
+ {
+ // nothing to convert
+ nLen = 0;
+ }
+
+ // anything to do?
+ if ( (nLen != 0) && (nLen != (size_t)-1) )
+ {
+ if ( !Alloc(nLen) )
+ {
+ wxFAIL_MSG( _T("out of memory in wxString::wxString") );
+ }
+ else
+ {
+ wxWCharBuffer buf(nLen + 1);
+ // MB2WC wants the buffer size, not the string length hence +1
+ nLen = conv.MB2WC(buf.data(), psz, nLen + 1);
+
+ if ( nLen != (size_t)-1 )
+ {
+ // initialized ok, set the real length as nLength specified by
+ // the caller could be greater than the real string length
+ assign(buf.data(), nLen);
+ return;
+ }
+ //else: the conversion failed -- leave the string empty (what else?)
+ }
+ }
+}
+
+#else // ANSI
+
+#if wxUSE_WCHAR_T
+// from wide string
+wxString::wxString(const wchar_t *pwz, wxMBConv& conv, size_t nLength)
+{
+ // first get the size of the buffer we need
+ size_t nLen;
+ if ( pwz )
+ {
+ // calculate the needed size ourselves or use the provided one
+ nLen = nLength == npos ? conv.WC2MB(NULL, pwz, 0) : nLength;
+ }
+ else
+ {
+ // nothing to convert
+ nLen = 0;
+ }
+
+ // anything to do?
+ if ( (nLen != 0) && (nLen != (size_t)-1) )
+ {
+ if ( !Alloc(nLen) )
+ {
+ wxFAIL_MSG( _T("out of memory in wxString::wxString") );
+ }
+ else
+ {
+ wxCharBuffer buf(nLen);
+ // WC2MB wants the buffer size, not the string length
+ if ( conv.WC2MB(buf.data(), pwz, nLen + 1) != (size_t)-1 )
+ {
+ // initialized ok
+ assign(buf.data(), nLen);
+ return;
+ }
+ //else: the conversion failed -- leave the string empty (what else?)
+ }
+ }
+
+ // leave empty
+}
+#endif // wxUSE_WCHAR_T
+
+#endif // Unicode/ANSI
+
+// shrink to minimal size (releasing extra memory)
+bool wxString::Shrink()
+{
+ wxString tmp(begin(), end());
+ swap(tmp);
+ return tmp.length() == length();
+}
+
+#if !wxUSE_STL
+// get the pointer to writable buffer of (at least) nLen bytes
+wxChar *wxString::GetWriteBuf(size_t nLen)
+{
+ if ( !AllocBeforeWrite(nLen) ) {
+ // allocation failure handled by caller
+ return NULL;
+ }
+
+ wxASSERT( GetStringData()->nRefs == 1 );
+ GetStringData()->Validate(FALSE);
+
+ return m_pchData;
+}
+
+// put string back in a reasonable state after GetWriteBuf
+void wxString::UngetWriteBuf()
+{
+ GetStringData()->nDataLength = wxStrlen(m_pchData);
+ GetStringData()->Validate(TRUE);
+}
+
+void wxString::UngetWriteBuf(size_t nLen)
+{
+ GetStringData()->nDataLength = nLen;
+ GetStringData()->Validate(TRUE);
+}
+#endif
+
+// ---------------------------------------------------------------------------
+// data access
+// ---------------------------------------------------------------------------
+
+// all functions are inline in string.h
+
+// ---------------------------------------------------------------------------
+// assignment 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:
wxString operator+(const wxString& str1, const wxString& str2)
{
+#if !wxUSE_STL
wxASSERT( str1.GetStringData()->IsValid() );
wxASSERT( str2.GetStringData()->IsValid() );
+#endif
wxString s = str1;
s += str2;
wxString operator+(const wxString& str, wxChar ch)
{
+#if !wxUSE_STL
wxASSERT( str.GetStringData()->IsValid() );
+#endif
wxString s = str;
s += ch;
wxString operator+(wxChar ch, const wxString& str)
{
+#if !wxUSE_STL
wxASSERT( str.GetStringData()->IsValid() );
+#endif
wxString s = ch;
s += str;
wxString operator+(const wxString& str, const wxChar *psz)
{
+#if !wxUSE_STL
wxASSERT( str.GetStringData()->IsValid() );
+#endif
wxString s;
if ( !s.Alloc(wxStrlen(psz) + str.Len()) ) {
wxString operator+(const wxChar *psz, const wxString& str)
{
+#if !wxUSE_STL
wxASSERT( str.GetStringData()->IsValid() );
+#endif
wxString s;
if ( !s.Alloc(wxStrlen(psz) + str.Len()) ) {
#endif // Unicode
-// ---------------------------------------------------------------------------
-// simple sub-string extraction
-// ---------------------------------------------------------------------------
-
-// helper function: clone the data attached to this string
-bool wxString::AllocCopy(wxString& dest, int nCopyLen, int nCopyIndex) const
-{
- if ( nCopyLen == 0 ) {
- dest.Init();
- }
- else {
- if ( !dest.AllocBuffer(nCopyLen) ) {
- // allocation failure handled by caller
- return FALSE;
- }
- memcpy(dest.m_pchData, m_pchData + nCopyIndex, nCopyLen*sizeof(wxChar));
- }
- return TRUE;
-}
-
// extract string of length nCount starting at nFirst
wxString wxString::Mid(size_t nFirst, size_t nCount) const
{
- wxStringData *pData = GetStringData();
- size_t nLen = pData->nDataLength;
+ size_t nLen = length();
- // default value of nCount is wxSTRING_MAXLEN and means "till the end"
- if ( nCount == wxSTRING_MAXLEN )
+ // default value of nCount is npos and means "till the end"
+ if ( nCount == npos )
{
nCount = nLen - nFirst;
}
nCount = 0;
}
- wxString dest;
- if ( !AllocCopy(dest, nCount, nFirst) ) {
+ wxString dest(*this, nFirst, nCount);
+ if ( dest.length() != nCount ) {
wxFAIL_MSG( _T("out of memory in wxString::Mid") );
}
return dest;
}
-// check that the tring starts with prefix and return the rest of the string
+// check that the string starts with prefix and return the rest of the string
// in the provided pointer if it is not NULL, otherwise return FALSE
bool wxString::StartsWith(const wxChar *prefix, wxString *rest) const
{
// extract nCount last (rightmost) characters
wxString wxString::Right(size_t nCount) const
{
- if ( nCount > (size_t)GetStringData()->nDataLength )
- nCount = GetStringData()->nDataLength;
+ if ( nCount > length() )
+ nCount = length();
- wxString dest;
- if ( !AllocCopy(dest, nCount, GetStringData()->nDataLength - nCount) ) {
+ wxString dest(*this, length() - nCount, nCount);
+ if ( dest.length() != nCount ) {
wxFAIL_MSG( _T("out of memory in wxString::Right") );
}
return dest;
// extract nCount first (leftmost) characters
wxString wxString::Left(size_t nCount) const
{
- if ( nCount > (size_t)GetStringData()->nDataLength )
- nCount = GetStringData()->nDataLength;
+ if ( nCount > length() )
+ nCount = length();
- wxString dest;
- if ( !AllocCopy(dest, nCount, 0) ) {
+ wxString dest(*this, 0, nCount);
+ if ( dest.length() != nCount ) {
wxFAIL_MSG( _T("out of memory in wxString::Left") );
}
return dest;
// (returns the whole string if ch not found)
wxString wxString::BeforeFirst(wxChar ch) const
{
- wxString str;
- for ( const wxChar *pc = m_pchData; *pc != wxT('\0') && *pc != ch; pc++ )
- str += *pc;
-
- return str;
+ int iPos = Find(ch);
+ if ( iPos == wxNOT_FOUND ) iPos = length();
+ return wxString(*this, 0, iPos);
}
/// get all characters before the last occurence of ch
size_t uiOldLen = wxStrlen(szOld);
wxString strTemp;
- const wxChar *pCurrent = m_pchData;
+ const wxChar *pCurrent = c_str();
const wxChar *pSubstr;
while ( *pCurrent != wxT('\0') ) {
pSubstr = wxStrstr(pCurrent, szOld);
}
else {
// take chars before match
- if ( !strTemp.ConcatSelf(pSubstr - pCurrent, pCurrent) ) {
+ size_type len = strTemp.length();
+ strTemp.append(pCurrent, pSubstr - pCurrent);
+ if ( strTemp.length() != (size_t)(len + pSubstr - pCurrent) ) {
wxFAIL_MSG( _T("out of memory in wxString::Replace") );
return 0;
}
}
// only done if there were replacements, otherwise would have returned above
- *this = strTemp;
+ swap(strTemp);
return uiCount;
}
wxString& wxString::MakeUpper()
{
- if ( !CopyBeforeWrite() ) {
- wxFAIL_MSG( _T("out of memory in wxString::MakeUpper") );
- return *this;
- }
-
- for ( wxChar *p = m_pchData; *p; p++ )
- *p = (wxChar)wxToupper(*p);
+ for ( iterator it = begin(), en = end(); it != en; ++it )
+ *it = (wxChar)wxToupper(*it);
return *this;
}
wxString& wxString::MakeLower()
{
- if ( !CopyBeforeWrite() ) {
- wxFAIL_MSG( _T("out of memory in wxString::MakeLower") );
- return *this;
- }
-
- for ( wxChar *p = m_pchData; *p; p++ )
- *p = (wxChar)wxTolower(*p);
+ for ( iterator it = begin(), en = end(); it != en; ++it )
+ *it = (wxChar)wxTolower(*it);
return *this;
}
)
)
{
- // ok, there is at least one space to trim
- if ( !CopyBeforeWrite() ) {
- wxFAIL_MSG( _T("out of memory in wxString::Trim") );
- return *this;
- }
-
if ( bFromRight )
{
// find last non-space character
- wxChar *psz = m_pchData + GetStringData()->nDataLength - 1;
- while ( wxSafeIsspace(*psz) && (psz >= m_pchData) )
+ iterator psz = begin() + length() - 1;
+ while ( wxSafeIsspace(*psz) && (psz >= begin()) )
psz--;
// truncate at trailing space start
*++psz = wxT('\0');
- GetStringData()->nDataLength = psz - m_pchData;
+ erase(psz, end());
}
else
{
// find first non-space character
- const wxChar *psz = m_pchData;
+ iterator psz = begin();
while ( wxSafeIsspace(*psz) )
psz++;
// fix up data and length
- int nDataLength = GetStringData()->nDataLength - (psz - (const wxChar*) m_pchData);
- memmove(m_pchData, psz, (nDataLength + 1)*sizeof(wxChar));
- GetStringData()->nDataLength = nDataLength;
+ erase(begin(), psz);
}
}
else
{
s += *this;
- *this = s;
+ swap(s);
}
return *this;
wxString& wxString::Truncate(size_t uiLen)
{
if ( uiLen < Len() ) {
- if ( !CopyBeforeWrite() ) {
- wxFAIL_MSG( _T("out of memory in wxString::Truncate") );
- return *this;
- }
-
- *(m_pchData + uiLen) = wxT('\0');
- GetStringData()->nDataLength = uiLen;
+ erase(begin() + uiLen, end());
}
//else: nothing to do, string is already short enough
// find a character
int wxString::Find(wxChar ch, bool bFromEnd) const
{
- const wxChar *psz = bFromEnd ? wxStrrchr(m_pchData, ch) : wxStrchr(m_pchData, ch);
+ size_type idx = bFromEnd ? find_last_of(ch) : find_first_of(ch);
- return (psz == NULL) ? wxNOT_FOUND : psz - (const wxChar*) m_pchData;
+ return (idx == npos) ? wxNOT_FOUND : (int)idx;
}
// find a sub-string (like strstr)
int wxString::Find(const wxChar *pszSub) const
{
- const wxChar *psz = wxStrstr(m_pchData, pszSub);
+ size_type idx = find(pszSub);
- return (psz == NULL) ? wxNOT_FOUND : psz - (const wxChar*) m_pchData;
+ return (idx == npos) ? wxNOT_FOUND : (int)idx;
}
// ----------------------------------------------------------------------------
int wxString::PrintfV(const wxChar* pszFormat, va_list argptr)
{
int size = 1024;
+ int len;
+
for ( ;; )
{
- wxChar *buf = GetWriteBuf(size + 1);
- if ( !buf )
{
- // out of memory
- return -1;
- }
+ wxStringBuffer tmp(*this, size + 1);
+ wxChar* buf = tmp;
- int len = wxVsnprintf(buf, size, pszFormat, argptr);
+ if ( !buf )
+ {
+ // out of memory
+ return -1;
+ }
- // some implementations of vsnprintf() don't NUL terminate the string
- // if there is not enough space for it so always do it manually
- buf[size] = _T('\0');
+ len = wxVsnprintf(buf, size, pszFormat, argptr);
- UngetWriteBuf();
+ // some implementations of vsnprintf() don't NUL terminate
+ // the string if there is not enough space for it so
+ // always do it manually
+ buf[size] = _T('\0');
+ }
if ( len >= 0 )
{
return iLen;
}
-// ---------------------------------------------------------------------------
-// standard C++ library string functions
-// ---------------------------------------------------------------------------
-
-#ifdef wxSTD_STRING_COMPATIBILITY
-
-void wxString::resize(size_t nSize, wxChar ch)
-{
- size_t len = length();
-
- if ( nSize < len )
- {
- Truncate(nSize);
- }
- else if ( nSize > len )
- {
- *this += wxString(ch, nSize - len);
- }
- //else: we have exactly the specified length, nothing to do
-}
-
-void wxString::swap(wxString& str)
-{
- // this is slightly less efficient than fiddling with m_pchData directly,
- // but it is still quite efficient as we don't copy the string here because
- // ref count always stays positive
- wxString tmp = str;
- str = *this;
- *this = tmp;
-}
-
-wxString& wxString::insert(size_t nPos, const wxString& str)
-{
- wxASSERT( str.GetStringData()->IsValid() );
- wxASSERT( nPos <= Len() );
-
- if ( !str.IsEmpty() ) {
- wxString strTmp;
- wxChar *pc = strTmp.GetWriteBuf(Len() + str.Len());
- wxStrncpy(pc, c_str(), nPos);
- wxStrcpy(pc + nPos, str);
- wxStrcpy(pc + nPos + str.Len(), c_str() + nPos);
- strTmp.UngetWriteBuf();
- *this = strTmp;
- }
-
- return *this;
-}
-
-size_t wxString::find(const wxString& str, size_t nStart) const
-{
- wxASSERT( str.GetStringData()->IsValid() );
- wxASSERT( nStart <= Len() );
-
- const wxChar *p = wxStrstr(c_str() + nStart, str);
-
- return p == NULL ? npos : p - c_str();
-}
-
-// VC++ 1.5 can't cope with the default argument in the header.
-#if !defined(__VISUALC__) || defined(__WIN32__)
-size_t wxString::find(const wxChar* sz, size_t nStart, size_t n) const
-{
- return find(wxString(sz, n), nStart);
-}
-#endif // VC++ 1.5
-
-// Gives a duplicate symbol (presumably a case-insensitivity problem)
-#if !defined(__BORLANDC__)
-size_t wxString::find(wxChar ch, size_t nStart) const
-{
- wxASSERT( nStart <= Len() );
-
- const wxChar *p = wxStrchr(c_str() + nStart, ch);
-
- return p == NULL ? npos : p - c_str();
-}
-#endif
-
-size_t wxString::rfind(const wxString& str, size_t nStart) const
-{
- wxASSERT( str.GetStringData()->IsValid() );
- wxASSERT( nStart == npos || nStart <= Len() );
-
- // TODO could be made much quicker than that
- const wxChar *p = c_str() + (nStart == npos ? Len() : nStart);
- while ( p >= c_str() + str.Len() ) {
- if ( wxStrncmp(p - str.Len(), str, str.Len()) == 0 )
- return p - str.Len() - c_str();
- p--;
- }
-
- return npos;
-}
-
-// VC++ 1.5 can't cope with the default argument in the header.
-#if !defined(__VISUALC__) || defined(__WIN32__)
-size_t wxString::rfind(const wxChar* sz, size_t nStart, size_t n) const
-{
- return rfind(wxString(sz, n == npos ? wxSTRING_MAXLEN : n), nStart);
-}
-
-size_t wxString::rfind(wxChar ch, size_t nStart) const
-{
- if ( nStart == npos )
- {
- nStart = Len();
- }
- else
- {
- wxASSERT( nStart <= Len() );
- }
-
- const wxChar *p = wxStrrchr(c_str(), ch);
-
- if ( p == NULL )
- return npos;
-
- size_t result = p - c_str();
- return ( result > nStart ) ? npos : result;
-}
-#endif // VC++ 1.5
-
-size_t wxString::find_first_of(const wxChar* sz, size_t nStart) const
-{
- const wxChar *start = c_str() + nStart;
- const wxChar *firstOf = wxStrpbrk(start, sz);
- if ( firstOf )
- return firstOf - c_str();
- else
- return npos;
-}
-
-size_t wxString::find_last_of(const wxChar* sz, size_t nStart) const
-{
- if ( nStart == npos )
- {
- nStart = Len();
- }
- else
- {
- wxASSERT( nStart <= Len() );
- }
-
- for ( const wxChar *p = c_str() + length() - 1; p >= c_str(); p-- )
- {
- if ( wxStrchr(sz, *p) )
- return p - c_str();
- }
-
- return npos;
-}
-
-size_t wxString::find_first_not_of(const wxChar* sz, size_t nStart) const
-{
- if ( nStart == npos )
- {
- nStart = Len();
- }
- else
- {
- wxASSERT( nStart <= Len() );
- }
-
- size_t nAccept = wxStrspn(c_str() + nStart, sz);
- if ( nAccept >= length() - nStart )
- return npos;
- else
- return nAccept;
-}
-
-size_t wxString::find_first_not_of(wxChar ch, size_t nStart) const
-{
- wxASSERT( nStart <= Len() );
-
- for ( const wxChar *p = c_str() + nStart; *p; p++ )
- {
- if ( *p != ch )
- return p - c_str();
- }
-
- return npos;
-}
-
-size_t wxString::find_last_not_of(const wxChar* sz, size_t nStart) const
-{
- if ( nStart == npos )
- {
- nStart = Len();
- }
- else
- {
- wxASSERT( nStart <= Len() );
- }
-
- for ( const wxChar *p = c_str() + nStart - 1; p >= c_str(); p-- )
- {
- if ( !wxStrchr(sz, *p) )
- return p - c_str();
- }
-
- return npos;
-}
-
-size_t wxString::find_last_not_of(wxChar ch, size_t nStart) const
-{
- if ( nStart == npos )
- {
- nStart = Len();
- }
- else
- {
- wxASSERT( nStart <= Len() );
- }
-
- for ( const wxChar *p = c_str() + nStart - 1; p >= c_str(); p-- )
- {
- if ( *p != ch )
- return p - c_str();
- }
-
- return npos;
-}
-
-wxString& wxString::erase(size_t nStart, size_t nLen)
-{
- wxString strTmp(c_str(), nStart);
- if ( nLen != npos ) {
- wxASSERT( nStart + nLen <= Len() );
-
- strTmp.append(c_str() + nStart + nLen);
- }
-
- *this = strTmp;
- return *this;
-}
-
-wxString& wxString::replace(size_t nStart, size_t nLen, const wxChar *sz)
-{
- wxASSERT_MSG( nStart + nLen <= Len(),
- _T("index out of bounds in wxString::replace") );
-
- wxString strTmp;
- strTmp.Alloc(Len()); // micro optimisation to avoid multiple mem allocs
-
- if ( nStart != 0 )
- strTmp.append(c_str(), nStart);
- strTmp << sz << c_str() + nStart + nLen;
-
- *this = strTmp;
- return *this;
-}
-
-wxString& wxString::replace(size_t nStart, size_t nLen, size_t nCount, wxChar ch)
-{
- return replace(nStart, nLen, wxString(ch, nCount));
-}
-
-wxString& wxString::replace(size_t nStart, size_t nLen,
- const wxString& str, size_t nStart2, size_t nLen2)
-{
- return replace(nStart, nLen, str.substr(nStart2, nLen2));
-}
-
-wxString& wxString::replace(size_t nStart, size_t nLen,
- const wxChar* sz, size_t nCount)
-{
- return replace(nStart, nLen, wxString(sz, nCount));
-}
-
-#endif //std::string compatibility
-
// ============================================================================
// ArrayString
// ============================================================================