X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/2f000c959a0ca9e7eb2a41cc7553b190322a8b66..45016e1a6bfed375993470efa844b94a42a41c73:/include/wx/string.h diff --git a/include/wx/string.h b/include/wx/string.h index 96a2184a64..d21eb47a47 100644 --- a/include/wx/string.h +++ b/include/wx/string.h @@ -9,17 +9,43 @@ // Licence: wxWindows license /////////////////////////////////////////////////////////////////////////////// +/* + Efficient string class [more or less] compatible with MFC CString, + wxWindows version 1 wxString and std::string and some handy functions + missing from string.h. +*/ + #ifndef _WX_WXSTRINGH__ #define _WX_WXSTRINGH__ #ifdef __GNUG__ -#pragma interface "string.h" + #pragma interface "string.h" #endif +// ---------------------------------------------------------------------------- +// conditinal compilation +// ---------------------------------------------------------------------------- + +// compile the std::string compatibility functions if defined +#define wxSTD_STRING_COMPATIBILITY + +// define to derive wxString from wxObject (deprecated!) +#ifdef WXSTRING_IS_WXOBJECT + #undef WXSTRING_IS_WXOBJECT +#endif + +// ---------------------------------------------------------------------------- +// headers +// ---------------------------------------------------------------------------- + #ifdef __WXMAC__ #include #endif +#ifdef __EMX__ + #include +#endif + #include #include #include @@ -30,53 +56,53 @@ #include // for strcasecmp() #endif // AIX -#ifndef WX_PRECOMP - #include "wx/defs.h" +#include "wx/defs.h" // everybody should include this +#include "wx/debug.h" // for wxASSERT() +#include "wx/wxchar.h" // for wxChar +#include "wx/buffer.h" // for wxCharBuffer +#include "wx/strconv.h" // for wxConvertXXX() macros and wxMBConv classes +#ifndef WX_PRECOMP #ifdef WXSTRING_IS_WXOBJECT - #include "wx/object.h" + #include "wx/object.h" // base class #endif #endif // !PCH -#include "wx/debug.h" -#include "wx/wxchar.h" -#include "wx/buffer.h" - -/* - Efficient string class [more or less] compatible with MFC CString, - wxWindows version 1 wxString and std::string and some handy functions - missing from string.h. -*/ - // --------------------------------------------------------------------------- // macros // --------------------------------------------------------------------------- -// compile the std::string compatibility functions if defined -#define wxSTD_STRING_COMPATIBILITY +// 'naughty' cast +#define WXSTRINGCAST (wxChar *)(const wxChar *) +#define wxCSTRINGCAST (wxChar *)(const wxChar *) +#define wxMBSTRINGCAST (char *)(const char *) +#define wxWCSTRINGCAST (wchar_t *)(const wchar_t *) -// define to derive wxString from wxObject -#ifdef WXSTRING_IS_WXOBJECT -#undef WXSTRING_IS_WXOBJECT -#endif +// implementation only +#define ASSERT_VALID_INDEX(i) wxASSERT( (unsigned)(i) <= Len() ) + +// ---------------------------------------------------------------------------- +// constants +// ---------------------------------------------------------------------------- // maximum possible length for a string means "take all string" everywhere -// (as sizeof(StringData) is unknown here we substract 100) +// (as sizeof(StringData) is unknown here, we substract 100) const unsigned int wxSTRING_MAXLEN = UINT_MAX - 100; -// 'naughty' cast -#define WXSTRINGCAST (wxChar *)(const wxChar *) -#define MBSTRINGCAST (char *)(const char *) -#define WCSTRINGCAST (wchar_t *)(const wchar_t *) +// ---------------------------------------------------------------------------- +// global data +// ---------------------------------------------------------------------------- -// implementation only -#define ASSERT_VALID_INDEX(i) wxASSERT( (unsigned)(i) <= Len() ) +// global pointer to empty string +WXDLLEXPORT_DATA(extern const wxChar*) wxEmptyString; // --------------------------------------------------------------------------- -// Global functions complementing standard C string library replacements for +// global functions complementing standard C string library replacements for // strlen() and portable strcasecmp() //--------------------------------------------------------------------------- -// USE wx* FUNCTIONS IN wx/wxchar.h INSTEAD - THIS IS ONLY FOR BINARY COMPATIBILITY + +// Use wxXXX() functions from wxchar.h instead! These functions are for +// backwards compatibility only. // checks whether the passed in pointer is NULL and if the string is empty inline bool WXDLLEXPORT IsEmpty(const char *p) { return (!p || !*p); } @@ -88,17 +114,21 @@ inline size_t WXDLLEXPORT Strlen(const char *psz) // portable strcasecmp/_stricmp inline int WXDLLEXPORT Stricmp(const char *psz1, const char *psz2) { -#if defined(__VISUALC__) || ( defined(__MWERKS__) && defined(__INTEL__) ) +#if defined(__VISUALC__) || ( defined(__MWERKS__) && defined(__INTEL__) ) return _stricmp(psz1, psz2); -#elif defined(__SC__) +#elif defined(__SC__) return _stricmp(psz1, psz2); -#elif defined(__SALFORDC__) +#elif defined(__SALFORDC__) return stricmp(psz1, psz2); #elif defined(__BORLANDC__) return stricmp(psz1, psz2); #elif defined(__WATCOMC__) return stricmp(psz1, psz2); -#elif defined(__UNIX__) || defined(__GNUWIN32__) +#elif defined(__EMX__) + return stricmp(psz1, psz2); +#elif defined(__WXPM__) + return stricmp(psz1, psz2); +#elif defined(__UNIX__) || defined(__GNUWIN32__) return strcasecmp(psz1, psz2); #elif defined(__MWERKS__) && !defined(__INTEL__) register char c1, c2; @@ -126,23 +156,15 @@ inline int WXDLLEXPORT Stricmp(const char *psz1, const char *psz2) #endif // OS/compiler } -// ---------------------------------------------------------------------------- -// global data -// ---------------------------------------------------------------------------- - -WXDLLEXPORT_DATA(extern const wxChar*) wxEmptyString; - -// global pointer to empty string -WXDLLEXPORT_DATA(extern const wxChar*) g_szNul; - // return an empty wxString class WXDLLEXPORT wxString; // not yet defined -inline const wxString& wxGetEmptyString() { return *(wxString *)&g_szNul; } +inline const wxString& wxGetEmptyString() { return *(wxString *)&wxEmptyString; } // --------------------------------------------------------------------------- // string data prepended with some housekeeping info (used by wxString class), // is never used directly (but had to be put here to allow inlining) // --------------------------------------------------------------------------- + struct WXDLLEXPORT wxStringData { int nRefs; // reference count @@ -166,87 +188,6 @@ struct WXDLLEXPORT wxStringData bool IsValid() const { return (nRefs != 0); } }; -// --------------------------------------------------------------------------- -// types of multibyte<->Unicode conversions -// --------------------------------------------------------------------------- -class WXDLLEXPORT wxMBConv -{ - public: - virtual size_t MB2WC(wchar_t *buf, const char *psz, size_t n) const; - virtual size_t WC2MB(char *buf, const wchar_t *psz, size_t n) const; - const wxWCharBuffer cMB2WC(const char *psz) const - { - size_t nLen = MB2WC((wchar_t *) NULL, psz, 0); - wxWCharBuffer buf(nLen); - MB2WC(WCSTRINGCAST buf, psz, nLen); - return buf; - } - const wxCharBuffer cWC2MB(const wchar_t *psz) const - { - size_t nLen = WC2MB((char *) NULL, psz, 0); - wxCharBuffer buf(nLen); - WC2MB(MBSTRINGCAST buf, psz, nLen); - return buf; - } -#if wxUSE_UNICODE - const wxWCharBuffer cMB2WX(const char *psz) const { return cMB2WC(psz); } - const wxCharBuffer cWX2MB(const wchar_t *psz) const { return cWC2MB(psz); } - const wchar_t* cWC2WX(const wchar_t *psz) const { return psz; } - const wchar_t* cMB2WC(const wchar_t *psz) const { return psz; } -#else - const char* cMB2WX(const char *psz) const { return psz; } - const char* cWX2MB(const char *psz) const { return psz; } - const wxCharBuffer cWC2WX(const wchar_t *psz) const { return cWC2MB(psz); } - const wxWCharBuffer cWX2WC(const char *psz) const { return cMB2WC(psz); } -#endif -}; -WXDLLEXPORT_DATA(extern wxMBConv) wxConv_libc; - -#define wxANOTHER_MBCONV(type) \ -class type : public wxMBConv { \ - public: \ - virtual size_t MB2WC(wchar_t *buf, const char *psz, size_t n) const; \ - virtual size_t WC2MB(char *buf, const wchar_t *psz, size_t n) const; \ -} - -WXDLLEXPORT_DATA(extern wxANOTHER_MBCONV(wxMBConv_file)) wxConv_file; -WXDLLEXPORT_DATA(extern wxANOTHER_MBCONV(wxMBConv_UTF7)) wxConv_UTF7; -WXDLLEXPORT_DATA(extern wxANOTHER_MBCONV(wxMBConv_UTF8)) wxConv_UTF8; -#if defined(__WXGTK__) && (GTK_MINOR_VERSION > 0) - WXDLLEXPORT_DATA(extern wxANOTHER_MBCONV(wxMBConv_gdk)) wxConv_gdk; -#endif // GTK > 1.0 - -class wxCharacterSet; -class WXDLLEXPORT wxCSConv : public wxMBConv -{ - private: - wxCharacterSet *cset; - public: - wxCSConv(const wxChar *charset); - virtual ~wxCSConv(void); - virtual size_t MB2WC(wchar_t *buf, const char *psz, size_t n) const; - virtual size_t WC2MB(char *buf, const wchar_t *psz, size_t n) const; -}; - -WXDLLEXPORT_DATA(extern wxCSConv) wxConv_local; - -WXDLLEXPORT_DATA(extern wxMBConv *) wxConv_current; - -// filenames are multibyte on Unix and probably widechar on Windows? -#ifdef __UNIX__ -#define wxMBFILES 1 -#else -#define wxMBFILES 0 -#endif - -#if wxMBFILES -#define wxFNCONV(name) wxConv_file.cWX2MB(name) -#define FNSTRINGCAST MBSTRINGCAST -#else -#define wxFNCONV(name) name -#define FNSTRINGCAST WXSTRINGCAST -#endif - // --------------------------------------------------------------------------- // This is (yet another one) String class for C++ programmers. It doesn't use // any of "advanced" C++ features (i.e. templates, exceptions, namespaces...) @@ -294,7 +235,7 @@ private: // string (re)initialization functions // initializes the string to the empty value (must be called only from // ctors, use Reinit() otherwise) - void Init() { m_pchData = (wxChar *)g_szNul; } + 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); // as Init, but also frees old data @@ -347,24 +288,33 @@ public: // (default value of wxSTRING_MAXLEN means take all the string) wxString(const wxChar *psz, size_t nLength = wxSTRING_MAXLEN) { InitWith(psz, 0, 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 = wxConv_libc, size_t nLength = wxSTRING_MAXLEN); + wxString(const char *psz, wxMBConv& conv = wxConvLibc, size_t nLength = wxSTRING_MAXLEN); // from wxWCharBuffer (i.e. return from wxGetString) wxString(const wxWCharBuffer& psz) { InitWith(psz, 0, wxSTRING_MAXLEN); } -#else +#else // ANSI // from C string (for compilers using unsigned char) wxString(const unsigned char* psz, size_t nLength = wxSTRING_MAXLEN) { InitWith((const char*)psz, 0, nLength); } + // from multibyte string + wxString(const char *psz, wxMBConv& WXUNUSED(conv), size_t nLength = wxSTRING_MAXLEN) + { InitWith(psz, 0, nLength); } + +#if wxUSE_WCHAR_T // from wide (Unicode) string wxString(const wchar_t *pwz); +#endif // !wxUSE_WCHAR_T + // from wxCharBuffer wxString(const wxCharBuffer& psz) { InitWith(psz, 0, wxSTRING_MAXLEN); } -#endif +#endif // Unicode/ANSI + // dtor is not virtual, this class must not be inherited from! ~wxString() { GetStringData()->Unlock(); } @@ -440,23 +390,38 @@ public: operator const wxChar*() const { return m_pchData; } // explicit conversion to C string (use this with printf()!) const wxChar* c_str() const { return m_pchData; } - // + // (and this with [wx]Printf()!) + const wxChar* wx_str() const { return m_pchData; } + // identical to c_str() const wxChar* GetData() const { return m_pchData; } + + // conversions with (possible) format convertions: have to return a + // buffer with temporary data #if wxUSE_UNICODE - const wxCharBuffer mb_str(wxMBConv& conv = wxConv_libc) const { return conv.cWC2MB(m_pchData); } - const wxChar* wc_str(wxMBConv& WXUNUSED(conv) = wxConv_libc) const { return m_pchData; } + const wxCharBuffer mb_str(wxMBConv& conv = wxConvLibc) const { return conv.cWC2MB(m_pchData); } + const wxWX2MBbuf mbc_str() const { return mb_str(*wxConvCurrent); } + + const wxChar* wc_str(wxMBConv& WXUNUSED(conv) = wxConvLibc) const { return m_pchData; } + #if wxMBFILES - const wxCharBuffer fn_str() const { return mb_str(wxConv_file); } -#else + const wxCharBuffer fn_str() const { return mb_str(wxConvFile); } +#else // !wxMBFILES const wxChar* fn_str() const { return m_pchData; } -#endif -#else - const wxChar* mb_str(wxMBConv& WXUNUSED(conv) = wxConv_libc ) const { return m_pchData; } +#endif // wxMBFILES/!wxMBFILES +#else // ANSI +#if wxUSE_MULTIBYTE + const wxChar* mb_str(wxMBConv& WXUNUSED(conv) = wxConvLibc) const + { return m_pchData; } + const wxWX2MBbuf mbc_str() const { return mb_str(*wxConvCurrent); } +#else // !mmultibyte + const wxChar* mb_str() const { return m_pchData; } + const wxWX2MBbuf mbc_str() const { return mb_str(); } +#endif // multibyte/!multibyte +#if wxUSE_WCHAR_T const wxWCharBuffer wc_str(wxMBConv& conv) const { return conv.cMB2WC(m_pchData); } +#endif // wxUSE_WCHAR_T const wxChar* fn_str() const { return m_pchData; } -#endif - // for convenience - const wxWX2MBbuf mbc_str() const { return mb_str(*wxConv_current); } +#endif // Unicode/ANSI // overloaded assignment // from another wxString @@ -468,14 +433,16 @@ public: #if wxUSE_UNICODE // from wxWCharBuffer wxString& operator=(const wxWCharBuffer& psz) { return operator=((const wchar_t *)psz); } -#else +#else // ANSI // from another kind of C string wxString& operator=(const unsigned char* psz); +#if wxUSE_WCHAR_T // from a wide string wxString& operator=(const wchar_t *pwz); +#endif // from wxCharBuffer wxString& operator=(const wxCharBuffer& psz) { return operator=((const char *)psz); } -#endif +#endif // Unicode/ANSI // string concatenation // in place concatenation @@ -547,13 +514,19 @@ public: // string comparison // case-sensitive comparison (returns a value < 0, = 0 or > 0) - int Cmp(const wxChar *psz) const { return wxStrcmp(c_str(), psz); } + int Cmp(const wxChar *psz) const { return wxStrcmp(c_str(), psz); } // same as Cmp() but not case-sensitive - int CmpNoCase(const wxChar *psz) const { return wxStricmp(c_str(), psz); } + int CmpNoCase(const wxChar *psz) const { return wxStricmp(c_str(), psz); } // test for the string equality, either considering case or not // (if compareWithCase then the case matters) bool IsSameAs(const wxChar *psz, bool compareWithCase = TRUE) const { return (compareWithCase ? Cmp(psz) : CmpNoCase(psz)) == 0; } + // comparison with a signle character: returns TRUE if equal + bool IsSameAs(wxChar c, bool compareWithCase = TRUE) const + { + return (Len() == 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 @@ -600,7 +573,7 @@ public: // remove spaces from left or from right (default) side wxString& Trim(bool bFromRight = TRUE); // add nCount copies chPad in the beginning or at the end (default) - wxString& Pad(size_t nCount, wxChar chPad = _T(' '), bool bFromRight = TRUE); + wxString& Pad(size_t nCount, wxChar chPad = wxT(' '), bool bFromRight = TRUE); // truncate string to given length wxString& Truncate(size_t uiLen); @@ -687,6 +660,10 @@ public: #ifdef wxSTD_STRING_COMPATIBILITY // std::string compatibility functions + // standard types + typedef wxChar value_type; + typedef const value_type *const_iterator; + // an 'invalid' value for string index static const size_t npos; @@ -708,7 +685,7 @@ public: // 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 = _T('\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 @@ -720,6 +697,11 @@ public: // 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(); } + // lib.string.modifiers // append a string wxString& append(const wxString& str) @@ -810,32 +792,37 @@ public: // find first/last occurence of any character in the set - // - size_t find_first_of(const wxString& str, size_t nStart = 0) const; - // + // 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; - // - size_t find_last_of (const wxString& str, size_t nStart = npos) const; - // - size_t find_last_of (const wxChar* s, size_t nStart = npos) const; - // same as rfind(char, size_t) - size_t find_last_of (wxChar c, size_t nStart = npos) const; + 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 - // - size_t find_first_not_of(const wxString& str, size_t nStart = 0) const; - // - size_t find_first_not_of(const wxChar* s, size_t nStart = 0) const; - // + // 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; - // - size_t find_last_not_of(const wxChar* s, size_t nStart = npos) const; - // + // 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, @@ -873,6 +860,7 @@ public: // so the original string may be safely deleted. When a string is retrieved // from the array (operator[] or Item() method), a reference is returned. // ---------------------------------------------------------------------------- + class WXDLLEXPORT wxArrayString { public: @@ -954,6 +942,7 @@ private: // --------------------------------------------------------------------------- // wxString comparison functions: operator versions are always case sensitive // --------------------------------------------------------------------------- + // inline bool operator==(const wxString& s1, const wxString& s2) { return (s1.Cmp(s2) == 0); } // @@ -991,17 +980,49 @@ inline bool operator>=(const wxString& s1, const wxChar * s2) { return (s1.Cmp( // inline bool operator>=(const wxChar * s1, const wxString& s2) { return (s2.Cmp(s1) <= 0); } +// 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); } +inline bool operator!=(wxChar c, const wxString& s) { return !s.IsSameAs(c); } +inline bool operator!=(const wxString& s, wxChar c) { return !s.IsSameAs(c); } + +#if wxUSE_UNICODE +inline bool operator==(const wxString& s1, const wxWCharBuffer& s2) + { return (s1.Cmp((const wchar_t *)s2) == 0); } +inline bool operator==(const wxWCharBuffer& s1, const wxString& s2) + { return (s2.Cmp((const wchar_t *)s1) == 0); } +#else +inline bool operator==(const wxString& s1, const wxCharBuffer& s2) + { return (s1.Cmp((const char *)s2) == 0); } +inline bool operator==(const wxCharBuffer& s1, const wxString& s2) + { return (s2.Cmp((const char *)s1) == 0); } +#endif + wxString WXDLLEXPORT operator+(const wxString& string1, const wxString& string2); wxString WXDLLEXPORT operator+(const wxString& string, wxChar ch); wxString WXDLLEXPORT operator+(wxChar ch, const wxString& string); wxString WXDLLEXPORT operator+(const wxString& string, const wxChar *psz); wxString WXDLLEXPORT operator+(const wxChar *psz, const wxString& string); +#if wxUSE_UNICODE +inline wxString WXDLLEXPORT operator+(const wxString& string, const wxWCharBuffer& buf) + { return string + (const wchar_t *)buf; } +inline wxString WXDLLEXPORT operator+(const wxWCharBuffer& buf, const wxString& string) + { return (const wchar_t *)buf + string; } +#else +inline wxString WXDLLEXPORT operator+(const wxString& string, const wxCharBuffer& buf) + { return string + (const char *)buf; } +inline wxString WXDLLEXPORT operator+(const wxCharBuffer& buf, const wxString& string) + { return (const char *)buf + string; } +#endif // --------------------------------------------------------------------------- // Implementation only from here until the end of file // --------------------------------------------------------------------------- -#ifdef wxSTD_STRING_COMPATIBILITY +// don't pollute the library user's name space +#undef ASSERT_VALID_INDEX + +#if defined(wxSTD_STRING_COMPATIBILITY) && wxUSE_STD_IOSTREAM #include "wx/ioswrap.h"