]> git.saurik.com Git - wxWidgets.git/blob - include/wx/string.h
b72a312f45576726cbbeac7e8c1c24b99a3a3a27
[wxWidgets.git] / include / wx / string.h
1 ///////////////////////////////////////////////////////////////////////////////
2 // Name: wx/string.h
3 // Purpose: wxString class
4 // Author: Vadim Zeitlin
5 // Modified by:
6 // Created: 29/01/98
7 // RCS-ID: $Id$
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows licence
10 ///////////////////////////////////////////////////////////////////////////////
11
12 /*
13 Efficient string class [more or less] compatible with MFC CString,
14 wxWidgets version 1 wxString and std::string and some handy functions
15 missing from string.h.
16 */
17
18 #ifndef _WX_WXSTRING_H__
19 #define _WX_WXSTRING_H__
20
21 // ----------------------------------------------------------------------------
22 // headers
23 // ----------------------------------------------------------------------------
24
25 #include "wx/defs.h" // everybody should include this
26
27 #ifndef __WXPALMOS5__
28 #if defined(__WXMAC__) || defined(__VISAGECPP__)
29 #include <ctype.h>
30 #endif
31
32 #if defined(__VISAGECPP__) && __IBMCPP__ >= 400
33 // problem in VACPP V4 with including stdlib.h multiple times
34 // strconv includes it anyway
35 # include <stdio.h>
36 # include <string.h>
37 # include <stdarg.h>
38 # include <limits.h>
39 #else
40 # include <string.h>
41 # include <stdio.h>
42 # include <stdarg.h>
43 # include <limits.h>
44 # include <stdlib.h>
45 #endif
46
47 #ifdef HAVE_STRCASECMP_IN_STRINGS_H
48 #include <strings.h> // for strcasecmp()
49 #endif // HAVE_STRCASECMP_IN_STRINGS_H
50 #endif // ! __WXPALMOS5__
51
52 #include "wx/wxcrtbase.h" // for wxChar, wxStrlen() etc.
53 #include "wx/strvararg.h"
54 #include "wx/buffer.h" // for wxCharBuffer
55 #include "wx/strconv.h" // for wxConvertXXX() macros and wxMBConv classes
56 #include "wx/stringimpl.h"
57 #include "wx/stringops.h"
58 #include "wx/unichar.h"
59
60 class WXDLLIMPEXP_FWD_BASE wxString;
61
62 // unless this symbol is predefined to disable the compatibility functions, do
63 // use them
64 #ifndef WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER
65 #define WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER 1
66 #endif
67
68 namespace wxPrivate
69 {
70 template <typename T> struct wxStringAsBufHelper;
71 }
72
73 // ---------------------------------------------------------------------------
74 // macros
75 // ---------------------------------------------------------------------------
76
77 // casts [unfortunately!] needed to call some broken functions which require
78 // "char *" instead of "const char *"
79 #define WXSTRINGCAST (wxChar *)(const wxChar *)
80 #define wxCSTRINGCAST (wxChar *)(const wxChar *)
81 #define wxMBSTRINGCAST (char *)(const char *)
82 #define wxWCSTRINGCAST (wchar_t *)(const wchar_t *)
83
84 // ----------------------------------------------------------------------------
85 // constants
86 // ----------------------------------------------------------------------------
87
88 #if WXWIN_COMPATIBILITY_2_6
89
90 // deprecated in favour of wxString::npos, don't use in new code
91 //
92 // maximum possible length for a string means "take all string" everywhere
93 #define wxSTRING_MAXLEN wxString::npos
94
95 #endif // WXWIN_COMPATIBILITY_2_6
96
97 // ---------------------------------------------------------------------------
98 // global functions complementing standard C string library replacements for
99 // strlen() and portable strcasecmp()
100 //---------------------------------------------------------------------------
101
102 #if WXWIN_COMPATIBILITY_2_8
103 // Use wxXXX() functions from wxcrt.h instead! These functions are for
104 // backwards compatibility only.
105
106 // checks whether the passed in pointer is NULL and if the string is empty
107 wxDEPRECATED( inline bool IsEmpty(const char *p) );
108 inline bool IsEmpty(const char *p) { return (!p || !*p); }
109
110 // safe version of strlen() (returns 0 if passed NULL pointer)
111 wxDEPRECATED( inline size_t Strlen(const char *psz) );
112 inline size_t Strlen(const char *psz)
113 { return psz ? strlen(psz) : 0; }
114
115 // portable strcasecmp/_stricmp
116 wxDEPRECATED( inline int Stricmp(const char *psz1, const char *psz2) );
117 inline int Stricmp(const char *psz1, const char *psz2)
118 {
119 #if defined(__VISUALC__) && defined(__WXWINCE__)
120 register char c1, c2;
121 do {
122 c1 = tolower(*psz1++);
123 c2 = tolower(*psz2++);
124 } while ( c1 && (c1 == c2) );
125
126 return c1 - c2;
127 #elif defined(__VISUALC__) || ( defined(__MWERKS__) && defined(__INTEL__) )
128 return _stricmp(psz1, psz2);
129 #elif defined(__SC__)
130 return _stricmp(psz1, psz2);
131 #elif defined(__BORLANDC__)
132 return stricmp(psz1, psz2);
133 #elif defined(__WATCOMC__)
134 return stricmp(psz1, psz2);
135 #elif defined(__DJGPP__)
136 return stricmp(psz1, psz2);
137 #elif defined(__EMX__)
138 return stricmp(psz1, psz2);
139 #elif defined(__WXPM__)
140 return stricmp(psz1, psz2);
141 #elif defined(__WXPALMOS__) || \
142 defined(HAVE_STRCASECMP_IN_STRING_H) || \
143 defined(HAVE_STRCASECMP_IN_STRINGS_H) || \
144 defined(__GNUWIN32__)
145 return strcasecmp(psz1, psz2);
146 #elif defined(__MWERKS__) && !defined(__INTEL__)
147 register char c1, c2;
148 do {
149 c1 = tolower(*psz1++);
150 c2 = tolower(*psz2++);
151 } while ( c1 && (c1 == c2) );
152
153 return c1 - c2;
154 #else
155 // almost all compilers/libraries provide this function (unfortunately under
156 // different names), that's why we don't implement our own which will surely
157 // be more efficient than this code (uncomment to use):
158 /*
159 register char c1, c2;
160 do {
161 c1 = tolower(*psz1++);
162 c2 = tolower(*psz2++);
163 } while ( c1 && (c1 == c2) );
164
165 return c1 - c2;
166 */
167
168 #error "Please define string case-insensitive compare for your OS/compiler"
169 #endif // OS/compiler
170 }
171
172 #endif // WXWIN_COMPATIBILITY_2_8
173
174 // ----------------------------------------------------------------------------
175 // wxCStrData
176 // ----------------------------------------------------------------------------
177
178 // Lightweight object returned by wxString::c_str() and implicitly convertible
179 // to either const char* or const wchar_t*.
180 class WXDLLIMPEXP_BASE wxCStrData
181 {
182 private:
183 // Ctors; for internal use by wxString and wxCStrData only
184 wxCStrData(const wxString *str, size_t offset = 0, bool owned = false)
185 : m_str(str), m_offset(offset), m_owned(owned) {}
186
187 public:
188 // Ctor constructs the object from char literal; they are needed to make
189 // operator?: compile and they intentionally take char*, not const char*
190 inline wxCStrData(char *buf);
191 inline wxCStrData(wchar_t *buf);
192 inline wxCStrData(const wxCStrData& data);
193
194 inline ~wxCStrData();
195
196 // methods defined inline below must be declared inline or mingw32 3.4.5
197 // warns about "<symbol> defined locally after being referenced with
198 // dllimport linkage"
199 #if wxUSE_UNICODE_WCHAR
200 inline
201 #endif
202 const wchar_t* AsWChar() const;
203 operator const wchar_t*() const { return AsWChar(); }
204
205 #if !wxUSE_UNICODE || wxUSE_UTF8_LOCALE_ONLY
206 inline
207 #endif
208 const char* AsChar() const;
209 const unsigned char* AsUnsignedChar() const
210 { return (const unsigned char *) AsChar(); }
211 operator const char*() const { return AsChar(); }
212 operator const unsigned char*() const { return AsUnsignedChar(); }
213
214 operator const void*() const { return AsChar(); }
215
216 inline const wxCharBuffer AsCharBuf() const;
217 inline const wxWCharBuffer AsWCharBuf() const;
218
219 inline wxString AsString() const;
220
221 // returns the value as C string in internal representation (equivalent
222 // to AsString().wx_str(), but more efficient)
223 const wxStringCharType *AsInternal() const;
224
225 // allow expressions like "c_str()[0]":
226 inline wxUniChar operator[](size_t n) const;
227 wxUniChar operator[](int n) const { return operator[](size_t(n)); }
228 wxUniChar operator[](long n) const { return operator[](size_t(n)); }
229 #ifndef wxSIZE_T_IS_UINT
230 wxUniChar operator[](unsigned int n) const { return operator[](size_t(n)); }
231 #endif // size_t != unsigned int
232
233 // these operators are needed to emulate the pointer semantics of c_str():
234 // expressions like "wxChar *p = str.c_str() + 1;" should continue to work
235 // (we need both versions to resolve ambiguities):
236 wxCStrData operator+(int n) const
237 { return wxCStrData(m_str, m_offset + n, m_owned); }
238 wxCStrData operator+(long n) const
239 { return wxCStrData(m_str, m_offset + n, m_owned); }
240 wxCStrData operator+(size_t n) const
241 { return wxCStrData(m_str, m_offset + n, m_owned); }
242
243 // and these for "str.c_str() + (p2 - p1)" (it also works for any integer
244 // expression but it must be ptrdiff_t and not e.g. int to work in this
245 // example):
246 wxCStrData operator-(ptrdiff_t n) const
247 {
248 wxASSERT_MSG( n <= (ptrdiff_t)m_offset,
249 _T("attempt to construct address before the beginning of the string") );
250 return wxCStrData(m_str, m_offset - n, m_owned);
251 }
252
253 // this operator is needed to make expressions like "*c_str()" or
254 // "*(c_str() + 2)" work
255 inline wxUniChar operator*() const;
256
257 private:
258 const wxString *m_str;
259 size_t m_offset;
260 bool m_owned;
261
262 friend class WXDLLIMPEXP_FWD_BASE wxString;
263 };
264
265 // ----------------------------------------------------------------------------
266 // wxStringPrintfMixin
267 // ---------------------------------------------------------------------------
268
269 // NB: VC6 has a bug that causes linker errors if you have template methods
270 // in a class using __declspec(dllimport). The solution is to split such
271 // class into two classes, one that contains the template methods and does
272 // *not* use WXDLLIMPEXP_BASE and another class that contains the rest
273 // (with DLL linkage).
274 //
275 // We only do this for VC6 here, because the code is less efficient
276 // (Printf() has to use dynamic_cast<>) and because OpenWatcom compiler
277 // cannot compile this code.
278
279 #if defined(__VISUALC__) && __VISUALC__ < 1300
280 #define wxNEEDS_WXSTRING_PRINTF_MIXIN
281 #endif
282
283 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
284 // this class contains implementation of wxString's vararg methods, it's
285 // exported from wxBase DLL
286 class WXDLLIMPEXP_BASE wxStringPrintfMixinBase
287 {
288 protected:
289 wxStringPrintfMixinBase() {}
290
291 #if !wxUSE_UTF8_LOCALE_ONLY
292 int DoPrintfWchar(const wxChar *format, ...);
293 static wxString DoFormatWchar(const wxChar *format, ...);
294 #endif
295 #if wxUSE_UNICODE_UTF8
296 int DoPrintfUtf8(const char *format, ...);
297 static wxString DoFormatUtf8(const char *format, ...);
298 #endif
299 };
300
301 // this class contains template wrappers for wxString's vararg methods, it's
302 // intentionally *not* exported from the DLL in order to fix the VC6 bug
303 // described above
304 class wxStringPrintfMixin : public wxStringPrintfMixinBase
305 {
306 private:
307 // to further complicate things, we can't return wxString from
308 // wxStringPrintfMixin::Format() because wxString is not yet declared at
309 // this point; the solution is to use this fake type trait template - this
310 // way the compiler won't know the return type until Format() is used
311 // (this doesn't compile with Watcom, but VC6 compiles it just fine):
312 template<typename T> struct StringReturnType
313 {
314 typedef wxString type;
315 };
316
317 public:
318 // these are duplicated wxString methods, they're also declared below
319 // if !wxNEEDS_WXSTRING_PRINTF_MIXIN:
320
321 // static wxString Format(const wString& format, ...) ATTRIBUTE_PRINTF_1;
322 WX_DEFINE_VARARG_FUNC_SANS_N0(static typename StringReturnType<T1>::type,
323 Format, 1, (const wxFormatString&),
324 DoFormatWchar, DoFormatUtf8)
325 // We have to implement the version without template arguments manually
326 // because of the StringReturnType<> hack, although WX_DEFINE_VARARG_FUNC
327 // normally does it itself. It has to be a template so that we can use
328 // the hack, even though there's no real template parameter. We can't move
329 // it to wxStrig, because it would shadow these versions of Format() then.
330 template<typename T>
331 inline static typename StringReturnType<T>::type
332 Format(const T& fmt)
333 {
334 // NB: this doesn't compile if T is not (some form of) a string;
335 // this makes Format's prototype equivalent to
336 // Format(const wxFormatString& fmt)
337 return DoFormatWchar(wxFormatString(fmt));
338 }
339
340 // int Printf(const wxString& format, ...);
341 WX_DEFINE_VARARG_FUNC(int, Printf, 1, (const wxFormatString&),
342 DoPrintfWchar, DoPrintfUtf8)
343 // int sprintf(const wxString& format, ...) ATTRIBUTE_PRINTF_2;
344 WX_DEFINE_VARARG_FUNC(int, sprintf, 1, (const wxFormatString&),
345 DoPrintfWchar, DoPrintfUtf8)
346
347 protected:
348 wxStringPrintfMixin() : wxStringPrintfMixinBase() {}
349 };
350 #endif // wxNEEDS_WXSTRING_PRINTF_MIXIN
351
352
353 // ----------------------------------------------------------------------------
354 // wxString: string class trying to be compatible with std::string, MFC
355 // CString and wxWindows 1.x wxString all at once
356 // ---------------------------------------------------------------------------
357
358 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
359 // "non dll-interface class 'wxStringPrintfMixin' used as base interface
360 // for dll-interface class 'wxString'" -- this is OK in our case
361 #pragma warning (disable:4275)
362 #endif
363
364 #if wxUSE_UNICODE_UTF8
365 // see the comment near wxString::iterator for why we need this
366 class WXDLLIMPEXP_BASE wxStringIteratorNode
367 {
368 public:
369 wxStringIteratorNode()
370 : m_str(NULL), m_citer(NULL), m_iter(NULL), m_prev(NULL), m_next(NULL) {}
371 wxStringIteratorNode(const wxString *str,
372 wxStringImpl::const_iterator *citer)
373 { DoSet(str, citer, NULL); }
374 wxStringIteratorNode(const wxString *str, wxStringImpl::iterator *iter)
375 { DoSet(str, NULL, iter); }
376 ~wxStringIteratorNode()
377 { clear(); }
378
379 inline void set(const wxString *str, wxStringImpl::const_iterator *citer)
380 { clear(); DoSet(str, citer, NULL); }
381 inline void set(const wxString *str, wxStringImpl::iterator *iter)
382 { clear(); DoSet(str, NULL, iter); }
383
384 const wxString *m_str;
385 wxStringImpl::const_iterator *m_citer;
386 wxStringImpl::iterator *m_iter;
387 wxStringIteratorNode *m_prev, *m_next;
388
389 private:
390 inline void clear();
391 inline void DoSet(const wxString *str,
392 wxStringImpl::const_iterator *citer,
393 wxStringImpl::iterator *iter);
394
395 // the node belongs to a particular iterator instance, it's not copied
396 // when a copy of the iterator is made
397 DECLARE_NO_COPY_CLASS(wxStringIteratorNode)
398 };
399 #endif // wxUSE_UNICODE_UTF8
400
401 class WXDLLIMPEXP_BASE wxString
402 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
403 : public wxStringPrintfMixin
404 #endif
405 {
406 // NB: special care was taken in arranging the member functions in such order
407 // that all inline functions can be effectively inlined, verify that all
408 // performance critical functions are still inlined if you change order!
409 public:
410 // an 'invalid' value for string index, moved to this place due to a CW bug
411 static const size_t npos;
412
413 private:
414 // if we hadn't made these operators private, it would be possible to
415 // compile "wxString s; s = 17;" without any warnings as 17 is implicitly
416 // converted to char in C and we do have operator=(char)
417 //
418 // NB: we don't need other versions (short/long and unsigned) as attempt
419 // to assign another numeric type to wxString will now result in
420 // ambiguity between operator=(char) and operator=(int)
421 wxString& operator=(int);
422
423 // these methods are not implemented - there is _no_ conversion from int to
424 // string, you're doing something wrong if the compiler wants to call it!
425 //
426 // try `s << i' or `s.Printf("%d", i)' instead
427 wxString(int);
428
429
430 // buffer for holding temporary substring when using any of the methods
431 // that take (char*,size_t) or (wchar_t*,size_t) arguments:
432 template<typename T>
433 struct SubstrBufFromType
434 {
435 T data;
436 size_t len;
437
438 SubstrBufFromType(const T& data_, size_t len_)
439 : data(data_), len(len_)
440 {
441 wxASSERT_MSG( len != npos, "must have real length" );
442 }
443 };
444
445 #if wxUSE_UNICODE_UTF8
446 // even char* -> char* needs conversion, from locale charset to UTF-8
447 typedef SubstrBufFromType<wxCharBuffer> SubstrBufFromWC;
448 typedef SubstrBufFromType<wxCharBuffer> SubstrBufFromMB;
449 #elif wxUSE_UNICODE_WCHAR
450 typedef SubstrBufFromType<const wchar_t*> SubstrBufFromWC;
451 typedef SubstrBufFromType<wxWCharBuffer> SubstrBufFromMB;
452 #else
453 typedef SubstrBufFromType<const char*> SubstrBufFromMB;
454 typedef SubstrBufFromType<wxCharBuffer> SubstrBufFromWC;
455 #endif
456
457
458 // Functions implementing primitive operations on string data; wxString
459 // methods and iterators are implemented in terms of it. The differences
460 // between UTF-8 and wchar_t* representations of the string are mostly
461 // contained here.
462
463 #if wxUSE_UNICODE_UTF8
464 static SubstrBufFromMB ConvertStr(const char *psz, size_t nLength,
465 const wxMBConv& conv);
466 static SubstrBufFromWC ConvertStr(const wchar_t *pwz, size_t nLength,
467 const wxMBConv& conv);
468 #elif wxUSE_UNICODE_WCHAR
469 static SubstrBufFromMB ConvertStr(const char *psz, size_t nLength,
470 const wxMBConv& conv);
471 #else
472 static SubstrBufFromWC ConvertStr(const wchar_t *pwz, size_t nLength,
473 const wxMBConv& conv);
474 #endif
475
476 #if !wxUSE_UNICODE_UTF8 // wxUSE_UNICODE_WCHAR or !wxUSE_UNICODE
477 // returns C string encoded as the implementation expects:
478 #if wxUSE_UNICODE
479 static const wchar_t* ImplStr(const wchar_t* str)
480 { return str ? str : wxT(""); }
481 static const SubstrBufFromWC ImplStr(const wchar_t* str, size_t n)
482 { return SubstrBufFromWC(str, (str && n == npos) ? wxWcslen(str) : n); }
483 static wxWCharBuffer ImplStr(const char* str,
484 const wxMBConv& conv = wxConvLibc)
485 { return ConvertStr(str, npos, conv).data; }
486 static SubstrBufFromMB ImplStr(const char* str, size_t n,
487 const wxMBConv& conv = wxConvLibc)
488 { return ConvertStr(str, n, conv); }
489 #else
490 static const char* ImplStr(const char* str,
491 const wxMBConv& WXUNUSED(conv) = wxConvLibc)
492 { return str ? str : ""; }
493 static const SubstrBufFromMB ImplStr(const char* str, size_t n,
494 const wxMBConv& WXUNUSED(conv) = wxConvLibc)
495 { return SubstrBufFromMB(str, (str && n == npos) ? wxStrlen(str) : n); }
496 static wxCharBuffer ImplStr(const wchar_t* str)
497 { return ConvertStr(str, npos, wxConvLibc).data; }
498 static SubstrBufFromWC ImplStr(const wchar_t* str, size_t n)
499 { return ConvertStr(str, n, wxConvLibc); }
500 #endif
501
502 // translates position index in wxString to/from index in underlying
503 // wxStringImpl:
504 static size_t PosToImpl(size_t pos) { return pos; }
505 static void PosLenToImpl(size_t pos, size_t len,
506 size_t *implPos, size_t *implLen)
507 { *implPos = pos; *implLen = len; }
508 static size_t LenToImpl(size_t len) { return len; }
509 static size_t PosFromImpl(size_t pos) { return pos; }
510
511 // we don't want to define this as an empty inline function as it could
512 // result in noticeable (and quite unnecessary in non-UTF-8 build) slowdown
513 // in debug build where the inline functions are not effectively inlined
514 #define wxSTRING_INVALIDATE_INDEX_CACHE()
515
516 #else // wxUSE_UNICODE_UTF8
517
518 static wxCharBuffer ImplStr(const char* str,
519 const wxMBConv& conv = wxConvLibc)
520 { return ConvertStr(str, npos, conv).data; }
521 static SubstrBufFromMB ImplStr(const char* str, size_t n,
522 const wxMBConv& conv = wxConvLibc)
523 { return ConvertStr(str, n, conv); }
524
525 static wxCharBuffer ImplStr(const wchar_t* str)
526 { return ConvertStr(str, npos, wxMBConvUTF8()).data; }
527 static SubstrBufFromWC ImplStr(const wchar_t* str, size_t n)
528 { return ConvertStr(str, n, wxMBConvUTF8()); }
529
530 // this is an extremely simple cache used by PosToImpl()
531 struct PosToImplCache
532 {
533 const wxString *str;
534 size_t pos,
535 impl;
536 };
537
538 static PosToImplCache ms_cache;
539
540 size_t PosToImpl(size_t pos) const
541 {
542 if ( pos == 0 || pos == npos )
543 return pos;
544
545 PosToImplCache& cache = ms_cache;
546 if ( this == cache.str )
547 {
548 if ( pos == cache.pos )
549 return cache.impl;
550
551 // TODO: is it worth complicating this function even further by going
552 // backwards from the last position? it might be if we're just
553 // before it...
554 if ( cache.pos > pos )
555 {
556 cache.pos =
557 cache.impl = 0;
558 }
559 }
560 else // data for this string not cached
561 {
562 cache.str = this;
563 cache.pos =
564 cache.impl = 0;
565 }
566
567 wxStringImpl::const_iterator i(m_impl.begin() + cache.impl);
568 for ( size_t n = cache.pos; n < pos; n++ )
569 wxStringOperations::IncIter(i);
570
571 cache.pos = pos;
572 return cache.impl = i - m_impl.begin();
573 }
574
575 void InvalidatePosToImplCache()
576 {
577 PosToImplCache& cache = ms_cache;
578 if ( cache.str == this )
579 {
580 cache.pos =
581 cache.impl = 0;
582 }
583 }
584
585 #define wxSTRING_INVALIDATE_INDEX_CACHE() InvalidatePosToImplCache()
586
587 void PosLenToImpl(size_t pos, size_t len, size_t *implPos, size_t *implLen) const;
588
589 size_t LenToImpl(size_t len) const
590 {
591 size_t pos, len2;
592 PosLenToImpl(0, len, &pos, &len2);
593 return len2;
594 }
595
596 size_t PosFromImpl(size_t pos) const
597 {
598 if ( pos == 0 || pos == npos )
599 return pos;
600 else
601 return const_iterator(this, m_impl.begin() + pos) - begin();
602 }
603 #endif // !wxUSE_UNICODE_UTF8/wxUSE_UNICODE_UTF8
604
605 public:
606 // standard types
607 typedef wxUniChar value_type;
608 typedef wxUniChar char_type;
609 typedef wxUniCharRef reference;
610 typedef wxChar* pointer;
611 typedef const wxChar* const_pointer;
612
613 typedef size_t size_type;
614 typedef wxUniChar const_reference;
615
616 #if wxUSE_STL
617 #if wxUSE_UNICODE_UTF8
618 // random access is not O(1), as required by Random Access Iterator
619 #define WX_STR_ITERATOR_TAG std::bidirectional_iterator_tag
620 #else
621 #define WX_STR_ITERATOR_TAG std::random_access_iterator_tag
622 #endif
623 #else
624 #define WX_STR_ITERATOR_TAG void /* dummy type */
625 #endif
626
627 #define WX_STR_ITERATOR_IMPL(iterator_name, pointer_type, reference_type) \
628 private: \
629 typedef wxStringImpl::iterator_name underlying_iterator; \
630 public: \
631 typedef WX_STR_ITERATOR_TAG iterator_category; \
632 typedef wxUniChar value_type; \
633 typedef int difference_type; \
634 typedef reference_type reference; \
635 typedef pointer_type pointer; \
636 \
637 reference operator[](size_t n) const { return *(*this + n); } \
638 \
639 iterator_name& operator++() \
640 { wxStringOperations::IncIter(m_cur); return *this; } \
641 iterator_name& operator--() \
642 { wxStringOperations::DecIter(m_cur); return *this; } \
643 iterator_name operator++(int) \
644 { \
645 iterator_name tmp = *this; \
646 wxStringOperations::IncIter(m_cur); \
647 return tmp; \
648 } \
649 iterator_name operator--(int) \
650 { \
651 iterator_name tmp = *this; \
652 wxStringOperations::DecIter(m_cur); \
653 return tmp; \
654 } \
655 \
656 iterator_name& operator+=(ptrdiff_t n) \
657 { \
658 m_cur = wxStringOperations::AddToIter(m_cur, n); \
659 return *this; \
660 } \
661 iterator_name& operator-=(ptrdiff_t n) \
662 { \
663 m_cur = wxStringOperations::AddToIter(m_cur, -n); \
664 return *this; \
665 } \
666 \
667 difference_type operator-(const iterator_name& i) const \
668 { return wxStringOperations::DiffIters(m_cur, i.m_cur); } \
669 \
670 bool operator==(const iterator_name& i) const \
671 { return m_cur == i.m_cur; } \
672 bool operator!=(const iterator_name& i) const \
673 { return m_cur != i.m_cur; } \
674 \
675 bool operator<(const iterator_name& i) const \
676 { return m_cur < i.m_cur; } \
677 bool operator>(const iterator_name& i) const \
678 { return m_cur > i.m_cur; } \
679 bool operator<=(const iterator_name& i) const \
680 { return m_cur <= i.m_cur; } \
681 bool operator>=(const iterator_name& i) const \
682 { return m_cur >= i.m_cur; } \
683 \
684 private: \
685 /* for internal wxString use only: */ \
686 underlying_iterator impl() const { return m_cur; } \
687 \
688 friend class wxString; \
689 friend class wxCStrData; \
690 \
691 private: \
692 underlying_iterator m_cur
693
694 class WXDLLIMPEXP_FWD_BASE const_iterator;
695
696 #if wxUSE_UNICODE_UTF8
697 // NB: In UTF-8 build, (non-const) iterator needs to keep reference
698 // to the underlying wxStringImpl, because UTF-8 is variable-length
699 // encoding and changing the value pointer to by an iterator (using
700 // its operator*) requires calling wxStringImpl::replace() if the old
701 // and new values differ in their encoding's length.
702 //
703 // Furthermore, the replace() call may invalid all iterators for the
704 // string, so we have to keep track of outstanding iterators and update
705 // them if replace() happens.
706 //
707 // This is implemented by maintaining linked list of iterators for every
708 // string and traversing it in wxUniCharRef::operator=(). Head of the
709 // list is stored in wxString. (FIXME-UTF8)
710
711 class WXDLLIMPEXP_BASE iterator
712 {
713 WX_STR_ITERATOR_IMPL(iterator, wxChar*, wxUniCharRef);
714
715 public:
716 iterator() {}
717 iterator(const iterator& i)
718 : m_cur(i.m_cur), m_node(i.str(), &m_cur) {}
719 iterator& operator=(const iterator& i)
720 {
721 if (&i != this)
722 {
723 m_cur = i.m_cur;
724 m_node.set(i.str(), &m_cur);
725 }
726 return *this;
727 }
728
729 reference operator*()
730 { return wxUniCharRef::CreateForString(m_node, m_cur); }
731
732 iterator operator+(ptrdiff_t n) const
733 { return iterator(str(), wxStringOperations::AddToIter(m_cur, n)); }
734 iterator operator-(ptrdiff_t n) const
735 { return iterator(str(), wxStringOperations::AddToIter(m_cur, -n)); }
736
737 private:
738 iterator(wxString *str, underlying_iterator ptr)
739 : m_cur(ptr), m_node(str, &m_cur) {}
740
741 wxString* str() const { return wx_const_cast(wxString*, m_node.m_str); }
742
743 wxStringIteratorNode m_node;
744
745 friend class const_iterator;
746 };
747
748 class WXDLLIMPEXP_BASE const_iterator
749 {
750 // NB: reference_type is intentionally value, not reference, the character
751 // may be encoded differently in wxString data:
752 WX_STR_ITERATOR_IMPL(const_iterator, const wxChar*, wxUniChar);
753
754 public:
755 const_iterator() {}
756 const_iterator(const const_iterator& i)
757 : m_cur(i.m_cur), m_node(i.str(), &m_cur) {}
758 const_iterator(const iterator& i)
759 : m_cur(i.m_cur), m_node(i.str(), &m_cur) {}
760
761 const_iterator& operator=(const const_iterator& i)
762 {
763 if (&i != this)
764 {
765 m_cur = i.m_cur;
766 m_node.set(i.str(), &m_cur);
767 }
768 return *this;
769 }
770 const_iterator& operator=(const iterator& i)
771 { m_cur = i.m_cur; m_node.set(i.str(), &m_cur); return *this; }
772
773 reference operator*() const
774 { return wxStringOperations::DecodeChar(m_cur); }
775
776 const_iterator operator+(ptrdiff_t n) const
777 { return const_iterator(str(), wxStringOperations::AddToIter(m_cur, n)); }
778 const_iterator operator-(ptrdiff_t n) const
779 { return const_iterator(str(), wxStringOperations::AddToIter(m_cur, -n)); }
780
781 private:
782 // for internal wxString use only:
783 const_iterator(const wxString *str, underlying_iterator ptr)
784 : m_cur(ptr), m_node(str, &m_cur) {}
785
786 const wxString* str() const { return m_node.m_str; }
787
788 wxStringIteratorNode m_node;
789 };
790
791 size_t IterToImplPos(wxString::iterator i) const
792 { return wxStringImpl::const_iterator(i.impl()) - m_impl.begin(); }
793
794 iterator GetNthIter(size_t n)
795 { return iterator(this, m_impl.begin() + PosToImpl(n)); }
796 const_iterator GetNthIter(size_t n) const
797 { return const_iterator(this, m_impl.begin() + PosToImpl(n)); }
798 #else // !wxUSE_UNICODE_UTF8
799
800 class WXDLLIMPEXP_BASE iterator
801 {
802 WX_STR_ITERATOR_IMPL(iterator, wxChar*, wxUniCharRef);
803
804 public:
805 iterator() {}
806 iterator(const iterator& i) : m_cur(i.m_cur) {}
807
808 reference operator*()
809 { return wxUniCharRef::CreateForString(m_cur); }
810
811 iterator operator+(ptrdiff_t n) const
812 { return iterator(wxStringOperations::AddToIter(m_cur, n)); }
813 iterator operator-(ptrdiff_t n) const
814 { return iterator(wxStringOperations::AddToIter(m_cur, -n)); }
815
816 private:
817 // for internal wxString use only:
818 iterator(underlying_iterator ptr) : m_cur(ptr) {}
819 iterator(wxString *WXUNUSED(str), underlying_iterator ptr) : m_cur(ptr) {}
820
821 friend class const_iterator;
822 };
823
824 class WXDLLIMPEXP_BASE const_iterator
825 {
826 // NB: reference_type is intentionally value, not reference, the character
827 // may be encoded differently in wxString data:
828 WX_STR_ITERATOR_IMPL(const_iterator, const wxChar*, wxUniChar);
829
830 public:
831 const_iterator() {}
832 const_iterator(const const_iterator& i) : m_cur(i.m_cur) {}
833 const_iterator(const iterator& i) : m_cur(i.m_cur) {}
834
835 reference operator*() const
836 { return wxStringOperations::DecodeChar(m_cur); }
837
838 const_iterator operator+(ptrdiff_t n) const
839 { return const_iterator(wxStringOperations::AddToIter(m_cur, n)); }
840 const_iterator operator-(ptrdiff_t n) const
841 { return const_iterator(wxStringOperations::AddToIter(m_cur, -n)); }
842
843 private:
844 // for internal wxString use only:
845 const_iterator(underlying_iterator ptr) : m_cur(ptr) {}
846 const_iterator(const wxString *WXUNUSED(str), underlying_iterator ptr)
847 : m_cur(ptr) {}
848 };
849
850 iterator GetNthIter(size_t n) { return begin() + n; }
851 const_iterator GetNthIter(size_t n) const { return begin() + n; }
852 #endif // wxUSE_UNICODE_UTF8/!wxUSE_UNICODE_UTF8
853
854 #undef WX_STR_ITERATOR_TAG
855 #undef WX_STR_ITERATOR_IMPL
856
857 friend class iterator;
858 friend class const_iterator;
859
860 template <typename T>
861 class reverse_iterator_impl
862 {
863 public:
864 typedef T iterator_type;
865
866 typedef typename T::iterator_category iterator_category;
867 typedef typename T::value_type value_type;
868 typedef typename T::difference_type difference_type;
869 typedef typename T::reference reference;
870 typedef typename T::pointer *pointer;
871
872 reverse_iterator_impl() {}
873 reverse_iterator_impl(iterator_type i) : m_cur(i) {}
874 reverse_iterator_impl(const reverse_iterator_impl& ri)
875 : m_cur(ri.m_cur) {}
876
877 iterator_type base() const { return m_cur; }
878
879 reference operator*() const { return *(m_cur-1); }
880 reference operator[](size_t n) const { return *(*this + n); }
881
882 reverse_iterator_impl& operator++()
883 { --m_cur; return *this; }
884 reverse_iterator_impl operator++(int)
885 { reverse_iterator_impl tmp = *this; --m_cur; return tmp; }
886 reverse_iterator_impl& operator--()
887 { ++m_cur; return *this; }
888 reverse_iterator_impl operator--(int)
889 { reverse_iterator_impl tmp = *this; ++m_cur; return tmp; }
890
891 // NB: explicit <T> in the functions below is to keep BCC 5.5 happy
892 reverse_iterator_impl operator+(ptrdiff_t n) const
893 { return reverse_iterator_impl<T>(m_cur - n); }
894 reverse_iterator_impl operator-(ptrdiff_t n) const
895 { return reverse_iterator_impl<T>(m_cur + n); }
896 reverse_iterator_impl operator+=(ptrdiff_t n)
897 { m_cur -= n; return *this; }
898 reverse_iterator_impl operator-=(ptrdiff_t n)
899 { m_cur += n; return *this; }
900
901 unsigned operator-(const reverse_iterator_impl& i) const
902 { return i.m_cur - m_cur; }
903
904 bool operator==(const reverse_iterator_impl& ri) const
905 { return m_cur == ri.m_cur; }
906 bool operator!=(const reverse_iterator_impl& ri) const
907 { return !(*this == ri); }
908
909 bool operator<(const reverse_iterator_impl& i) const
910 { return m_cur > i.m_cur; }
911 bool operator>(const reverse_iterator_impl& i) const
912 { return m_cur < i.m_cur; }
913 bool operator<=(const reverse_iterator_impl& i) const
914 { return m_cur >= i.m_cur; }
915 bool operator>=(const reverse_iterator_impl& i) const
916 { return m_cur <= i.m_cur; }
917
918 private:
919 iterator_type m_cur;
920 };
921
922 typedef reverse_iterator_impl<iterator> reverse_iterator;
923 typedef reverse_iterator_impl<const_iterator> const_reverse_iterator;
924
925 private:
926 // used to transform an expression built using c_str() (and hence of type
927 // wxCStrData) to an iterator into the string
928 static const_iterator CreateConstIterator(const wxCStrData& data)
929 {
930 return const_iterator(data.m_str,
931 (data.m_str->begin() + data.m_offset).impl());
932 }
933
934 // in UTF-8 STL build, creation from std::string requires conversion under
935 // non-UTF8 locales, so we can't have and use wxString(wxStringImpl) ctor;
936 // instead we define dummy type that lets us have wxString ctor for creation
937 // from wxStringImpl that couldn't be used by user code (in all other builds,
938 // "standard" ctors can be used):
939 #if wxUSE_UNICODE_UTF8 && wxUSE_STL_BASED_WXSTRING
940 struct CtorFromStringImplTag {};
941
942 wxString(CtorFromStringImplTag* WXUNUSED(dummy), const wxStringImpl& src)
943 : m_impl(src) {}
944
945 static wxString FromImpl(const wxStringImpl& src)
946 { return wxString((CtorFromStringImplTag*)NULL, src); }
947 #else
948 #if !wxUSE_STL_BASED_WXSTRING
949 wxString(const wxStringImpl& src) : m_impl(src) { }
950 // else: already defined as wxString(wxStdString) below
951 #endif
952 static wxString FromImpl(const wxStringImpl& src) { return wxString(src); }
953 #endif
954
955 public:
956 // constructors and destructor
957 // ctor for an empty string
958 wxString() {}
959
960 // copy ctor
961 wxString(const wxString& stringSrc) : m_impl(stringSrc.m_impl) { }
962
963 // string containing nRepeat copies of ch
964 wxString(wxUniChar ch, size_t nRepeat = 1 )
965 { assign(nRepeat, ch); }
966 wxString(size_t nRepeat, wxUniChar ch)
967 { assign(nRepeat, ch); }
968 wxString(wxUniCharRef ch, size_t nRepeat = 1)
969 { assign(nRepeat, ch); }
970 wxString(size_t nRepeat, wxUniCharRef ch)
971 { assign(nRepeat, ch); }
972 wxString(char ch, size_t nRepeat = 1)
973 { assign(nRepeat, ch); }
974 wxString(size_t nRepeat, char ch)
975 { assign(nRepeat, ch); }
976 wxString(wchar_t ch, size_t nRepeat = 1)
977 { assign(nRepeat, ch); }
978 wxString(size_t nRepeat, wchar_t ch)
979 { assign(nRepeat, ch); }
980
981 // ctors from char* strings:
982 wxString(const char *psz)
983 : m_impl(ImplStr(psz)) {}
984 wxString(const char *psz, const wxMBConv& conv)
985 : m_impl(ImplStr(psz, conv)) {}
986 wxString(const char *psz, size_t nLength)
987 { assign(psz, nLength); }
988 wxString(const char *psz, const wxMBConv& conv, size_t nLength)
989 {
990 SubstrBufFromMB str(ImplStr(psz, nLength, conv));
991 m_impl.assign(str.data, str.len);
992 }
993
994 // and unsigned char*:
995 wxString(const unsigned char *psz)
996 : m_impl(ImplStr((const char*)psz)) {}
997 wxString(const unsigned char *psz, const wxMBConv& conv)
998 : m_impl(ImplStr((const char*)psz, conv)) {}
999 wxString(const unsigned char *psz, size_t nLength)
1000 { assign((const char*)psz, nLength); }
1001 wxString(const unsigned char *psz, const wxMBConv& conv, size_t nLength)
1002 {
1003 SubstrBufFromMB str(ImplStr((const char*)psz, nLength, conv));
1004 m_impl.assign(str.data, str.len);
1005 }
1006
1007 // ctors from wchar_t* strings:
1008 wxString(const wchar_t *pwz)
1009 : m_impl(ImplStr(pwz)) {}
1010 wxString(const wchar_t *pwz, const wxMBConv& WXUNUSED(conv))
1011 : m_impl(ImplStr(pwz)) {}
1012 wxString(const wchar_t *pwz, size_t nLength)
1013 { assign(pwz, nLength); }
1014 wxString(const wchar_t *pwz, const wxMBConv& WXUNUSED(conv), size_t nLength)
1015 { assign(pwz, nLength); }
1016
1017 wxString(const wxCharBuffer& buf)
1018 { assign(buf.data()); } // FIXME-UTF8: fix for embedded NUL and buffer length
1019 wxString(const wxWCharBuffer& buf)
1020 { assign(buf.data()); } // FIXME-UTF8: fix for embedded NUL and buffer length
1021
1022 // NB: this version uses m_impl.c_str() to force making a copy of the
1023 // string, so that "wxString(str.c_str())" idiom for passing strings
1024 // between threads works
1025 wxString(const wxCStrData& cstr)
1026 : m_impl(cstr.AsString().m_impl.c_str()) { }
1027
1028 // as we provide both ctors with this signature for both char and unsigned
1029 // char string, we need to provide one for wxCStrData to resolve ambiguity
1030 wxString(const wxCStrData& cstr, size_t nLength)
1031 : m_impl(cstr.AsString().Mid(0, nLength).m_impl) {}
1032
1033 // and because wxString is convertible to wxCStrData and const wxChar *
1034 // we also need to provide this one
1035 wxString(const wxString& str, size_t nLength)
1036 { assign(str, nLength); }
1037
1038 // even if we're not built with wxUSE_STL == 1 it is very convenient to allow
1039 // implicit conversions from std::string to wxString and vice verse as this
1040 // allows to use the same strings in non-GUI and GUI code, however we don't
1041 // want to unconditionally add this ctor as it would make wx lib dependent on
1042 // libstdc++ on some Linux versions which is bad, so instead we ask the
1043 // client code to define this wxUSE_STD_STRING symbol if they need it
1044 #if wxUSE_STD_STRING
1045 #if wxUSE_UNICODE_WCHAR
1046 wxString(const wxStdWideString& str) : m_impl(str) {}
1047 #else // UTF-8 or ANSI
1048 wxString(const wxStdWideString& str)
1049 { assign(str.c_str(), str.length()); }
1050 #endif
1051
1052 #if !wxUSE_UNICODE // ANSI build
1053 // FIXME-UTF8: do this in UTF8 build #if wxUSE_UTF8_LOCALE_ONLY, too
1054 wxString(const std::string& str) : m_impl(str) {}
1055 #else // Unicode
1056 wxString(const std::string& str)
1057 { assign(str.c_str(), str.length()); }
1058 #endif
1059 #endif // wxUSE_STD_STRING
1060
1061 // Unlike ctor from std::string, we provide conversion to std::string only
1062 // if wxUSE_STL and not merely wxUSE_STD_STRING (which is on by default),
1063 // because it conflicts with operator const char/wchar_t*:
1064 #if wxUSE_STL
1065 #if wxUSE_UNICODE_WCHAR && wxUSE_STL_BASED_WXSTRING
1066 // wxStringImpl is std::string in the encoding we want
1067 operator const wxStdWideString&() const { return m_impl; }
1068 #else
1069 // wxStringImpl is either not std::string or needs conversion
1070 operator wxStdWideString() const
1071 // FIXME-UTF8: broken for embedded NULs
1072 { return wxStdWideString(wc_str()); }
1073 #endif
1074
1075 #if (!wxUSE_UNICODE || wxUSE_UTF8_LOCALE_ONLY) && wxUSE_STL_BASED_WXSTRING
1076 // wxStringImpl is std::string in the encoding we want
1077 operator const std::string&() const { return m_impl; }
1078 #else
1079 // wxStringImpl is either not std::string or needs conversion
1080 operator std::string() const
1081 // FIXME-UTF8: broken for embedded NULs
1082 { return std::string(mb_str()); }
1083 #endif
1084 #endif // wxUSE_STL
1085
1086 wxString Clone() const
1087 {
1088 // make a deep copy of the string, i.e. the returned string will have
1089 // ref count = 1 with refcounted implementation
1090 return wxString::FromImpl(wxStringImpl(m_impl.c_str(), m_impl.length()));
1091 }
1092
1093 // first valid index position
1094 const_iterator begin() const { return const_iterator(this, m_impl.begin()); }
1095 iterator begin() { return iterator(this, m_impl.begin()); }
1096 // position one after the last valid one
1097 const_iterator end() const { return const_iterator(this, m_impl.end()); }
1098 iterator end() { return iterator(this, m_impl.end()); }
1099
1100 // first element of the reversed string
1101 const_reverse_iterator rbegin() const
1102 { return const_reverse_iterator(end()); }
1103 reverse_iterator rbegin()
1104 { return reverse_iterator(end()); }
1105 // one beyond the end of the reversed string
1106 const_reverse_iterator rend() const
1107 { return const_reverse_iterator(begin()); }
1108 reverse_iterator rend()
1109 { return reverse_iterator(begin()); }
1110
1111 // std::string methods:
1112 #if wxUSE_UNICODE_UTF8
1113 size_t length() const { return end() - begin(); } // FIXME-UTF8: optimize!
1114 #else
1115 size_t length() const { return m_impl.length(); }
1116 #endif
1117
1118 size_type size() const { return length(); }
1119 size_type max_size() const { return npos; }
1120
1121 bool empty() const { return m_impl.empty(); }
1122
1123 size_type capacity() const { return m_impl.capacity(); } // FIXME-UTF8
1124 void reserve(size_t sz) { m_impl.reserve(sz); } // FIXME-UTF8
1125
1126 void resize(size_t nSize, wxUniChar ch = wxT('\0'))
1127 {
1128 const size_t len = length();
1129 if ( nSize == len)
1130 return;
1131
1132 #if wxUSE_UNICODE_UTF8
1133 if ( nSize < len )
1134 {
1135 wxSTRING_INVALIDATE_INDEX_CACHE();
1136
1137 // we can't use wxStringImpl::resize() for truncating the string as it
1138 // counts in bytes, not characters
1139 erase(nSize);
1140 return;
1141 }
1142
1143 // we also can't use (presumably more efficient) resize() if we have to
1144 // append characters taking more than one byte
1145 if ( !ch.IsAscii() )
1146 append(nSize - len, ch);
1147 else
1148 #endif // wxUSE_UNICODE_UTF8
1149 m_impl.resize(nSize, (wxStringCharType)ch);
1150 }
1151
1152 wxString substr(size_t nStart = 0, size_t nLen = npos) const
1153 {
1154 size_t pos, len;
1155 PosLenToImpl(nStart, nLen, &pos, &len);
1156 return FromImpl(m_impl.substr(pos, len));
1157 }
1158
1159 // generic attributes & operations
1160 // as standard strlen()
1161 size_t Len() const { return length(); }
1162 // string contains any characters?
1163 bool IsEmpty() const { return empty(); }
1164 // empty string is "false", so !str will return true
1165 bool operator!() const { return empty(); }
1166 // truncate the string to given length
1167 wxString& Truncate(size_t uiLen);
1168 // empty string contents
1169 void Empty()
1170 {
1171 Truncate(0);
1172
1173 wxASSERT_MSG( empty(), _T("string not empty after call to Empty()?") );
1174 }
1175 // empty the string and free memory
1176 void Clear() { clear(); }
1177
1178 // contents test
1179 // Is an ascii value
1180 bool IsAscii() const;
1181 // Is a number
1182 bool IsNumber() const;
1183 // Is a word
1184 bool IsWord() const;
1185
1186 // data access (all indexes are 0 based)
1187 // read access
1188 wxUniChar at(size_t n) const
1189 { return wxStringOperations::DecodeChar(m_impl.begin() + PosToImpl(n)); }
1190 wxUniChar GetChar(size_t n) const
1191 { return at(n); }
1192 // read/write access
1193 wxUniCharRef at(size_t n)
1194 { return *GetNthIter(n); }
1195 wxUniCharRef GetWritableChar(size_t n)
1196 { return at(n); }
1197 // write access
1198 void SetChar(size_t n, wxUniChar ch)
1199 {
1200 wxUniCharRef ref(at(n));
1201
1202 #if wxUSE_UNICODE_UTF8
1203 // if the new character takes the same number of bytes as the old one,
1204 // we can avoid invalidating the index cache and it's an important case
1205 // as it is exercised by a simple for loop using indices
1206 if ( wxStringOperations::GetUtf8CharLength(ref)
1207 != wxStringOperations::GetUtf8CharLength(ch) )
1208 {
1209 wxSTRING_INVALIDATE_INDEX_CACHE();
1210 }
1211 #endif // wxUSE_UNICODE_UTF8
1212
1213 ref = ch;
1214 }
1215
1216 // get last character
1217 wxUniChar Last() const
1218 {
1219 wxASSERT_MSG( !empty(), _T("wxString: index out of bounds") );
1220 return *rbegin();
1221 }
1222
1223 // get writable last character
1224 wxUniCharRef Last()
1225 {
1226 wxASSERT_MSG( !empty(), _T("wxString: index out of bounds") );
1227 return *rbegin();
1228 }
1229
1230 /*
1231 Note that we we must define all of the overloads below to avoid
1232 ambiguity when using str[0].
1233 */
1234 wxUniChar operator[](int n) const
1235 { return at(n); }
1236 wxUniChar operator[](long n) const
1237 { return at(n); }
1238 wxUniChar operator[](size_t n) const
1239 { return at(n); }
1240 #ifndef wxSIZE_T_IS_UINT
1241 wxUniChar operator[](unsigned int n) const
1242 { return at(n); }
1243 #endif // size_t != unsigned int
1244
1245 // operator versions of GetWriteableChar()
1246 wxUniCharRef operator[](int n)
1247 { return at(n); }
1248 wxUniCharRef operator[](long n)
1249 { return at(n); }
1250 wxUniCharRef operator[](size_t n)
1251 { return at(n); }
1252 #ifndef wxSIZE_T_IS_UINT
1253 wxUniCharRef operator[](unsigned int n)
1254 { return at(n); }
1255 #endif // size_t != unsigned int
1256
1257 // explicit conversion to C string (use this with printf()!)
1258 wxCStrData c_str() const { return wxCStrData(this); }
1259 wxCStrData data() const { return c_str(); }
1260
1261 // implicit conversion to C string
1262 operator wxCStrData() const { return c_str(); }
1263
1264 // the first two operators conflict with operators for conversion to
1265 // std::string and they must be disabled in STL build; the next one only
1266 // makes sense if conversions to char* are also defined and not defining it
1267 // in STL build also helps us to get more clear error messages for the code
1268 // which relies on implicit conversion to char* in STL build
1269 #if !wxUSE_STL
1270 operator const char*() const { return c_str(); }
1271 operator const wchar_t*() const { return c_str(); }
1272
1273 // implicit conversion to untyped pointer for compatibility with previous
1274 // wxWidgets versions: this is the same as conversion to const char * so it
1275 // may fail!
1276 operator const void*() const { return c_str(); }
1277 #endif // wxUSE_STL
1278
1279 // identical to c_str(), for MFC compatibility
1280 const wxCStrData GetData() const { return c_str(); }
1281
1282 // explicit conversion to C string in internal representation (char*,
1283 // wchar_t*, UTF-8-encoded char*, depending on the build):
1284 const wxStringCharType *wx_str() const { return m_impl.c_str(); }
1285
1286 // conversion to *non-const* multibyte or widestring buffer; modifying
1287 // returned buffer won't affect the string, these methods are only useful
1288 // for passing values to const-incorrect functions
1289 wxWritableCharBuffer char_str(const wxMBConv& conv = wxConvLibc) const
1290 { return mb_str(conv); }
1291 wxWritableWCharBuffer wchar_str() const { return wc_str(); }
1292
1293 // conversion to the buffer of the given type T (= char or wchar_t) and
1294 // also optionally return the buffer length
1295 //
1296 // this is mostly/only useful for the template functions
1297 //
1298 // FIXME-VC6: the second argument only exists for VC6 which doesn't support
1299 // explicit template function selection, do not use it unless
1300 // you must support VC6!
1301 template <typename T>
1302 wxCharTypeBuffer<T> tchar_str(size_t *len = NULL,
1303 T * WXUNUSED(dummy) = NULL) const
1304 {
1305 #if wxUSE_UNICODE
1306 // we need a helper dispatcher depending on type
1307 return wxPrivate::wxStringAsBufHelper<T>::Get(*this, len);
1308 #else // ANSI
1309 // T can only be char in ANSI build
1310 if ( len )
1311 *len = length();
1312
1313 return wxCharTypeBuffer<T>::CreateNonOwned(wx_str());
1314 #endif // Unicode build kind
1315 }
1316
1317 // conversion to/from plain (i.e. 7 bit) ASCII: this is useful for
1318 // converting numbers or strings which are certain not to contain special
1319 // chars (typically system functions, X atoms, environment variables etc.)
1320 //
1321 // the behaviour of these functions with the strings containing anything
1322 // else than 7 bit ASCII characters is undefined, use at your own risk.
1323 #if wxUSE_UNICODE
1324 static wxString FromAscii(const char *ascii, size_t len);
1325 static wxString FromAscii(const char *ascii);
1326 static wxString FromAscii(char ascii);
1327 const wxCharBuffer ToAscii() const;
1328 #else // ANSI
1329 static wxString FromAscii(const char *ascii) { return wxString( ascii ); }
1330 static wxString FromAscii(const char *ascii, size_t len)
1331 { return wxString( ascii, len ); }
1332 static wxString FromAscii(char ascii) { return wxString( ascii ); }
1333 const char *ToAscii() const { return c_str(); }
1334 #endif // Unicode/!Unicode
1335
1336 // also provide unsigned char overloads as signed/unsigned doesn't matter
1337 // for 7 bit ASCII characters
1338 static wxString FromAscii(const unsigned char *ascii)
1339 { return FromAscii((const char *)ascii); }
1340 static wxString FromAscii(const unsigned char *ascii, size_t len)
1341 { return FromAscii((const char *)ascii, len); }
1342
1343 // conversion to/from UTF-8:
1344 #if wxUSE_UNICODE_UTF8
1345 static wxString FromUTF8Unchecked(const char *utf8)
1346 {
1347 if ( !utf8 )
1348 return wxEmptyString;
1349
1350 wxASSERT( wxStringOperations::IsValidUtf8String(utf8) );
1351 return FromImpl(wxStringImpl(utf8));
1352 }
1353 static wxString FromUTF8Unchecked(const char *utf8, size_t len)
1354 {
1355 if ( !utf8 )
1356 return wxEmptyString;
1357 if ( len == npos )
1358 return FromUTF8Unchecked(utf8);
1359
1360 wxASSERT( wxStringOperations::IsValidUtf8String(utf8, len) );
1361 return FromImpl(wxStringImpl(utf8, len));
1362 }
1363
1364 static wxString FromUTF8(const char *utf8)
1365 {
1366 if ( !utf8 || !wxStringOperations::IsValidUtf8String(utf8) )
1367 return "";
1368
1369 return FromImpl(wxStringImpl(utf8));
1370 }
1371 static wxString FromUTF8(const char *utf8, size_t len)
1372 {
1373 if ( len == npos )
1374 return FromUTF8(utf8);
1375
1376 if ( !utf8 || !wxStringOperations::IsValidUtf8String(utf8, len) )
1377 return "";
1378
1379 return FromImpl(wxStringImpl(utf8, len));
1380 }
1381
1382 const char* utf8_str() const { return wx_str(); }
1383 const char* ToUTF8() const { return wx_str(); }
1384
1385 // this function exists in UTF-8 build only and returns the length of the
1386 // internal UTF-8 representation
1387 size_t utf8_length() const { return m_impl.length(); }
1388 #elif wxUSE_UNICODE_WCHAR
1389 static wxString FromUTF8(const char *utf8, size_t len = npos)
1390 { return wxString(utf8, wxMBConvUTF8(), len); }
1391 static wxString FromUTF8Unchecked(const char *utf8, size_t len = npos)
1392 {
1393 const wxString s(utf8, wxMBConvUTF8(), len);
1394 wxASSERT_MSG( !utf8 || !*utf8 || !s.empty(),
1395 "string must be valid UTF-8" );
1396 return s;
1397 }
1398 const wxCharBuffer utf8_str() const { return mb_str(wxMBConvUTF8()); }
1399 const wxCharBuffer ToUTF8() const { return utf8_str(); }
1400 #else // ANSI
1401 static wxString FromUTF8(const char *utf8)
1402 { return wxString(wxMBConvUTF8().cMB2WC(utf8)); }
1403 static wxString FromUTF8(const char *utf8, size_t len)
1404 {
1405 size_t wlen;
1406 wxWCharBuffer buf(wxMBConvUTF8().cMB2WC(utf8, len == npos ? wxNO_LEN : len, &wlen));
1407 return wxString(buf.data(), wlen);
1408 }
1409 static wxString FromUTF8Unchecked(const char *utf8, size_t len = npos)
1410 {
1411 size_t wlen;
1412 wxWCharBuffer buf(wxMBConvUTF8().cMB2WC(utf8,
1413 len == npos ? wxNO_LEN : len,
1414 &wlen));
1415 wxASSERT_MSG( !utf8 || !*utf8 || wlen,
1416 "string must be valid UTF-8" );
1417
1418 return wxString(buf.data(), wlen);
1419 }
1420 const wxCharBuffer utf8_str() const
1421 { return wxMBConvUTF8().cWC2MB(wc_str()); }
1422 const wxCharBuffer ToUTF8() const { return utf8_str(); }
1423 #endif
1424
1425 // functions for storing binary data in wxString:
1426 #if wxUSE_UNICODE
1427 static wxString From8BitData(const char *data, size_t len)
1428 { return wxString(data, wxConvISO8859_1, len); }
1429 // version for NUL-terminated data:
1430 static wxString From8BitData(const char *data)
1431 { return wxString(data, wxConvISO8859_1); }
1432 const wxCharBuffer To8BitData() const { return mb_str(wxConvISO8859_1); }
1433 #else // ANSI
1434 static wxString From8BitData(const char *data, size_t len)
1435 { return wxString(data, len); }
1436 // version for NUL-terminated data:
1437 static wxString From8BitData(const char *data)
1438 { return wxString(data); }
1439 const char *To8BitData() const { return c_str(); }
1440 #endif // Unicode/ANSI
1441
1442 // conversions with (possible) format conversions: have to return a
1443 // buffer with temporary data
1444 //
1445 // the functions defined (in either Unicode or ANSI) mode are mb_str() to
1446 // return an ANSI (multibyte) string, wc_str() to return a wide string and
1447 // fn_str() to return a string which should be used with the OS APIs
1448 // accepting the file names. The return value is always the same, but the
1449 // type differs because a function may either return pointer to the buffer
1450 // directly or have to use intermediate buffer for translation.
1451 #if wxUSE_UNICODE
1452
1453 #if wxUSE_UTF8_LOCALE_ONLY
1454 const char* mb_str() const { return wx_str(); }
1455 const wxCharBuffer mb_str(const wxMBConv& conv) const;
1456 #else
1457 const wxCharBuffer mb_str(const wxMBConv& conv = wxConvLibc) const;
1458 #endif
1459
1460 const wxWX2MBbuf mbc_str() const { return mb_str(*wxConvCurrent); }
1461
1462 #if wxUSE_UNICODE_WCHAR
1463 const wchar_t* wc_str() const { return wx_str(); }
1464 #elif wxUSE_UNICODE_UTF8
1465 const wxWCharBuffer wc_str() const;
1466 #endif
1467 // for compatibility with !wxUSE_UNICODE version
1468 const wxWX2WCbuf wc_str(const wxMBConv& WXUNUSED(conv)) const
1469 { return wc_str(); }
1470
1471 #if wxMBFILES
1472 const wxCharBuffer fn_str() const { return mb_str(wxConvFile); }
1473 #else // !wxMBFILES
1474 const wxWX2WCbuf fn_str() const { return wc_str(); }
1475 #endif // wxMBFILES/!wxMBFILES
1476
1477 #else // ANSI
1478 const wxChar* mb_str() const { return wx_str(); }
1479
1480 // for compatibility with wxUSE_UNICODE version
1481 const char* mb_str(const wxMBConv& WXUNUSED(conv)) const { return wx_str(); }
1482
1483 const wxWX2MBbuf mbc_str() const { return mb_str(); }
1484
1485 #if wxUSE_WCHAR_T
1486 const wxWCharBuffer wc_str(const wxMBConv& conv = wxConvLibc) const;
1487 #endif // wxUSE_WCHAR_T
1488 const wxCharBuffer fn_str() const { return wxConvFile.cWC2WX( wc_str( wxConvLibc ) ); }
1489 #endif // Unicode/ANSI
1490
1491 #if wxUSE_UNICODE_UTF8
1492 const wxWCharBuffer t_str() const { return wc_str(); }
1493 #elif wxUSE_UNICODE_WCHAR
1494 const wchar_t* t_str() const { return wx_str(); }
1495 #else
1496 const char* t_str() const { return wx_str(); }
1497 #endif
1498
1499
1500 // overloaded assignment
1501 // from another wxString
1502 wxString& operator=(const wxString& stringSrc)
1503 {
1504 if ( this != &stringSrc )
1505 {
1506 wxSTRING_INVALIDATE_INDEX_CACHE();
1507
1508 m_impl = stringSrc.m_impl;
1509 }
1510
1511 return *this;
1512 }
1513
1514 wxString& operator=(const wxCStrData& cstr)
1515 { return *this = cstr.AsString(); }
1516 // from a character
1517 wxString& operator=(wxUniChar ch)
1518 {
1519 wxSTRING_INVALIDATE_INDEX_CACHE();
1520
1521 #if wxUSE_UNICODE_UTF8
1522 if ( !ch.IsAscii() )
1523 m_impl = wxStringOperations::EncodeChar(ch);
1524 else
1525 #endif // wxUSE_UNICODE_UTF8
1526 m_impl = (wxStringCharType)ch;
1527 return *this;
1528 }
1529
1530 wxString& operator=(wxUniCharRef ch)
1531 { return operator=((wxUniChar)ch); }
1532 wxString& operator=(char ch)
1533 { return operator=(wxUniChar(ch)); }
1534 wxString& operator=(unsigned char ch)
1535 { return operator=(wxUniChar(ch)); }
1536 wxString& operator=(wchar_t ch)
1537 { return operator=(wxUniChar(ch)); }
1538 // from a C string - STL probably will crash on NULL,
1539 // so we need to compensate in that case
1540 #if wxUSE_STL_BASED_WXSTRING
1541 wxString& operator=(const char *psz)
1542 {
1543 wxSTRING_INVALIDATE_INDEX_CACHE();
1544
1545 if ( psz )
1546 m_impl = ImplStr(psz);
1547 else
1548 clear();
1549
1550 return *this;
1551 }
1552
1553 wxString& operator=(const wchar_t *pwz)
1554 {
1555 wxSTRING_INVALIDATE_INDEX_CACHE();
1556
1557 if ( pwz )
1558 m_impl = ImplStr(pwz);
1559 else
1560 clear();
1561
1562 return *this;
1563 }
1564 #else // !wxUSE_STL_BASED_WXSTRING
1565 wxString& operator=(const char *psz)
1566 {
1567 wxSTRING_INVALIDATE_INDEX_CACHE();
1568
1569 m_impl = ImplStr(psz);
1570
1571 return *this;
1572 }
1573
1574 wxString& operator=(const wchar_t *pwz)
1575 {
1576 wxSTRING_INVALIDATE_INDEX_CACHE();
1577
1578 m_impl = ImplStr(pwz);
1579
1580 return *this;
1581 }
1582 #endif // wxUSE_STL_BASED_WXSTRING/!wxUSE_STL_BASED_WXSTRING
1583
1584 wxString& operator=(const unsigned char *psz)
1585 { return operator=((const char*)psz); }
1586
1587 // from wxWCharBuffer
1588 wxString& operator=(const wxWCharBuffer& s)
1589 { return operator=(s.data()); } // FIXME-UTF8: fix for embedded NULs
1590 // from wxCharBuffer
1591 wxString& operator=(const wxCharBuffer& s)
1592 { return operator=(s.data()); } // FIXME-UTF8: fix for embedded NULs
1593
1594 // string concatenation
1595 // in place concatenation
1596 /*
1597 Concatenate and return the result. Note that the left to right
1598 associativity of << allows to write things like "str << str1 << str2
1599 << ..." (unlike with +=)
1600 */
1601 // string += string
1602 wxString& operator<<(const wxString& s)
1603 {
1604 #if WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
1605 wxASSERT_MSG( s.IsValid(),
1606 _T("did you forget to call UngetWriteBuf()?") );
1607 #endif
1608
1609 append(s);
1610 return *this;
1611 }
1612 // string += C string
1613 wxString& operator<<(const char *psz)
1614 { append(psz); return *this; }
1615 wxString& operator<<(const wchar_t *pwz)
1616 { append(pwz); return *this; }
1617 wxString& operator<<(const wxCStrData& psz)
1618 { append(psz.AsString()); return *this; }
1619 // string += char
1620 wxString& operator<<(wxUniChar ch) { append(1, ch); return *this; }
1621 wxString& operator<<(wxUniCharRef ch) { append(1, ch); return *this; }
1622 wxString& operator<<(char ch) { append(1, ch); return *this; }
1623 wxString& operator<<(unsigned char ch) { append(1, ch); return *this; }
1624 wxString& operator<<(wchar_t ch) { append(1, ch); return *this; }
1625
1626 // string += buffer (i.e. from wxGetString)
1627 wxString& operator<<(const wxWCharBuffer& s)
1628 { return operator<<((const wchar_t *)s); }
1629 wxString& operator<<(const wxCharBuffer& s)
1630 { return operator<<((const char *)s); }
1631
1632 // string += C string
1633 wxString& Append(const wxString& s)
1634 {
1635 // test for empty() to share the string if possible
1636 if ( empty() )
1637 *this = s;
1638 else
1639 append(s);
1640 return *this;
1641 }
1642 wxString& Append(const char* psz)
1643 { append(psz); return *this; }
1644 wxString& Append(const wchar_t* pwz)
1645 { append(pwz); return *this; }
1646 wxString& Append(const wxCStrData& psz)
1647 { append(psz); return *this; }
1648 wxString& Append(const wxCharBuffer& psz)
1649 { append(psz); return *this; }
1650 wxString& Append(const wxWCharBuffer& psz)
1651 { append(psz); return *this; }
1652 wxString& Append(const char* psz, size_t nLen)
1653 { append(psz, nLen); return *this; }
1654 wxString& Append(const wchar_t* pwz, size_t nLen)
1655 { append(pwz, nLen); return *this; }
1656 wxString& Append(const wxCStrData& psz, size_t nLen)
1657 { append(psz, nLen); return *this; }
1658 wxString& Append(const wxCharBuffer& psz, size_t nLen)
1659 { append(psz, nLen); return *this; }
1660 wxString& Append(const wxWCharBuffer& psz, size_t nLen)
1661 { append(psz, nLen); return *this; }
1662 // append count copies of given character
1663 wxString& Append(wxUniChar ch, size_t count = 1u)
1664 { append(count, ch); return *this; }
1665 wxString& Append(wxUniCharRef ch, size_t count = 1u)
1666 { append(count, ch); return *this; }
1667 wxString& Append(char ch, size_t count = 1u)
1668 { append(count, ch); return *this; }
1669 wxString& Append(unsigned char ch, size_t count = 1u)
1670 { append(count, ch); return *this; }
1671 wxString& Append(wchar_t ch, size_t count = 1u)
1672 { append(count, ch); return *this; }
1673
1674 // prepend a string, return the string itself
1675 wxString& Prepend(const wxString& str)
1676 { *this = str + *this; return *this; }
1677
1678 // non-destructive concatenation
1679 // two strings
1680 friend wxString WXDLLIMPEXP_BASE operator+(const wxString& string1,
1681 const wxString& string2);
1682 // string with a single char
1683 friend wxString WXDLLIMPEXP_BASE operator+(const wxString& string, wxUniChar ch);
1684 // char with a string
1685 friend wxString WXDLLIMPEXP_BASE operator+(wxUniChar ch, const wxString& string);
1686 // string with C string
1687 friend wxString WXDLLIMPEXP_BASE operator+(const wxString& string,
1688 const char *psz);
1689 friend wxString WXDLLIMPEXP_BASE operator+(const wxString& string,
1690 const wchar_t *pwz);
1691 // C string with string
1692 friend wxString WXDLLIMPEXP_BASE operator+(const char *psz,
1693 const wxString& string);
1694 friend wxString WXDLLIMPEXP_BASE operator+(const wchar_t *pwz,
1695 const wxString& string);
1696
1697 // stream-like functions
1698 // insert an int into string
1699 wxString& operator<<(int i)
1700 { return (*this) << Format(_T("%d"), i); }
1701 // insert an unsigned int into string
1702 wxString& operator<<(unsigned int ui)
1703 { return (*this) << Format(_T("%u"), ui); }
1704 // insert a long into string
1705 wxString& operator<<(long l)
1706 { return (*this) << Format(_T("%ld"), l); }
1707 // insert an unsigned long into string
1708 wxString& operator<<(unsigned long ul)
1709 { return (*this) << Format(_T("%lu"), ul); }
1710 #if defined wxLongLong_t && !defined wxLongLongIsLong
1711 // insert a long long if they exist and aren't longs
1712 wxString& operator<<(wxLongLong_t ll)
1713 {
1714 const wxChar *fmt = _T("%") wxLongLongFmtSpec _T("d");
1715 return (*this) << Format(fmt, ll);
1716 }
1717 // insert an unsigned long long
1718 wxString& operator<<(wxULongLong_t ull)
1719 {
1720 const wxChar *fmt = _T("%") wxLongLongFmtSpec _T("u");
1721 return (*this) << Format(fmt , ull);
1722 }
1723 #endif // wxLongLong_t && !wxLongLongIsLong
1724 // insert a float into string
1725 wxString& operator<<(float f)
1726 { return (*this) << Format(_T("%f"), f); }
1727 // insert a double into string
1728 wxString& operator<<(double d)
1729 { return (*this) << Format(_T("%g"), d); }
1730
1731 // string comparison
1732 // case-sensitive comparison (returns a value < 0, = 0 or > 0)
1733 int Cmp(const char *psz) const
1734 { return compare(psz); }
1735 int Cmp(const wchar_t *pwz) const
1736 { return compare(pwz); }
1737 int Cmp(const wxString& s) const
1738 { return compare(s); }
1739 int Cmp(const wxCStrData& s) const
1740 { return compare(s); }
1741 int Cmp(const wxCharBuffer& s) const
1742 { return compare(s); }
1743 int Cmp(const wxWCharBuffer& s) const
1744 { return compare(s); }
1745 // same as Cmp() but not case-sensitive
1746 int CmpNoCase(const wxString& s) const;
1747
1748 // test for the string equality, either considering case or not
1749 // (if compareWithCase then the case matters)
1750 bool IsSameAs(const wxString& str, bool compareWithCase = true) const
1751 {
1752 #if !wxUSE_UNICODE_UTF8
1753 // in UTF-8 build, length() is O(n) and doing this would be _slower_
1754 if ( length() != str.length() )
1755 return false;
1756 #endif
1757 return (compareWithCase ? Cmp(str) : CmpNoCase(str)) == 0;
1758 }
1759 bool IsSameAs(const char *str, bool compareWithCase = true) const
1760 { return (compareWithCase ? Cmp(str) : CmpNoCase(str)) == 0; }
1761 bool IsSameAs(const wchar_t *str, bool compareWithCase = true) const
1762 { return (compareWithCase ? Cmp(str) : CmpNoCase(str)) == 0; }
1763
1764 bool IsSameAs(const wxCStrData& str, bool compareWithCase = true) const
1765 { return IsSameAs(str.AsString(), compareWithCase); }
1766 bool IsSameAs(const wxCharBuffer& str, bool compareWithCase = true) const
1767 { return IsSameAs(str.data(), compareWithCase); }
1768 bool IsSameAs(const wxWCharBuffer& str, bool compareWithCase = true) const
1769 { return IsSameAs(str.data(), compareWithCase); }
1770 // comparison with a single character: returns true if equal
1771 bool IsSameAs(wxUniChar c, bool compareWithCase = true) const;
1772 // FIXME-UTF8: remove these overloads
1773 bool IsSameAs(wxUniCharRef c, bool compareWithCase = true) const
1774 { return IsSameAs(wxUniChar(c), compareWithCase); }
1775 bool IsSameAs(char c, bool compareWithCase = true) const
1776 { return IsSameAs(wxUniChar(c), compareWithCase); }
1777 bool IsSameAs(unsigned char c, bool compareWithCase = true) const
1778 { return IsSameAs(wxUniChar(c), compareWithCase); }
1779 bool IsSameAs(wchar_t c, bool compareWithCase = true) const
1780 { return IsSameAs(wxUniChar(c), compareWithCase); }
1781 bool IsSameAs(int c, bool compareWithCase = true) const
1782 { return IsSameAs(wxUniChar(c), compareWithCase); }
1783
1784 // simple sub-string extraction
1785 // return substring starting at nFirst of length nCount (or till the end
1786 // if nCount = default value)
1787 wxString Mid(size_t nFirst, size_t nCount = npos) const;
1788
1789 // operator version of Mid()
1790 wxString operator()(size_t start, size_t len) const
1791 { return Mid(start, len); }
1792
1793 // check if the string starts with the given prefix and return the rest
1794 // of the string in the provided pointer if it is not NULL; otherwise
1795 // return false
1796 bool StartsWith(const wxString& prefix, wxString *rest = NULL) const;
1797 // check if the string ends with the given suffix and return the
1798 // beginning of the string before the suffix in the provided pointer if
1799 // it is not NULL; otherwise return false
1800 bool EndsWith(const wxString& suffix, wxString *rest = NULL) const;
1801
1802 // get first nCount characters
1803 wxString Left(size_t nCount) const;
1804 // get last nCount characters
1805 wxString Right(size_t nCount) const;
1806 // get all characters before the first occurance of ch
1807 // (returns the whole string if ch not found)
1808 wxString BeforeFirst(wxUniChar ch) const;
1809 // get all characters before the last occurence of ch
1810 // (returns empty string if ch not found)
1811 wxString BeforeLast(wxUniChar ch) const;
1812 // get all characters after the first occurence of ch
1813 // (returns empty string if ch not found)
1814 wxString AfterFirst(wxUniChar ch) const;
1815 // get all characters after the last occurence of ch
1816 // (returns the whole string if ch not found)
1817 wxString AfterLast(wxUniChar ch) const;
1818
1819 // for compatibility only, use more explicitly named functions above
1820 wxString Before(wxUniChar ch) const { return BeforeLast(ch); }
1821 wxString After(wxUniChar ch) const { return AfterFirst(ch); }
1822
1823 // case conversion
1824 // convert to upper case in place, return the string itself
1825 wxString& MakeUpper();
1826 // convert to upper case, return the copy of the string
1827 wxString Upper() const { return wxString(*this).MakeUpper(); }
1828 // convert to lower case in place, return the string itself
1829 wxString& MakeLower();
1830 // convert to lower case, return the copy of the string
1831 wxString Lower() const { return wxString(*this).MakeLower(); }
1832 // convert the first character to the upper case and the rest to the
1833 // lower one, return the modified string itself
1834 wxString& MakeCapitalized();
1835 // convert the first character to the upper case and the rest to the
1836 // lower one, return the copy of the string
1837 wxString Capitalize() const { return wxString(*this).MakeCapitalized(); }
1838
1839 // trimming/padding whitespace (either side) and truncating
1840 // remove spaces from left or from right (default) side
1841 wxString& Trim(bool bFromRight = true);
1842 // add nCount copies chPad in the beginning or at the end (default)
1843 wxString& Pad(size_t nCount, wxUniChar chPad = wxT(' '), bool bFromRight = true);
1844
1845 // searching and replacing
1846 // searching (return starting index, or -1 if not found)
1847 int Find(wxUniChar ch, bool bFromEnd = false) const; // like strchr/strrchr
1848 int Find(wxUniCharRef ch, bool bFromEnd = false) const
1849 { return Find(wxUniChar(ch), bFromEnd); }
1850 int Find(char ch, bool bFromEnd = false) const
1851 { return Find(wxUniChar(ch), bFromEnd); }
1852 int Find(unsigned char ch, bool bFromEnd = false) const
1853 { return Find(wxUniChar(ch), bFromEnd); }
1854 int Find(wchar_t ch, bool bFromEnd = false) const
1855 { return Find(wxUniChar(ch), bFromEnd); }
1856 // searching (return starting index, or -1 if not found)
1857 int Find(const wxString& sub) const // like strstr
1858 {
1859 size_type idx = find(sub);
1860 return (idx == npos) ? wxNOT_FOUND : (int)idx;
1861 }
1862 int Find(const char *sub) const // like strstr
1863 {
1864 size_type idx = find(sub);
1865 return (idx == npos) ? wxNOT_FOUND : (int)idx;
1866 }
1867 int Find(const wchar_t *sub) const // like strstr
1868 {
1869 size_type idx = find(sub);
1870 return (idx == npos) ? wxNOT_FOUND : (int)idx;
1871 }
1872
1873 int Find(const wxCStrData& sub) const
1874 { return Find(sub.AsString()); }
1875 int Find(const wxCharBuffer& sub) const
1876 { return Find(sub.data()); }
1877 int Find(const wxWCharBuffer& sub) const
1878 { return Find(sub.data()); }
1879
1880 // replace first (or all of bReplaceAll) occurences of substring with
1881 // another string, returns the number of replacements made
1882 size_t Replace(const wxString& strOld,
1883 const wxString& strNew,
1884 bool bReplaceAll = true);
1885
1886 // check if the string contents matches a mask containing '*' and '?'
1887 bool Matches(const wxString& mask) const;
1888
1889 // conversion to numbers: all functions return true only if the whole
1890 // string is a number and put the value of this number into the pointer
1891 // provided, the base is the numeric base in which the conversion should be
1892 // done and must be comprised between 2 and 36 or be 0 in which case the
1893 // standard C rules apply (leading '0' => octal, "0x" => hex)
1894 // convert to a signed integer
1895 bool ToLong(long *val, int base = 10) const;
1896 // convert to an unsigned integer
1897 bool ToULong(unsigned long *val, int base = 10) const;
1898 // convert to wxLongLong
1899 #if defined(wxLongLong_t)
1900 bool ToLongLong(wxLongLong_t *val, int base = 10) const;
1901 // convert to wxULongLong
1902 bool ToULongLong(wxULongLong_t *val, int base = 10) const;
1903 #endif // wxLongLong_t
1904 // convert to a double
1905 bool ToDouble(double *val) const;
1906
1907
1908 #ifndef wxNEEDS_WXSTRING_PRINTF_MIXIN
1909 // formatted input/output
1910 // as sprintf(), returns the number of characters written or < 0 on error
1911 // (take 'this' into account in attribute parameter count)
1912 // int Printf(const wxString& format, ...);
1913 WX_DEFINE_VARARG_FUNC(int, Printf, 1, (const wxFormatString&),
1914 DoPrintfWchar, DoPrintfUtf8)
1915 #ifdef __WATCOMC__
1916 // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
1917 WX_VARARG_WATCOM_WORKAROUND(int, Printf, 1, (const wxString&),
1918 (wxFormatString(f1)));
1919 WX_VARARG_WATCOM_WORKAROUND(int, Printf, 1, (const wxCStrData&),
1920 (wxFormatString(f1)));
1921 WX_VARARG_WATCOM_WORKAROUND(int, Printf, 1, (const char*),
1922 (wxFormatString(f1)));
1923 WX_VARARG_WATCOM_WORKAROUND(int, Printf, 1, (const wchar_t*),
1924 (wxFormatString(f1)));
1925 #endif
1926 #endif // !wxNEEDS_WXSTRING_PRINTF_MIXIN
1927 // as vprintf(), returns the number of characters written or < 0 on error
1928 int PrintfV(const wxString& format, va_list argptr);
1929
1930 #ifndef wxNEEDS_WXSTRING_PRINTF_MIXIN
1931 // returns the string containing the result of Printf() to it
1932 // static wxString Format(const wxString& format, ...) ATTRIBUTE_PRINTF_1;
1933 WX_DEFINE_VARARG_FUNC(static wxString, Format, 1, (const wxFormatString&),
1934 DoFormatWchar, DoFormatUtf8)
1935 #ifdef __WATCOMC__
1936 // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
1937 WX_VARARG_WATCOM_WORKAROUND(static wxString, Format, 1, (const wxString&),
1938 (wxFormatString(f1)));
1939 WX_VARARG_WATCOM_WORKAROUND(static wxString, Format, 1, (const wxCStrData&),
1940 (wxFormatString(f1)));
1941 WX_VARARG_WATCOM_WORKAROUND(static wxString, Format, 1, (const char*),
1942 (wxFormatString(f1)));
1943 WX_VARARG_WATCOM_WORKAROUND(static wxString, Format, 1, (const wchar_t*),
1944 (wxFormatString(f1)));
1945 #endif
1946 #endif
1947 // the same as above, but takes a va_list
1948 static wxString FormatV(const wxString& format, va_list argptr);
1949
1950 // raw access to string memory
1951 // ensure that string has space for at least nLen characters
1952 // only works if the data of this string is not shared
1953 bool Alloc(size_t nLen) { reserve(nLen); return capacity() >= nLen; }
1954 // minimize the string's memory
1955 // only works if the data of this string is not shared
1956 bool Shrink();
1957 #if WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
1958 // These are deprecated, use wxStringBuffer or wxStringBufferLength instead
1959 //
1960 // get writable buffer of at least nLen bytes. Unget() *must* be called
1961 // a.s.a.p. to put string back in a reasonable state!
1962 wxDEPRECATED( wxStringCharType *GetWriteBuf(size_t nLen) );
1963 // call this immediately after GetWriteBuf() has been used
1964 wxDEPRECATED( void UngetWriteBuf() );
1965 wxDEPRECATED( void UngetWriteBuf(size_t nLen) );
1966 #endif // WXWIN_COMPATIBILITY_2_8 && !wxUSE_STL_BASED_WXSTRING && wxUSE_UNICODE_UTF8
1967
1968 // wxWidgets version 1 compatibility functions
1969
1970 // use Mid()
1971 wxString SubString(size_t from, size_t to) const
1972 { return Mid(from, (to - from + 1)); }
1973 // values for second parameter of CompareTo function
1974 enum caseCompare {exact, ignoreCase};
1975 // values for first parameter of Strip function
1976 enum stripType {leading = 0x1, trailing = 0x2, both = 0x3};
1977
1978 #ifndef wxNEEDS_WXSTRING_PRINTF_MIXIN
1979 // use Printf()
1980 // (take 'this' into account in attribute parameter count)
1981 // int sprintf(const wxString& format, ...) ATTRIBUTE_PRINTF_2;
1982 WX_DEFINE_VARARG_FUNC(int, sprintf, 1, (const wxFormatString&),
1983 DoPrintfWchar, DoPrintfUtf8)
1984 #ifdef __WATCOMC__
1985 // workaround for http://bugzilla.openwatcom.org/show_bug.cgi?id=351
1986 WX_VARARG_WATCOM_WORKAROUND(int, sprintf, 1, (const wxString&),
1987 (wxFormatString(f1)));
1988 WX_VARARG_WATCOM_WORKAROUND(int, sprintf, 1, (const wxCStrData&),
1989 (wxFormatString(f1)));
1990 WX_VARARG_WATCOM_WORKAROUND(int, sprintf, 1, (const char*),
1991 (wxFormatString(f1)));
1992 WX_VARARG_WATCOM_WORKAROUND(int, sprintf, 1, (const wchar_t*),
1993 (wxFormatString(f1)));
1994 #endif
1995 #endif // wxNEEDS_WXSTRING_PRINTF_MIXIN
1996
1997 // use Cmp()
1998 int CompareTo(const wxChar* psz, caseCompare cmp = exact) const
1999 { return cmp == exact ? Cmp(psz) : CmpNoCase(psz); }
2000
2001 // use length()
2002 size_t Length() const { return length(); }
2003 // Count the number of characters
2004 int Freq(wxUniChar ch) const;
2005 // use MakeLower
2006 void LowerCase() { MakeLower(); }
2007 // use MakeUpper
2008 void UpperCase() { MakeUpper(); }
2009 // use Trim except that it doesn't change this string
2010 wxString Strip(stripType w = trailing) const;
2011
2012 // use Find (more general variants not yet supported)
2013 size_t Index(const wxChar* psz) const { return Find(psz); }
2014 size_t Index(wxUniChar ch) const { return Find(ch); }
2015 // use Truncate
2016 wxString& Remove(size_t pos) { return Truncate(pos); }
2017 wxString& RemoveLast(size_t n = 1) { return Truncate(length() - n); }
2018
2019 wxString& Remove(size_t nStart, size_t nLen)
2020 { return (wxString&)erase( nStart, nLen ); }
2021
2022 // use Find()
2023 int First( wxUniChar ch ) const { return Find(ch); }
2024 int First( wxUniCharRef ch ) const { return Find(ch); }
2025 int First( char ch ) const { return Find(ch); }
2026 int First( unsigned char ch ) const { return Find(ch); }
2027 int First( wchar_t ch ) const { return Find(ch); }
2028 int First( const wxString& str ) const { return Find(str); }
2029 int Last( wxUniChar ch ) const { return Find(ch, true); }
2030 bool Contains(const wxString& str) const { return Find(str) != wxNOT_FOUND; }
2031
2032 // use empty()
2033 bool IsNull() const { return empty(); }
2034
2035 // std::string compatibility functions
2036
2037 // take nLen chars starting at nPos
2038 wxString(const wxString& str, size_t nPos, size_t nLen)
2039 { assign(str, nPos, nLen); }
2040 // take all characters from first to last
2041 wxString(const_iterator first, const_iterator last)
2042 : m_impl(first.impl(), last.impl()) { }
2043 #if WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER
2044 // the 2 overloads below are for compatibility with the existing code using
2045 // pointers instead of iterators
2046 wxString(const char *first, const char *last)
2047 {
2048 SubstrBufFromMB str(ImplStr(first, last - first));
2049 m_impl.assign(str.data, str.len);
2050 }
2051 wxString(const wchar_t *first, const wchar_t *last)
2052 {
2053 SubstrBufFromWC str(ImplStr(first, last - first));
2054 m_impl.assign(str.data, str.len);
2055 }
2056 // and this one is needed to compile code adding offsets to c_str() result
2057 wxString(const wxCStrData& first, const wxCStrData& last)
2058 : m_impl(CreateConstIterator(first).impl(),
2059 CreateConstIterator(last).impl())
2060 {
2061 wxASSERT_MSG( first.m_str == last.m_str,
2062 _T("pointers must be into the same string") );
2063 }
2064 #endif // WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER
2065
2066 // lib.string.modifiers
2067 // append elements str[pos], ..., str[pos+n]
2068 wxString& append(const wxString& str, size_t pos, size_t n)
2069 {
2070 size_t from, len;
2071 str.PosLenToImpl(pos, n, &from, &len);
2072 m_impl.append(str.m_impl, from, len);
2073 return *this;
2074 }
2075 // append a string
2076 wxString& append(const wxString& str)
2077 { m_impl.append(str.m_impl); return *this; }
2078 // append first n (or all if n == npos) characters of sz
2079 wxString& append(const char *sz)
2080 { m_impl.append(ImplStr(sz)); return *this; }
2081 wxString& append(const wchar_t *sz)
2082 { m_impl.append(ImplStr(sz)); return *this; }
2083 wxString& append(const char *sz, size_t n)
2084 {
2085 SubstrBufFromMB str(ImplStr(sz, n));
2086 m_impl.append(str.data, str.len);
2087 return *this;
2088 }
2089 wxString& append(const wchar_t *sz, size_t n)
2090 {
2091 SubstrBufFromWC str(ImplStr(sz, n));
2092 m_impl.append(str.data, str.len);
2093 return *this;
2094 }
2095
2096 wxString& append(const wxCStrData& str)
2097 { return append(str.AsString()); }
2098 wxString& append(const wxCharBuffer& str)
2099 { return append(str.data()); }
2100 wxString& append(const wxWCharBuffer& str)
2101 { return append(str.data()); }
2102 wxString& append(const wxCStrData& str, size_t n)
2103 { return append(str.AsString(), 0, n); }
2104 wxString& append(const wxCharBuffer& str, size_t n)
2105 { return append(str.data(), n); }
2106 wxString& append(const wxWCharBuffer& str, size_t n)
2107 { return append(str.data(), n); }
2108
2109 // append n copies of ch
2110 wxString& append(size_t n, wxUniChar ch)
2111 {
2112 #if wxUSE_UNICODE_UTF8
2113 if ( !ch.IsAscii() )
2114 m_impl.append(wxStringOperations::EncodeNChars(n, ch));
2115 else
2116 #endif
2117 m_impl.append(n, (wxStringCharType)ch);
2118 return *this;
2119 }
2120 wxString& append(size_t n, wxUniCharRef ch)
2121 { return append(n, wxUniChar(ch)); }
2122 wxString& append(size_t n, char ch)
2123 { return append(n, wxUniChar(ch)); }
2124 wxString& append(size_t n, unsigned char ch)
2125 { return append(n, wxUniChar(ch)); }
2126 wxString& append(size_t n, wchar_t ch)
2127 { return append(n, wxUniChar(ch)); }
2128
2129 // append from first to last
2130 wxString& append(const_iterator first, const_iterator last)
2131 { m_impl.append(first.impl(), last.impl()); return *this; }
2132 #if WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER
2133 wxString& append(const char *first, const char *last)
2134 { return append(first, last - first); }
2135 wxString& append(const wchar_t *first, const wchar_t *last)
2136 { return append(first, last - first); }
2137 wxString& append(const wxCStrData& first, const wxCStrData& last)
2138 { return append(CreateConstIterator(first), CreateConstIterator(last)); }
2139 #endif // WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER
2140
2141 // same as `this_string = str'
2142 wxString& assign(const wxString& str)
2143 {
2144 wxSTRING_INVALIDATE_INDEX_CACHE();
2145
2146 m_impl = str.m_impl;
2147
2148 return *this;
2149 }
2150
2151 wxString& assign(const wxString& str, size_t len)
2152 {
2153 wxSTRING_INVALIDATE_INDEX_CACHE();
2154
2155 m_impl.assign(str.m_impl, 0, str.LenToImpl(len));
2156
2157 return *this;
2158 }
2159
2160 // same as ` = str[pos..pos + n]
2161 wxString& assign(const wxString& str, size_t pos, size_t n)
2162 {
2163 wxSTRING_INVALIDATE_INDEX_CACHE();
2164
2165 size_t from, len;
2166 str.PosLenToImpl(pos, n, &from, &len);
2167 m_impl.assign(str.m_impl, from, len);
2168 return *this;
2169 }
2170
2171 // same as `= first n (or all if n == npos) characters of sz'
2172 wxString& assign(const char *sz)
2173 {
2174 wxSTRING_INVALIDATE_INDEX_CACHE();
2175
2176 m_impl.assign(ImplStr(sz));
2177
2178 return *this;
2179 }
2180
2181 wxString& assign(const wchar_t *sz)
2182 {
2183 wxSTRING_INVALIDATE_INDEX_CACHE();
2184
2185 m_impl.assign(ImplStr(sz));
2186
2187 return *this;
2188 }
2189
2190 wxString& assign(const char *sz, size_t n)
2191 {
2192 wxSTRING_INVALIDATE_INDEX_CACHE();
2193
2194 SubstrBufFromMB str(ImplStr(sz, n));
2195 m_impl.assign(str.data, str.len);
2196
2197 return *this;
2198 }
2199
2200 wxString& assign(const wchar_t *sz, size_t n)
2201 {
2202 wxSTRING_INVALIDATE_INDEX_CACHE();
2203
2204 SubstrBufFromWC str(ImplStr(sz, n));
2205 m_impl.assign(str.data, str.len);
2206
2207 return *this;
2208 }
2209
2210 wxString& assign(const wxCStrData& str)
2211 { return assign(str.AsString()); }
2212 wxString& assign(const wxCharBuffer& str)
2213 { return assign(str.data()); }
2214 wxString& assign(const wxWCharBuffer& str)
2215 { return assign(str.data()); }
2216 wxString& assign(const wxCStrData& str, size_t len)
2217 { return assign(str.AsString(), len); }
2218 wxString& assign(const wxCharBuffer& str, size_t len)
2219 { return assign(str.data(), len); }
2220 wxString& assign(const wxWCharBuffer& str, size_t len)
2221 { return assign(str.data(), len); }
2222
2223 // same as `= n copies of ch'
2224 wxString& assign(size_t n, wxUniChar ch)
2225 {
2226 wxSTRING_INVALIDATE_INDEX_CACHE();
2227
2228 #if wxUSE_UNICODE_UTF8
2229 if ( !ch.IsAscii() )
2230 m_impl.assign(wxStringOperations::EncodeNChars(n, ch));
2231 else
2232 #endif
2233 m_impl.assign(n, (wxStringCharType)ch);
2234 return *this;
2235 }
2236
2237 wxString& assign(size_t n, wxUniCharRef ch)
2238 { return assign(n, wxUniChar(ch)); }
2239 wxString& assign(size_t n, char ch)
2240 { return assign(n, wxUniChar(ch)); }
2241 wxString& assign(size_t n, unsigned char ch)
2242 { return assign(n, wxUniChar(ch)); }
2243 wxString& assign(size_t n, wchar_t ch)
2244 { return assign(n, wxUniChar(ch)); }
2245
2246 // assign from first to last
2247 wxString& assign(const_iterator first, const_iterator last)
2248 {
2249 wxSTRING_INVALIDATE_INDEX_CACHE();
2250
2251 m_impl.assign(first.impl(), last.impl());
2252
2253 return *this;
2254 }
2255 #if WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER
2256 wxString& assign(const char *first, const char *last)
2257 { return assign(first, last - first); }
2258 wxString& assign(const wchar_t *first, const wchar_t *last)
2259 { return assign(first, last - first); }
2260 wxString& assign(const wxCStrData& first, const wxCStrData& last)
2261 { return assign(CreateConstIterator(first), CreateConstIterator(last)); }
2262 #endif // WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER
2263
2264 // string comparison
2265 int compare(const wxString& str) const;
2266 int compare(const char* sz) const;
2267 int compare(const wchar_t* sz) const;
2268 int compare(const wxCStrData& str) const
2269 { return compare(str.AsString()); }
2270 int compare(const wxCharBuffer& str) const
2271 { return compare(str.data()); }
2272 int compare(const wxWCharBuffer& str) const
2273 { return compare(str.data()); }
2274 // comparison with a substring
2275 int compare(size_t nStart, size_t nLen, const wxString& str) const;
2276 // comparison of 2 substrings
2277 int compare(size_t nStart, size_t nLen,
2278 const wxString& str, size_t nStart2, size_t nLen2) const;
2279 // substring comparison with first nCount characters of sz
2280 int compare(size_t nStart, size_t nLen,
2281 const char* sz, size_t nCount = npos) const;
2282 int compare(size_t nStart, size_t nLen,
2283 const wchar_t* sz, size_t nCount = npos) const;
2284
2285 // insert another string
2286 wxString& insert(size_t nPos, const wxString& str)
2287 { insert(GetNthIter(nPos), str.begin(), str.end()); return *this; }
2288 // insert n chars of str starting at nStart (in str)
2289 wxString& insert(size_t nPos, const wxString& str, size_t nStart, size_t n)
2290 {
2291 wxSTRING_INVALIDATE_INDEX_CACHE();
2292
2293 size_t from, len;
2294 str.PosLenToImpl(nStart, n, &from, &len);
2295 m_impl.insert(PosToImpl(nPos), str.m_impl, from, len);
2296
2297 return *this;
2298 }
2299
2300 // insert first n (or all if n == npos) characters of sz
2301 wxString& insert(size_t nPos, const char *sz)
2302 {
2303 wxSTRING_INVALIDATE_INDEX_CACHE();
2304
2305 m_impl.insert(PosToImpl(nPos), ImplStr(sz));
2306
2307 return *this;
2308 }
2309
2310 wxString& insert(size_t nPos, const wchar_t *sz)
2311 {
2312 wxSTRING_INVALIDATE_INDEX_CACHE();
2313
2314 m_impl.insert(PosToImpl(nPos), ImplStr(sz)); return *this;
2315 }
2316
2317 wxString& insert(size_t nPos, const char *sz, size_t n)
2318 {
2319 wxSTRING_INVALIDATE_INDEX_CACHE();
2320
2321 SubstrBufFromMB str(ImplStr(sz, n));
2322 m_impl.insert(PosToImpl(nPos), str.data, str.len);
2323
2324 return *this;
2325 }
2326
2327 wxString& insert(size_t nPos, const wchar_t *sz, size_t n)
2328 {
2329 wxSTRING_INVALIDATE_INDEX_CACHE();
2330
2331 SubstrBufFromWC str(ImplStr(sz, n));
2332 m_impl.insert(PosToImpl(nPos), str.data, str.len);
2333
2334 return *this;
2335 }
2336
2337 // insert n copies of ch
2338 wxString& insert(size_t nPos, size_t n, wxUniChar ch)
2339 {
2340 wxSTRING_INVALIDATE_INDEX_CACHE();
2341
2342 #if wxUSE_UNICODE_UTF8
2343 if ( !ch.IsAscii() )
2344 m_impl.insert(PosToImpl(nPos), wxStringOperations::EncodeNChars(n, ch));
2345 else
2346 #endif
2347 m_impl.insert(PosToImpl(nPos), n, (wxStringCharType)ch);
2348 return *this;
2349 }
2350
2351 iterator insert(iterator it, wxUniChar ch)
2352 {
2353 wxSTRING_INVALIDATE_INDEX_CACHE();
2354
2355 #if wxUSE_UNICODE_UTF8
2356 if ( !ch.IsAscii() )
2357 {
2358 size_t pos = IterToImplPos(it);
2359 m_impl.insert(pos, wxStringOperations::EncodeChar(ch));
2360 return iterator(this, m_impl.begin() + pos);
2361 }
2362 else
2363 #endif
2364 return iterator(this, m_impl.insert(it.impl(), (wxStringCharType)ch));
2365 }
2366
2367 void insert(iterator it, const_iterator first, const_iterator last)
2368 {
2369 wxSTRING_INVALIDATE_INDEX_CACHE();
2370
2371 m_impl.insert(it.impl(), first.impl(), last.impl());
2372 }
2373
2374 #if WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER
2375 void insert(iterator it, const char *first, const char *last)
2376 { insert(it - begin(), first, last - first); }
2377 void insert(iterator it, const wchar_t *first, const wchar_t *last)
2378 { insert(it - begin(), first, last - first); }
2379 void insert(iterator it, const wxCStrData& first, const wxCStrData& last)
2380 { insert(it, CreateConstIterator(first), CreateConstIterator(last)); }
2381 #endif // WXWIN_COMPATIBILITY_STRING_PTR_AS_ITER
2382
2383 void insert(iterator it, size_type n, wxUniChar ch)
2384 {
2385 wxSTRING_INVALIDATE_INDEX_CACHE();
2386
2387 #if wxUSE_UNICODE_UTF8
2388 if ( !ch.IsAscii() )
2389 m_impl.insert(IterToImplPos(it), wxStringOperations::EncodeNChars(n, ch));
2390 else
2391 #endif
2392 m_impl.insert(it.impl(), n, (wxStringCharType)ch);
2393 }
2394
2395 // delete characters from nStart to nStart + nLen
2396 wxString& erase(size_type pos = 0, size_type n = npos)
2397 {
2398 wxSTRING_INVALIDATE_INDEX_CACHE();
2399
2400 size_t from, len;
2401 PosLenToImpl(pos, n, &from, &len);
2402 m_impl.erase(from, len);
2403
2404 return *this;
2405 }
2406
2407 // delete characters from first up to last
2408 iterator erase(iterator first, iterator last)
2409 {
2410 wxSTRING_INVALIDATE_INDEX_CACHE();
2411
2412 return iterator(this, m_impl.erase(first.impl(), last.impl()));
2413 }
2414
2415 iterator erase(iterator first)
2416 {
2417 wxSTRING_INVALIDATE_INDEX_CACHE();
2418
2419 return iterator(this, m_impl.erase(first.impl()));
2420 }
2421
2422 #ifdef wxSTRING_BASE_HASNT_CLEAR
2423 void clear() { erase(); }
2424 #else
2425 void clear()
2426 {
2427 wxSTRING_INVALIDATE_INDEX_CACHE();
2428
2429 m_impl.clear();
2430 }
2431 #endif
2432
2433 // replaces the substring of length nLen starting at nStart
2434 wxString& replace(size_t nStart, size_t nLen, const char* sz)
2435 {
2436 wxSTRING_INVALIDATE_INDEX_CACHE();
2437
2438 size_t from, len;
2439 PosLenToImpl(nStart, nLen, &from, &len);
2440 m_impl.replace(from, len, ImplStr(sz));
2441
2442 return *this;
2443 }
2444
2445 wxString& replace(size_t nStart, size_t nLen, const wchar_t* sz)
2446 {
2447 wxSTRING_INVALIDATE_INDEX_CACHE();
2448
2449 size_t from, len;
2450 PosLenToImpl(nStart, nLen, &from, &len);
2451 m_impl.replace(from, len, ImplStr(sz));
2452
2453 return *this;
2454 }
2455
2456 // replaces the substring of length nLen starting at nStart
2457 wxString& replace(size_t nStart, size_t nLen, const wxString& str)
2458 {
2459 wxSTRING_INVALIDATE_INDEX_CACHE();
2460
2461 size_t from, len;
2462 PosLenToImpl(nStart, nLen, &from, &len);
2463 m_impl.replace(from, len, str.m_impl);
2464
2465 return *this;
2466 }
2467
2468 // replaces the substring with nCount copies of ch
2469 wxString& replace(size_t nStart, size_t nLen, size_t nCount, wxUniChar ch)
2470 {
2471 wxSTRING_INVALIDATE_INDEX_CACHE();
2472
2473 size_t from, len;
2474 PosLenToImpl(nStart, nLen, &from, &len);
2475 #if wxUSE_UNICODE_UTF8
2476 if ( !ch.IsAscii() )
2477 m_impl.replace(from, len, wxStringOperations::EncodeNChars(nCount, ch));
2478 else
2479 #endif
2480 m_impl.replace(from, len, nCount, (wxStringCharType)ch);
2481
2482 return *this;
2483 }
2484
2485 // replaces a substring with another substring
2486 wxString& replace(size_t nStart, size_t nLen,
2487 const wxString& str, size_t nStart2, size_t nLen2)
2488 {
2489 wxSTRING_INVALIDATE_INDEX_CACHE();
2490
2491 size_t from, len;
2492 PosLenToImpl(nStart, nLen, &from, &len);
2493
2494 size_t from2, len2;
2495 str.PosLenToImpl(nStart2, nLen2, &from2, &len2);
2496
2497 m_impl.replace(from, len, str.m_impl, from2, len2);
2498
2499 return *this;
2500 }
2501
2502 // replaces the substring with first nCount chars of sz
2503 wxString& replace(size_t nStart, size_t nLen,
2504 const char* sz, size_t nCount)
2505 {
2506 wxSTRING_INVALIDATE_INDEX_CACHE();
2507
2508 size_t from, len;
2509 PosLenToImpl(nStart, nLen, &from, &len);
2510
2511 SubstrBufFromMB str(ImplStr(sz, nCount));
2512
2513 m_impl.replace(from, len, str.data, str.len);
2514
2515 return *this;
2516 }
2517
2518 wxString& replace(size_t nStart, size_t nLen,
2519 const wchar_t* sz, size_t nCount)
2520 {
2521 wxSTRING_INVALIDATE_INDEX_CACHE();
2522
2523 size_t from, len;
2524 PosLenToImpl(nStart, nLen, &from, &len);
2525
2526 SubstrBufFromWC str(ImplStr(sz, nCount));
2527
2528 m_impl.replace(from, len, str.data, str.len);
2529
2530 return *this;
2531 }
2532
2533 wxString& replace(size_t nStart, size_t nLen,
2534 const wxString& s, size_t nCount)
2535 {
2536 wxSTRING_INVALIDATE_INDEX_CACHE();
2537
2538 size_t from, len;
2539 PosLenToImpl(nStart, nLen, &from, &len);
2540 m_impl.replace(from, len, s.m_impl.c_str(), s.LenToImpl(nCount));
2541
2542 return *this;
2543 }
2544
2545 wxString& replace(iterator first, iterator last, const char* s)
2546 {
2547 wxSTRING_INVALIDATE_INDEX_CACHE();
2548
2549 m_impl.replace(first.impl(), last.impl(), ImplStr(s));
2550
2551 return *this;
2552 }
2553
2554 wxString& replace(iterator first, iterator last, const wchar_t* s)
2555 {
2556 wxSTRING_INVALIDATE_INDEX_CACHE();
2557
2558 m_impl.replace(first.impl(), last.impl(), ImplStr(s));
2559
2560 return *this;
2561 }
2562
2563 wxString& replace(iterator first, iterator last, const char* s, size_type n)
2564 {
2565 wxSTRING_INVALIDATE_INDEX_CACHE();
2566
2567 SubstrBufFromMB str(ImplStr(s, n));
2568 m_impl.replace(first.impl(), last.impl(), str.data, str.len);
2569
2570 return *this;
2571 }
2572
2573 wxString& replace(iterator first, iterator last, const wchar_t* s, size_type n)
2574 {
2575 wxSTRING_INVALIDATE_INDEX_CACHE();
2576
2577 SubstrBufFromWC str(ImplStr(s, n));
2578 m_impl.replace(first.impl(), last.impl(), str.data, str.len);
2579
2580 return *this;
2581 }
2582
2583 wxString& replace(iterator first, iterator last, const wxString& s)
2584 {
2585 wxSTRING_INVALIDATE_INDEX_CACHE();
2586
2587 m_impl.replace(first.impl(), last.impl(), s.m_impl);
2588
2589 return *this;
2590 }
2591
2592 wxString& replace(iterator first, iterator last, size_type n, wxUniChar ch)
2593 {
2594 wxSTRING_INVALIDATE_INDEX_CACHE();
2595
2596 #if wxUSE_UNICODE_UTF8
2597 if ( !ch.IsAscii() )
2598 m_impl.replace(first.impl(), last.impl(),
2599 wxStringOperations::EncodeNChars(n, ch));
2600 else
2601 #endif
2602 m_impl.replace(first.impl(), last.impl(), n, (wxStringCharType)ch);
2603
2604 return *this;
2605 }
2606
2607 wxString& replace(iterator first, iterator last,
2608 const_iterator first1, const_iterator last1)
2609 {
2610 wxSTRING_INVALIDATE_INDEX_CACHE();
2611
2612 m_impl.replace(first.impl(), last.impl(), first1.impl(), last1.impl());
2613
2614 return *this;
2615 }
2616
2617 wxString& replace(iterator first, iterator last,
2618 const char *first1, const char *last1)
2619 { replace(first, last, first1, last1 - first1); return *this; }
2620 wxString& replace(iterator first, iterator last,
2621 const wchar_t *first1, const wchar_t *last1)
2622 { replace(first, last, first1, last1 - first1); return *this; }
2623
2624 // swap two strings
2625 void swap(wxString& str)
2626 {
2627 wxSTRING_INVALIDATE_INDEX_CACHE();
2628
2629 m_impl.swap(str.m_impl);
2630 }
2631
2632 // find a substring
2633 size_t find(const wxString& str, size_t nStart = 0) const
2634 { return PosFromImpl(m_impl.find(str.m_impl, PosToImpl(nStart))); }
2635
2636 // find first n characters of sz
2637 size_t find(const char* sz, size_t nStart = 0, size_t n = npos) const
2638 {
2639 SubstrBufFromMB str(ImplStr(sz, n));
2640 return PosFromImpl(m_impl.find(str.data, PosToImpl(nStart), str.len));
2641 }
2642 size_t find(const wchar_t* sz, size_t nStart = 0, size_t n = npos) const
2643 {
2644 SubstrBufFromWC str(ImplStr(sz, n));
2645 return PosFromImpl(m_impl.find(str.data, PosToImpl(nStart), str.len));
2646 }
2647 size_t find(const wxCharBuffer& s, size_t nStart = 0, size_t n = npos) const
2648 { return find(s.data(), nStart, n); }
2649 size_t find(const wxWCharBuffer& s, size_t nStart = 0, size_t n = npos) const
2650 { return find(s.data(), nStart, n); }
2651 size_t find(const wxCStrData& s, size_t nStart = 0, size_t n = npos) const
2652 { return find(s.AsWChar(), nStart, n); }
2653
2654 // find the first occurence of character ch after nStart
2655 size_t find(wxUniChar ch, size_t nStart = 0) const
2656 {
2657 #if wxUSE_UNICODE_UTF8
2658 if ( !ch.IsAscii() )
2659 return PosFromImpl(m_impl.find(wxStringOperations::EncodeChar(ch),
2660 PosToImpl(nStart)));
2661 else
2662 #endif
2663 return PosFromImpl(m_impl.find((wxStringCharType)ch,
2664 PosToImpl(nStart)));
2665
2666 }
2667 size_t find(wxUniCharRef ch, size_t nStart = 0) const
2668 { return find(wxUniChar(ch), nStart); }
2669 size_t find(char ch, size_t nStart = 0) const
2670 { return find(wxUniChar(ch), nStart); }
2671 size_t find(unsigned char ch, size_t nStart = 0) const
2672 { return find(wxUniChar(ch), nStart); }
2673 size_t find(wchar_t ch, size_t nStart = 0) const
2674 { return find(wxUniChar(ch), nStart); }
2675
2676 // rfind() family is exactly like find() but works right to left
2677
2678 // as find, but from the end
2679 size_t rfind(const wxString& str, size_t nStart = npos) const
2680 { return PosFromImpl(m_impl.rfind(str.m_impl, PosToImpl(nStart))); }
2681
2682 // as find, but from the end
2683 size_t rfind(const char* sz, size_t nStart = npos, size_t n = npos) const
2684 {
2685 SubstrBufFromMB str(ImplStr(sz, n));
2686 return PosFromImpl(m_impl.rfind(str.data, PosToImpl(nStart), str.len));
2687 }
2688 size_t rfind(const wchar_t* sz, size_t nStart = npos, size_t n = npos) const
2689 {
2690 SubstrBufFromWC str(ImplStr(sz, n));
2691 return PosFromImpl(m_impl.rfind(str.data, PosToImpl(nStart), str.len));
2692 }
2693 size_t rfind(const wxCharBuffer& s, size_t nStart = npos, size_t n = npos) const
2694 { return rfind(s.data(), nStart, n); }
2695 size_t rfind(const wxWCharBuffer& s, size_t nStart = npos, size_t n = npos) const
2696 { return rfind(s.data(), nStart, n); }
2697 size_t rfind(const wxCStrData& s, size_t nStart = npos, size_t n = npos) const
2698 { return rfind(s.AsWChar(), nStart, n); }
2699 // as find, but from the end
2700 size_t rfind(wxUniChar ch, size_t nStart = npos) const
2701 {
2702 #if wxUSE_UNICODE_UTF8
2703 if ( !ch.IsAscii() )
2704 return PosFromImpl(m_impl.rfind(wxStringOperations::EncodeChar(ch),
2705 PosToImpl(nStart)));
2706 else
2707 #endif
2708 return PosFromImpl(m_impl.rfind((wxStringCharType)ch,
2709 PosToImpl(nStart)));
2710 }
2711 size_t rfind(wxUniCharRef ch, size_t nStart = npos) const
2712 { return rfind(wxUniChar(ch), nStart); }
2713 size_t rfind(char ch, size_t nStart = npos) const
2714 { return rfind(wxUniChar(ch), nStart); }
2715 size_t rfind(unsigned char ch, size_t nStart = npos) const
2716 { return rfind(wxUniChar(ch), nStart); }
2717 size_t rfind(wchar_t ch, size_t nStart = npos) const
2718 { return rfind(wxUniChar(ch), nStart); }
2719
2720 // find first/last occurence of any character (not) in the set:
2721 #if wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
2722 // FIXME-UTF8: this is not entirely correct, because it doesn't work if
2723 // sizeof(wchar_t)==2 and surrogates are present in the string;
2724 // should we care? Probably not.
2725 size_t find_first_of(const wxString& str, size_t nStart = 0) const
2726 { return m_impl.find_first_of(str.m_impl, nStart); }
2727 size_t find_first_of(const char* sz, size_t nStart = 0) const
2728 { return m_impl.find_first_of(ImplStr(sz), nStart); }
2729 size_t find_first_of(const wchar_t* sz, size_t nStart = 0) const
2730 { return m_impl.find_first_of(ImplStr(sz), nStart); }
2731 size_t find_first_of(const char* sz, size_t nStart, size_t n) const
2732 { return m_impl.find_first_of(ImplStr(sz), nStart, n); }
2733 size_t find_first_of(const wchar_t* sz, size_t nStart, size_t n) const
2734 { return m_impl.find_first_of(ImplStr(sz), nStart, n); }
2735 size_t find_first_of(wxUniChar c, size_t nStart = 0) const
2736 { return m_impl.find_first_of((wxChar)c, nStart); }
2737
2738 size_t find_last_of(const wxString& str, size_t nStart = npos) const
2739 { return m_impl.find_last_of(str.m_impl, nStart); }
2740 size_t find_last_of(const char* sz, size_t nStart = npos) const
2741 { return m_impl.find_last_of(ImplStr(sz), nStart); }
2742 size_t find_last_of(const wchar_t* sz, size_t nStart = npos) const
2743 { return m_impl.find_last_of(ImplStr(sz), nStart); }
2744 size_t find_last_of(const char* sz, size_t nStart, size_t n) const
2745 { return m_impl.find_last_of(ImplStr(sz), nStart, n); }
2746 size_t find_last_of(const wchar_t* sz, size_t nStart, size_t n) const
2747 { return m_impl.find_last_of(ImplStr(sz), nStart, n); }
2748 size_t find_last_of(wxUniChar c, size_t nStart = npos) const
2749 { return m_impl.find_last_of((wxChar)c, nStart); }
2750
2751 size_t find_first_not_of(const wxString& str, size_t nStart = 0) const
2752 { return m_impl.find_first_not_of(str.m_impl, nStart); }
2753 size_t find_first_not_of(const char* sz, size_t nStart = 0) const
2754 { return m_impl.find_first_not_of(ImplStr(sz), nStart); }
2755 size_t find_first_not_of(const wchar_t* sz, size_t nStart = 0) const
2756 { return m_impl.find_first_not_of(ImplStr(sz), nStart); }
2757 size_t find_first_not_of(const char* sz, size_t nStart, size_t n) const
2758 { return m_impl.find_first_not_of(ImplStr(sz), nStart, n); }
2759 size_t find_first_not_of(const wchar_t* sz, size_t nStart, size_t n) const
2760 { return m_impl.find_first_not_of(ImplStr(sz), nStart, n); }
2761 size_t find_first_not_of(wxUniChar c, size_t nStart = 0) const
2762 { return m_impl.find_first_not_of((wxChar)c, nStart); }
2763
2764 size_t find_last_not_of(const wxString& str, size_t nStart = npos) const
2765 { return m_impl.find_last_not_of(str.m_impl, nStart); }
2766 size_t find_last_not_of(const char* sz, size_t nStart = npos) const
2767 { return m_impl.find_last_not_of(ImplStr(sz), nStart); }
2768 size_t find_last_not_of(const wchar_t* sz, size_t nStart = npos) const
2769 { return m_impl.find_last_not_of(ImplStr(sz), nStart); }
2770 size_t find_last_not_of(const char* sz, size_t nStart, size_t n) const
2771 { return m_impl.find_last_not_of(ImplStr(sz), nStart, n); }
2772 size_t find_last_not_of(const wchar_t* sz, size_t nStart, size_t n) const
2773 { return m_impl.find_last_not_of(ImplStr(sz), nStart, n); }
2774 size_t find_last_not_of(wxUniChar c, size_t nStart = npos) const
2775 { return m_impl.find_last_not_of((wxChar)c, nStart); }
2776 #else
2777 // we can't use std::string implementation in UTF-8 build, because the
2778 // character sets would be interpreted wrongly:
2779
2780 // as strpbrk() but starts at nStart, returns npos if not found
2781 size_t find_first_of(const wxString& str, size_t nStart = 0) const
2782 #if wxUSE_UNICODE // FIXME-UTF8: temporary
2783 { return find_first_of(str.wc_str(), nStart); }
2784 #else
2785 { return find_first_of(str.mb_str(), nStart); }
2786 #endif
2787 // same as above
2788 size_t find_first_of(const char* sz, size_t nStart = 0) const;
2789 size_t find_first_of(const wchar_t* sz, size_t nStart = 0) const;
2790 size_t find_first_of(const char* sz, size_t nStart, size_t n) const;
2791 size_t find_first_of(const wchar_t* sz, size_t nStart, size_t n) const;
2792 // same as find(char, size_t)
2793 size_t find_first_of(wxUniChar c, size_t nStart = 0) const
2794 { return find(c, nStart); }
2795 // find the last (starting from nStart) char from str in this string
2796 size_t find_last_of (const wxString& str, size_t nStart = npos) const
2797 #if wxUSE_UNICODE // FIXME-UTF8: temporary
2798 { return find_last_of(str.wc_str(), nStart); }
2799 #else
2800 { return find_last_of(str.mb_str(), nStart); }
2801 #endif
2802 // same as above
2803 size_t find_last_of (const char* sz, size_t nStart = npos) const;
2804 size_t find_last_of (const wchar_t* sz, size_t nStart = npos) const;
2805 size_t find_last_of(const char* sz, size_t nStart, size_t n) const;
2806 size_t find_last_of(const wchar_t* sz, size_t nStart, size_t n) const;
2807 // same as above
2808 size_t find_last_of(wxUniChar c, size_t nStart = npos) const
2809 { return rfind(c, nStart); }
2810
2811 // find first/last occurence of any character not in the set
2812
2813 // as strspn() (starting from nStart), returns npos on failure
2814 size_t find_first_not_of(const wxString& str, size_t nStart = 0) const
2815 #if wxUSE_UNICODE // FIXME-UTF8: temporary
2816 { return find_first_not_of(str.wc_str(), nStart); }
2817 #else
2818 { return find_first_not_of(str.mb_str(), nStart); }
2819 #endif
2820 // same as above
2821 size_t find_first_not_of(const char* sz, size_t nStart = 0) const;
2822 size_t find_first_not_of(const wchar_t* sz, size_t nStart = 0) const;
2823 size_t find_first_not_of(const char* sz, size_t nStart, size_t n) const;
2824 size_t find_first_not_of(const wchar_t* sz, size_t nStart, size_t n) const;
2825 // same as above
2826 size_t find_first_not_of(wxUniChar ch, size_t nStart = 0) const;
2827 // as strcspn()
2828 size_t find_last_not_of(const wxString& str, size_t nStart = npos) const
2829 #if wxUSE_UNICODE // FIXME-UTF8: temporary
2830 { return find_last_not_of(str.wc_str(), nStart); }
2831 #else
2832 { return find_last_not_of(str.mb_str(), nStart); }
2833 #endif
2834 // same as above
2835 size_t find_last_not_of(const char* sz, size_t nStart = npos) const;
2836 size_t find_last_not_of(const wchar_t* sz, size_t nStart = npos) const;
2837 size_t find_last_not_of(const char* sz, size_t nStart, size_t n) const;
2838 size_t find_last_not_of(const wchar_t* sz, size_t nStart, size_t n) const;
2839 // same as above
2840 size_t find_last_not_of(wxUniChar ch, size_t nStart = npos) const;
2841 #endif // wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8 or not
2842
2843 // provide char/wchar_t/wxUniCharRef overloads for char-finding functions
2844 // above to resolve ambiguities:
2845 size_t find_first_of(wxUniCharRef ch, size_t nStart = 0) const
2846 { return find_first_of(wxUniChar(ch), nStart); }
2847 size_t find_first_of(char ch, size_t nStart = 0) const
2848 { return find_first_of(wxUniChar(ch), nStart); }
2849 size_t find_first_of(unsigned char ch, size_t nStart = 0) const
2850 { return find_first_of(wxUniChar(ch), nStart); }
2851 size_t find_first_of(wchar_t ch, size_t nStart = 0) const
2852 { return find_first_of(wxUniChar(ch), nStart); }
2853 size_t find_last_of(wxUniCharRef ch, size_t nStart = npos) const
2854 { return find_last_of(wxUniChar(ch), nStart); }
2855 size_t find_last_of(char ch, size_t nStart = npos) const
2856 { return find_last_of(wxUniChar(ch), nStart); }
2857 size_t find_last_of(unsigned char ch, size_t nStart = npos) const
2858 { return find_last_of(wxUniChar(ch), nStart); }
2859 size_t find_last_of(wchar_t ch, size_t nStart = npos) const
2860 { return find_last_of(wxUniChar(ch), nStart); }
2861 size_t find_first_not_of(wxUniCharRef ch, size_t nStart = 0) const
2862 { return find_first_not_of(wxUniChar(ch), nStart); }
2863 size_t find_first_not_of(char ch, size_t nStart = 0) const
2864 { return find_first_not_of(wxUniChar(ch), nStart); }
2865 size_t find_first_not_of(unsigned char ch, size_t nStart = 0) const
2866 { return find_first_not_of(wxUniChar(ch), nStart); }
2867 size_t find_first_not_of(wchar_t ch, size_t nStart = 0) const
2868 { return find_first_not_of(wxUniChar(ch), nStart); }
2869 size_t find_last_not_of(wxUniCharRef ch, size_t nStart = npos) const
2870 { return find_last_not_of(wxUniChar(ch), nStart); }
2871 size_t find_last_not_of(char ch, size_t nStart = npos) const
2872 { return find_last_not_of(wxUniChar(ch), nStart); }
2873 size_t find_last_not_of(unsigned char ch, size_t nStart = npos) const
2874 { return find_last_not_of(wxUniChar(ch), nStart); }
2875 size_t find_last_not_of(wchar_t ch, size_t nStart = npos) const
2876 { return find_last_not_of(wxUniChar(ch), nStart); }
2877
2878 // and additional overloads for the versions taking strings:
2879 size_t find_first_of(const wxCStrData& sz, size_t nStart = 0) const
2880 { return find_first_of(sz.AsString(), nStart); }
2881 size_t find_first_of(const wxCharBuffer& sz, size_t nStart = 0) const
2882 { return find_first_of(sz.data(), nStart); }
2883 size_t find_first_of(const wxWCharBuffer& sz, size_t nStart = 0) const
2884 { return find_first_of(sz.data(), nStart); }
2885 size_t find_first_of(const wxCStrData& sz, size_t nStart, size_t n) const
2886 { return find_first_of(sz.AsWChar(), nStart, n); }
2887 size_t find_first_of(const wxCharBuffer& sz, size_t nStart, size_t n) const
2888 { return find_first_of(sz.data(), nStart, n); }
2889 size_t find_first_of(const wxWCharBuffer& sz, size_t nStart, size_t n) const
2890 { return find_first_of(sz.data(), nStart, n); }
2891
2892 size_t find_last_of(const wxCStrData& sz, size_t nStart = 0) const
2893 { return find_last_of(sz.AsString(), nStart); }
2894 size_t find_last_of(const wxCharBuffer& sz, size_t nStart = 0) const
2895 { return find_last_of(sz.data(), nStart); }
2896 size_t find_last_of(const wxWCharBuffer& sz, size_t nStart = 0) const
2897 { return find_last_of(sz.data(), nStart); }
2898 size_t find_last_of(const wxCStrData& sz, size_t nStart, size_t n) const
2899 { return find_last_of(sz.AsWChar(), nStart, n); }
2900 size_t find_last_of(const wxCharBuffer& sz, size_t nStart, size_t n) const
2901 { return find_last_of(sz.data(), nStart, n); }
2902 size_t find_last_of(const wxWCharBuffer& sz, size_t nStart, size_t n) const
2903 { return find_last_of(sz.data(), nStart, n); }
2904
2905 size_t find_first_not_of(const wxCStrData& sz, size_t nStart = 0) const
2906 { return find_first_not_of(sz.AsString(), nStart); }
2907 size_t find_first_not_of(const wxCharBuffer& sz, size_t nStart = 0) const
2908 { return find_first_not_of(sz.data(), nStart); }
2909 size_t find_first_not_of(const wxWCharBuffer& sz, size_t nStart = 0) const
2910 { return find_first_not_of(sz.data(), nStart); }
2911 size_t find_first_not_of(const wxCStrData& sz, size_t nStart, size_t n) const
2912 { return find_first_not_of(sz.AsWChar(), nStart, n); }
2913 size_t find_first_not_of(const wxCharBuffer& sz, size_t nStart, size_t n) const
2914 { return find_first_not_of(sz.data(), nStart, n); }
2915 size_t find_first_not_of(const wxWCharBuffer& sz, size_t nStart, size_t n) const
2916 { return find_first_not_of(sz.data(), nStart, n); }
2917
2918 size_t find_last_not_of(const wxCStrData& sz, size_t nStart = 0) const
2919 { return find_last_not_of(sz.AsString(), nStart); }
2920 size_t find_last_not_of(const wxCharBuffer& sz, size_t nStart = 0) const
2921 { return find_last_not_of(sz.data(), nStart); }
2922 size_t find_last_not_of(const wxWCharBuffer& sz, size_t nStart = 0) const
2923 { return find_last_not_of(sz.data(), nStart); }
2924 size_t find_last_not_of(const wxCStrData& sz, size_t nStart, size_t n) const
2925 { return find_last_not_of(sz.AsWChar(), nStart, n); }
2926 size_t find_last_not_of(const wxCharBuffer& sz, size_t nStart, size_t n) const
2927 { return find_last_not_of(sz.data(), nStart, n); }
2928 size_t find_last_not_of(const wxWCharBuffer& sz, size_t nStart, size_t n) const
2929 { return find_last_not_of(sz.data(), nStart, n); }
2930
2931 // string += string
2932 wxString& operator+=(const wxString& s)
2933 { m_impl += s.m_impl; return *this; }
2934 // string += C string
2935 wxString& operator+=(const char *psz)
2936 { m_impl += ImplStr(psz); return *this; }
2937 wxString& operator+=(const wchar_t *pwz)
2938 { m_impl += ImplStr(pwz); return *this; }
2939 wxString& operator+=(const wxCStrData& s)
2940 { m_impl += s.AsString().m_impl; return *this; }
2941 wxString& operator+=(const wxCharBuffer& s)
2942 { return operator+=(s.data()); }
2943 wxString& operator+=(const wxWCharBuffer& s)
2944 { return operator+=(s.data()); }
2945 // string += char
2946 wxString& operator+=(wxUniChar ch)
2947 {
2948 #if wxUSE_UNICODE_UTF8
2949 if ( !ch.IsAscii() )
2950 m_impl += wxStringOperations::EncodeChar(ch);
2951 else
2952 #endif
2953 m_impl += (wxStringCharType)ch;
2954 return *this;
2955 }
2956 wxString& operator+=(wxUniCharRef ch) { return *this += wxUniChar(ch); }
2957 wxString& operator+=(int ch) { return *this += wxUniChar(ch); }
2958 wxString& operator+=(char ch) { return *this += wxUniChar(ch); }
2959 wxString& operator+=(unsigned char ch) { return *this += wxUniChar(ch); }
2960 wxString& operator+=(wchar_t ch) { return *this += wxUniChar(ch); }
2961
2962 private:
2963 #if !wxUSE_STL_BASED_WXSTRING
2964 // helpers for wxStringBuffer and wxStringBufferLength
2965 wxStringCharType *DoGetWriteBuf(size_t nLen)
2966 {
2967 return m_impl.DoGetWriteBuf(nLen);
2968 }
2969
2970 void DoUngetWriteBuf()
2971 {
2972 wxSTRING_INVALIDATE_INDEX_CACHE();
2973
2974 m_impl.DoUngetWriteBuf();
2975 }
2976
2977 void DoUngetWriteBuf(size_t nLen)
2978 {
2979 wxSTRING_INVALIDATE_INDEX_CACHE();
2980
2981 m_impl.DoUngetWriteBuf(nLen);
2982 }
2983 #endif // !wxUSE_STL_BASED_WXSTRING
2984
2985 #ifndef wxNEEDS_WXSTRING_PRINTF_MIXIN
2986 #if !wxUSE_UTF8_LOCALE_ONLY
2987 int DoPrintfWchar(const wxChar *format, ...);
2988 static wxString DoFormatWchar(const wxChar *format, ...);
2989 #endif
2990 #if wxUSE_UNICODE_UTF8
2991 int DoPrintfUtf8(const char *format, ...);
2992 static wxString DoFormatUtf8(const char *format, ...);
2993 #endif
2994 #endif
2995
2996 #if !wxUSE_STL_BASED_WXSTRING
2997 // check string's data validity
2998 bool IsValid() const { return m_impl.GetStringData()->IsValid(); }
2999 #endif
3000
3001 private:
3002 wxStringImpl m_impl;
3003
3004 // buffers for compatibility conversion from (char*)c_str() and
3005 // (wchar_t*)c_str():
3006 // FIXME-UTF8: bechmark various approaches to keeping compatibility buffers
3007 template<typename T>
3008 struct ConvertedBuffer
3009 {
3010 ConvertedBuffer() : m_buf(NULL) {}
3011 ~ConvertedBuffer()
3012 { free(m_buf); }
3013
3014 operator T*() const { return m_buf; }
3015
3016 ConvertedBuffer& operator=(T *str)
3017 {
3018 free(m_buf);
3019 m_buf = str;
3020 return *this;
3021 }
3022
3023 T *m_buf;
3024 };
3025 #if wxUSE_UNICODE && !wxUSE_UTF8_LOCALE_ONLY
3026 ConvertedBuffer<char> m_convertedToChar;
3027 #endif
3028 #if !wxUSE_UNICODE_WCHAR
3029 ConvertedBuffer<wchar_t> m_convertedToWChar;
3030 #endif
3031
3032 #if wxUSE_UNICODE_UTF8
3033 // FIXME-UTF8: (try to) move this elsewhere (TLS) or solve differently
3034 // assigning to character pointer to by wxString::interator may
3035 // change the underlying wxStringImpl iterator, so we have to
3036 // keep track of all iterators and update them as necessary:
3037 struct wxStringIteratorNodeHead
3038 {
3039 wxStringIteratorNodeHead() : ptr(NULL) {}
3040 wxStringIteratorNode *ptr;
3041
3042 // copying is disallowed as it would result in more than one pointer into
3043 // the same linked list
3044 DECLARE_NO_COPY_CLASS(wxStringIteratorNodeHead)
3045 };
3046
3047 wxStringIteratorNodeHead m_iterators;
3048
3049 friend class WXDLLIMPEXP_FWD_BASE wxStringIteratorNode;
3050 friend class WXDLLIMPEXP_FWD_BASE wxUniCharRef;
3051 #endif // wxUSE_UNICODE_UTF8
3052
3053 friend class WXDLLIMPEXP_FWD_BASE wxCStrData;
3054 friend class wxStringInternalBuffer;
3055 friend class wxStringInternalBufferLength;
3056 };
3057
3058 #ifdef wxNEEDS_WXSTRING_PRINTF_MIXIN
3059 #pragma warning (default:4275)
3060 #endif
3061
3062 // string iterator operators that satisfy STL Random Access Iterator
3063 // requirements:
3064 inline wxString::iterator operator+(ptrdiff_t n, wxString::iterator i)
3065 { return i + n; }
3066 inline wxString::const_iterator operator+(ptrdiff_t n, wxString::const_iterator i)
3067 { return i + n; }
3068 inline wxString::reverse_iterator operator+(ptrdiff_t n, wxString::reverse_iterator i)
3069 { return i + n; }
3070 inline wxString::const_reverse_iterator operator+(ptrdiff_t n, wxString::const_reverse_iterator i)
3071 { return i + n; }
3072
3073 // notice that even though for many compilers the friend declarations above are
3074 // enough, from the point of view of C++ standard we must have the declarations
3075 // here as friend ones are not injected in the enclosing namespace and without
3076 // them the code fails to compile with conforming compilers such as xlC or g++4
3077 wxString WXDLLIMPEXP_BASE operator+(const wxString& string1, const wxString& string2);
3078 wxString WXDLLIMPEXP_BASE operator+(const wxString& string, const char *psz);
3079 wxString WXDLLIMPEXP_BASE operator+(const wxString& string, const wchar_t *pwz);
3080 wxString WXDLLIMPEXP_BASE operator+(const char *psz, const wxString& string);
3081 wxString WXDLLIMPEXP_BASE operator+(const wchar_t *pwz, const wxString& string);
3082
3083 wxString WXDLLIMPEXP_BASE operator+(const wxString& string, wxUniChar ch);
3084 wxString WXDLLIMPEXP_BASE operator+(wxUniChar ch, const wxString& string);
3085
3086 inline wxString operator+(const wxString& string, wxUniCharRef ch)
3087 { return string + (wxUniChar)ch; }
3088 inline wxString operator+(const wxString& string, char ch)
3089 { return string + wxUniChar(ch); }
3090 inline wxString operator+(const wxString& string, wchar_t ch)
3091 { return string + wxUniChar(ch); }
3092 inline wxString operator+(wxUniCharRef ch, const wxString& string)
3093 { return (wxUniChar)ch + string; }
3094 inline wxString operator+(char ch, const wxString& string)
3095 { return wxUniChar(ch) + string; }
3096 inline wxString operator+(wchar_t ch, const wxString& string)
3097 { return wxUniChar(ch) + string; }
3098
3099
3100 #define wxGetEmptyString() wxString()
3101
3102 // ----------------------------------------------------------------------------
3103 // helper functions which couldn't be defined inline
3104 // ----------------------------------------------------------------------------
3105
3106 namespace wxPrivate
3107 {
3108
3109 #if wxUSE_UNICODE_WCHAR
3110
3111 template <>
3112 struct wxStringAsBufHelper<char>
3113 {
3114 static wxCharBuffer Get(const wxString& s, size_t *len)
3115 {
3116 wxCharBuffer buf(s.mb_str());
3117 if ( len )
3118 *len = buf ? strlen(buf) : 0;
3119 return buf;
3120 }
3121 };
3122
3123 template <>
3124 struct wxStringAsBufHelper<wchar_t>
3125 {
3126 static wxWCharBuffer Get(const wxString& s, size_t *len)
3127 {
3128 if ( len )
3129 *len = s.length();
3130 return wxWCharBuffer::CreateNonOwned(s.wx_str());
3131 }
3132 };
3133
3134 #elif wxUSE_UNICODE_UTF8
3135
3136 template <>
3137 struct wxStringAsBufHelper<char>
3138 {
3139 static wxCharBuffer Get(const wxString& s, size_t *len)
3140 {
3141 if ( len )
3142 *len = s.utf8_length();
3143 return wxCharBuffer::CreateNonOwned(s.wx_str());
3144 }
3145 };
3146
3147 template <>
3148 struct wxStringAsBufHelper<wchar_t>
3149 {
3150 static wxWCharBuffer Get(const wxString& s, size_t *len)
3151 {
3152 wxWCharBuffer wbuf(s.wc_str());
3153 if ( len )
3154 *len = wxWcslen(wbuf);
3155 return wbuf;
3156 }
3157 };
3158
3159 #endif // Unicode build kind
3160
3161 } // namespace wxPrivate
3162
3163 // ----------------------------------------------------------------------------
3164 // wxStringBuffer: a tiny class allowing to get a writable pointer into string
3165 // ----------------------------------------------------------------------------
3166
3167 #if !wxUSE_STL_BASED_WXSTRING
3168 // string buffer for direct access to string data in their native
3169 // representation:
3170 class wxStringInternalBuffer
3171 {
3172 public:
3173 typedef wxStringCharType CharType;
3174
3175 wxStringInternalBuffer(wxString& str, size_t lenWanted = 1024)
3176 : m_str(str), m_buf(NULL)
3177 { m_buf = m_str.DoGetWriteBuf(lenWanted); }
3178
3179 ~wxStringInternalBuffer() { m_str.DoUngetWriteBuf(); }
3180
3181 operator wxStringCharType*() const { return m_buf; }
3182
3183 private:
3184 wxString& m_str;
3185 wxStringCharType *m_buf;
3186
3187 DECLARE_NO_COPY_CLASS(wxStringInternalBuffer)
3188 };
3189
3190 class wxStringInternalBufferLength
3191 {
3192 public:
3193 typedef wxStringCharType CharType;
3194
3195 wxStringInternalBufferLength(wxString& str, size_t lenWanted = 1024)
3196 : m_str(str), m_buf(NULL), m_len(0), m_lenSet(false)
3197 {
3198 m_buf = m_str.DoGetWriteBuf(lenWanted);
3199 wxASSERT(m_buf != NULL);
3200 }
3201
3202 ~wxStringInternalBufferLength()
3203 {
3204 wxASSERT(m_lenSet);
3205 m_str.DoUngetWriteBuf(m_len);
3206 }
3207
3208 operator wxStringCharType*() const { return m_buf; }
3209 void SetLength(size_t length) { m_len = length; m_lenSet = true; }
3210
3211 private:
3212 wxString& m_str;
3213 wxStringCharType *m_buf;
3214 size_t m_len;
3215 bool m_lenSet;
3216
3217 DECLARE_NO_COPY_CLASS(wxStringInternalBufferLength)
3218 };
3219
3220 #endif // !wxUSE_STL_BASED_WXSTRING
3221
3222 template<typename T>
3223 class WXDLLIMPEXP_BASE wxStringTypeBufferBase
3224 {
3225 public:
3226 typedef T CharType;
3227
3228 wxStringTypeBufferBase(wxString& str, size_t lenWanted = 1024)
3229 : m_str(str), m_buf(lenWanted)
3230 {
3231 // for compatibility with old wxStringBuffer which provided direct
3232 // access to wxString internal buffer, initialize ourselves with the
3233 // string initial contents
3234
3235 // FIXME-VC6: remove the ugly (CharType *)NULL and use normal
3236 // tchar_str<CharType>
3237 size_t len;
3238 const wxCharTypeBuffer<CharType> buf(str.tchar_str(&len, (CharType *)NULL));
3239 if ( buf )
3240 {
3241 if ( len > lenWanted )
3242 {
3243 // in this case there is not enough space for terminating NUL,
3244 // ensure that we still put it there
3245 m_buf.data()[lenWanted] = 0;
3246 len = lenWanted - 1;
3247 }
3248
3249 memcpy(m_buf.data(), buf, (len + 1)*sizeof(CharType));
3250 }
3251 //else: conversion failed, this can happen when trying to get Unicode
3252 // string contents into a char string
3253 }
3254
3255 operator CharType*() { return m_buf.data(); }
3256
3257 protected:
3258 wxString& m_str;
3259 wxCharTypeBuffer<CharType> m_buf;
3260 };
3261
3262 template<typename T>
3263 class WXDLLIMPEXP_BASE wxStringTypeBufferLengthBase
3264 : public wxStringTypeBufferBase<T>
3265 {
3266 public:
3267 wxStringTypeBufferLengthBase(wxString& str, size_t lenWanted = 1024)
3268 : wxStringTypeBufferBase<T>(str, lenWanted),
3269 m_len(0),
3270 m_lenSet(false)
3271 { }
3272
3273 ~wxStringTypeBufferLengthBase()
3274 {
3275 wxASSERT_MSG( this->m_lenSet, "forgot to call SetLength()" );
3276 }
3277
3278 void SetLength(size_t length) { m_len = length; m_lenSet = true; }
3279
3280 protected:
3281 size_t m_len;
3282 bool m_lenSet;
3283 };
3284
3285 template<typename T>
3286 class wxStringTypeBuffer : public wxStringTypeBufferBase<T>
3287 {
3288 public:
3289 wxStringTypeBuffer(wxString& str, size_t lenWanted = 1024)
3290 : wxStringTypeBufferBase<T>(str, lenWanted)
3291 { }
3292
3293 ~wxStringTypeBuffer()
3294 {
3295 this->m_str.assign(this->m_buf.data());
3296 }
3297
3298 DECLARE_NO_COPY_CLASS(wxStringTypeBuffer)
3299 };
3300
3301 template<typename T>
3302 class wxStringTypeBufferLength : public wxStringTypeBufferLengthBase<T>
3303 {
3304 public:
3305 wxStringTypeBufferLength(wxString& str, size_t lenWanted = 1024)
3306 : wxStringTypeBufferLengthBase<T>(str, lenWanted)
3307 { }
3308
3309 ~wxStringTypeBufferLength()
3310 {
3311 this->m_str.assign(this->m_buf.data(), this->m_len);
3312 }
3313
3314 DECLARE_NO_COPY_CLASS(wxStringTypeBufferLength)
3315 };
3316
3317 #if wxUSE_STL_BASED_WXSTRING
3318
3319 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxStringTypeBufferBase<wxStringCharType> )
3320
3321 class wxStringInternalBuffer : public wxStringTypeBufferBase<wxStringCharType>
3322 {
3323 public:
3324 wxStringInternalBuffer(wxString& str, size_t lenWanted = 1024)
3325 : wxStringTypeBufferBase<wxStringCharType>(str, lenWanted) {}
3326 ~wxStringInternalBuffer()
3327 { m_str.m_impl.assign(m_buf.data()); }
3328
3329 DECLARE_NO_COPY_CLASS(wxStringInternalBuffer)
3330 };
3331
3332 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE(
3333 wxStringTypeBufferLengthBase<wxStringCharType> )
3334
3335 class wxStringInternalBufferLength
3336 : public wxStringTypeBufferLengthBase<wxStringCharType>
3337 {
3338 public:
3339 wxStringInternalBufferLength(wxString& str, size_t lenWanted = 1024)
3340 : wxStringTypeBufferLengthBase<wxStringCharType>(str, lenWanted) {}
3341
3342 ~wxStringInternalBufferLength()
3343 {
3344 m_str.m_impl.assign(m_buf.data(), m_len);
3345 }
3346
3347 DECLARE_NO_COPY_CLASS(wxStringInternalBufferLength)
3348 };
3349
3350 #endif // wxUSE_STL_BASED_WXSTRING
3351
3352
3353 #if wxUSE_STL_BASED_WXSTRING || wxUSE_UNICODE_UTF8
3354 typedef wxStringTypeBuffer<wxChar> wxStringBuffer;
3355 typedef wxStringTypeBufferLength<wxChar> wxStringBufferLength;
3356 #else // if !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
3357 typedef wxStringInternalBuffer wxStringBuffer;
3358 typedef wxStringInternalBufferLength wxStringBufferLength;
3359 #endif // !wxUSE_STL_BASED_WXSTRING && !wxUSE_UNICODE_UTF8
3360
3361 #if wxUSE_UNICODE_UTF8
3362 typedef wxStringInternalBuffer wxUTF8StringBuffer;
3363 typedef wxStringInternalBufferLength wxUTF8StringBufferLength;
3364 #elif wxUSE_UNICODE_WCHAR
3365
3366 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxStringTypeBufferBase<char> )
3367
3368 class WXDLLIMPEXP_BASE wxUTF8StringBuffer : public wxStringTypeBufferBase<char>
3369 {
3370 public:
3371 wxUTF8StringBuffer(wxString& str, size_t lenWanted = 1024)
3372 : wxStringTypeBufferBase<char>(str, lenWanted) {}
3373 ~wxUTF8StringBuffer();
3374
3375 DECLARE_NO_COPY_CLASS(wxUTF8StringBuffer)
3376 };
3377
3378 WXDLLIMPEXP_TEMPLATE_INSTANCE_BASE( wxStringTypeBufferLengthBase<char> )
3379
3380 class WXDLLIMPEXP_BASE wxUTF8StringBufferLength
3381 : public wxStringTypeBufferLengthBase<char>
3382 {
3383 public:
3384 wxUTF8StringBufferLength(wxString& str, size_t lenWanted = 1024)
3385 : wxStringTypeBufferLengthBase<char>(str, lenWanted) {}
3386 ~wxUTF8StringBufferLength();
3387
3388 DECLARE_NO_COPY_CLASS(wxUTF8StringBufferLength)
3389 };
3390 #endif // wxUSE_UNICODE_UTF8/wxUSE_UNICODE_WCHAR
3391
3392
3393 // ---------------------------------------------------------------------------
3394 // wxString comparison functions: operator versions are always case sensitive
3395 // ---------------------------------------------------------------------------
3396
3397 #define wxCMP_WXCHAR_STRING(p, s, op) 0 op s.Cmp(p)
3398
3399 wxDEFINE_ALL_COMPARISONS(const wxChar *, const wxString&, wxCMP_WXCHAR_STRING)
3400
3401 #undef wxCMP_WXCHAR_STRING
3402
3403 inline bool operator==(const wxString& s1, const wxString& s2)
3404 { return s1.IsSameAs(s2); }
3405 inline bool operator!=(const wxString& s1, const wxString& s2)
3406 { return !s1.IsSameAs(s2); }
3407 inline bool operator< (const wxString& s1, const wxString& s2)
3408 { return s1.Cmp(s2) < 0; }
3409 inline bool operator> (const wxString& s1, const wxString& s2)
3410 { return s1.Cmp(s2) > 0; }
3411 inline bool operator<=(const wxString& s1, const wxString& s2)
3412 { return s1.Cmp(s2) <= 0; }
3413 inline bool operator>=(const wxString& s1, const wxString& s2)
3414 { return s1.Cmp(s2) >= 0; }
3415
3416 inline bool operator==(const wxString& s1, const wxCStrData& s2)
3417 { return s1 == s2.AsString(); }
3418 inline bool operator==(const wxCStrData& s1, const wxString& s2)
3419 { return s1.AsString() == s2; }
3420 inline bool operator!=(const wxString& s1, const wxCStrData& s2)
3421 { return s1 != s2.AsString(); }
3422 inline bool operator!=(const wxCStrData& s1, const wxString& s2)
3423 { return s1.AsString() != s2; }
3424
3425 inline bool operator==(const wxString& s1, const wxWCharBuffer& s2)
3426 { return (s1.Cmp((const wchar_t *)s2) == 0); }
3427 inline bool operator==(const wxWCharBuffer& s1, const wxString& s2)
3428 { return (s2.Cmp((const wchar_t *)s1) == 0); }
3429 inline bool operator!=(const wxString& s1, const wxWCharBuffer& s2)
3430 { return (s1.Cmp((const wchar_t *)s2) != 0); }
3431 inline bool operator!=(const wxWCharBuffer& s1, const wxString& s2)
3432 { return (s2.Cmp((const wchar_t *)s1) != 0); }
3433
3434 inline bool operator==(const wxString& s1, const wxCharBuffer& s2)
3435 { return (s1.Cmp((const char *)s2) == 0); }
3436 inline bool operator==(const wxCharBuffer& s1, const wxString& s2)
3437 { return (s2.Cmp((const char *)s1) == 0); }
3438 inline bool operator!=(const wxString& s1, const wxCharBuffer& s2)
3439 { return (s1.Cmp((const char *)s2) != 0); }
3440 inline bool operator!=(const wxCharBuffer& s1, const wxString& s2)
3441 { return (s2.Cmp((const char *)s1) != 0); }
3442
3443 inline wxString operator+(const wxString& string, const wxWCharBuffer& buf)
3444 { return string + (const wchar_t *)buf; }
3445 inline wxString operator+(const wxWCharBuffer& buf, const wxString& string)
3446 { return (const wchar_t *)buf + string; }
3447
3448 inline wxString operator+(const wxString& string, const wxCharBuffer& buf)
3449 { return string + (const char *)buf; }
3450 inline wxString operator+(const wxCharBuffer& buf, const wxString& string)
3451 { return (const char *)buf + string; }
3452
3453 // comparison with char
3454 inline bool operator==(const wxUniChar& c, const wxString& s) { return s.IsSameAs(c); }
3455 inline bool operator==(const wxUniCharRef& c, const wxString& s) { return s.IsSameAs(c); }
3456 inline bool operator==(char c, const wxString& s) { return s.IsSameAs(c); }
3457 inline bool operator==(wchar_t c, const wxString& s) { return s.IsSameAs(c); }
3458 inline bool operator==(int c, const wxString& s) { return s.IsSameAs(c); }
3459 inline bool operator==(const wxString& s, const wxUniChar& c) { return s.IsSameAs(c); }
3460 inline bool operator==(const wxString& s, const wxUniCharRef& c) { return s.IsSameAs(c); }
3461 inline bool operator==(const wxString& s, char c) { return s.IsSameAs(c); }
3462 inline bool operator==(const wxString& s, wchar_t c) { return s.IsSameAs(c); }
3463 inline bool operator!=(const wxUniChar& c, const wxString& s) { return !s.IsSameAs(c); }
3464 inline bool operator!=(const wxUniCharRef& c, const wxString& s) { return !s.IsSameAs(c); }
3465 inline bool operator!=(char c, const wxString& s) { return !s.IsSameAs(c); }
3466 inline bool operator!=(wchar_t c, const wxString& s) { return !s.IsSameAs(c); }
3467 inline bool operator!=(int c, const wxString& s) { return !s.IsSameAs(c); }
3468 inline bool operator!=(const wxString& s, const wxUniChar& c) { return !s.IsSameAs(c); }
3469 inline bool operator!=(const wxString& s, const wxUniCharRef& c) { return !s.IsSameAs(c); }
3470 inline bool operator!=(const wxString& s, char c) { return !s.IsSameAs(c); }
3471 inline bool operator!=(const wxString& s, wchar_t c) { return !s.IsSameAs(c); }
3472
3473 // comparison with C string in Unicode build
3474 #if wxUSE_UNICODE
3475
3476 #define wxCMP_CHAR_STRING(p, s, op) wxString(p) op s
3477
3478 wxDEFINE_ALL_COMPARISONS(const char *, const wxString&, wxCMP_CHAR_STRING)
3479
3480 #undef wxCMP_CHAR_STRING
3481
3482 #endif // wxUSE_UNICODE
3483
3484 // we also need to provide the operators for comparison with wxCStrData to
3485 // resolve ambiguity between operator(const wxChar *,const wxString &) and
3486 // operator(const wxChar *, const wxChar *) for "p == s.c_str()"
3487 //
3488 // notice that these are (shallow) pointer comparisons, not (deep) string ones
3489 #define wxCMP_CHAR_CSTRDATA(p, s, op) p op s.AsChar()
3490 #define wxCMP_WCHAR_CSTRDATA(p, s, op) p op s.AsWChar()
3491
3492 wxDEFINE_ALL_COMPARISONS(const wchar_t *, const wxCStrData&, wxCMP_WCHAR_CSTRDATA)
3493 wxDEFINE_ALL_COMPARISONS(const char *, const wxCStrData&, wxCMP_CHAR_CSTRDATA)
3494
3495 #undef wxCMP_CHAR_CSTRDATA
3496 #undef wxCMP_WCHAR_CSTRDATA
3497
3498 // ---------------------------------------------------------------------------
3499 // Implementation only from here until the end of file
3500 // ---------------------------------------------------------------------------
3501
3502 #if wxUSE_STD_IOSTREAM
3503
3504 #include "wx/iosfwrap.h"
3505
3506 WXDLLIMPEXP_BASE wxSTD ostream& operator<<(wxSTD ostream&, const wxString&);
3507 WXDLLIMPEXP_BASE wxSTD ostream& operator<<(wxSTD ostream&, const wxCStrData&);
3508 WXDLLIMPEXP_BASE wxSTD ostream& operator<<(wxSTD ostream&, const wxCharBuffer&);
3509 #ifndef __BORLANDC__
3510 WXDLLIMPEXP_BASE wxSTD ostream& operator<<(wxSTD ostream&, const wxWCharBuffer&);
3511 #endif
3512
3513 #if wxUSE_UNICODE && defined(HAVE_WOSTREAM)
3514
3515 WXDLLIMPEXP_BASE wxSTD wostream& operator<<(wxSTD wostream&, const wxString&);
3516 WXDLLIMPEXP_BASE wxSTD wostream& operator<<(wxSTD wostream&, const wxCStrData&);
3517 WXDLLIMPEXP_BASE wxSTD wostream& operator<<(wxSTD wostream&, const wxWCharBuffer&);
3518
3519 #endif // wxUSE_UNICODE && defined(HAVE_WOSTREAM)
3520
3521 #endif // wxUSE_STD_IOSTREAM
3522
3523 // ---------------------------------------------------------------------------
3524 // wxCStrData implementation
3525 // ---------------------------------------------------------------------------
3526
3527 inline wxCStrData::wxCStrData(char *buf)
3528 : m_str(new wxString(buf)), m_offset(0), m_owned(true) {}
3529 inline wxCStrData::wxCStrData(wchar_t *buf)
3530 : m_str(new wxString(buf)), m_offset(0), m_owned(true) {}
3531
3532 inline wxCStrData::wxCStrData(const wxCStrData& data)
3533 : m_str(data.m_owned ? new wxString(*data.m_str) : data.m_str),
3534 m_offset(data.m_offset),
3535 m_owned(data.m_owned)
3536 {
3537 }
3538
3539 inline wxCStrData::~wxCStrData()
3540 {
3541 if ( m_owned )
3542 delete wx_const_cast(wxString*, m_str); // cast to silence warnings
3543 }
3544
3545 // simple cases for AsChar() and AsWChar(), the complicated ones are
3546 // in string.cpp
3547 #if wxUSE_UNICODE_WCHAR
3548 inline const wchar_t* wxCStrData::AsWChar() const
3549 {
3550 return m_str->wx_str() + m_offset;
3551 }
3552 #endif // wxUSE_UNICODE_WCHAR
3553
3554 #if !wxUSE_UNICODE
3555 inline const char* wxCStrData::AsChar() const
3556 {
3557 return m_str->wx_str() + m_offset;
3558 }
3559 #endif // !wxUSE_UNICODE
3560
3561 #if wxUSE_UTF8_LOCALE_ONLY
3562 inline const char* wxCStrData::AsChar() const
3563 {
3564 return wxStringOperations::AddToIter(m_str->wx_str(), m_offset);
3565 }
3566 #endif // wxUSE_UTF8_LOCALE_ONLY
3567
3568 inline const wxCharBuffer wxCStrData::AsCharBuf() const
3569 {
3570 #if !wxUSE_UNICODE
3571 return wxCharBuffer::CreateNonOwned(AsChar());
3572 #else
3573 return AsString().mb_str();
3574 #endif
3575 }
3576
3577 inline const wxWCharBuffer wxCStrData::AsWCharBuf() const
3578 {
3579 #if wxUSE_UNICODE_WCHAR
3580 return wxWCharBuffer::CreateNonOwned(AsWChar());
3581 #else
3582 return AsString().wc_str();
3583 #endif
3584 }
3585
3586 inline wxString wxCStrData::AsString() const
3587 {
3588 if ( m_offset == 0 )
3589 return *m_str;
3590 else
3591 return m_str->Mid(m_offset);
3592 }
3593
3594 inline const wxStringCharType *wxCStrData::AsInternal() const
3595 {
3596 #if wxUSE_UNICODE_UTF8
3597 return wxStringOperations::AddToIter(m_str->wx_str(), m_offset);
3598 #else
3599 return m_str->wx_str() + m_offset;
3600 #endif
3601 }
3602
3603 inline wxUniChar wxCStrData::operator*() const
3604 {
3605 if ( m_str->empty() )
3606 return wxUniChar(_T('\0'));
3607 else
3608 return (*m_str)[m_offset];
3609 }
3610
3611 inline wxUniChar wxCStrData::operator[](size_t n) const
3612 {
3613 // NB: we intentionally use operator[] and not at() here because the former
3614 // works for the terminating NUL while the latter does not
3615 return (*m_str)[m_offset + n];
3616 }
3617
3618 // ----------------------------------------------------------------------------
3619 // more wxCStrData operators
3620 // ----------------------------------------------------------------------------
3621
3622 // we need to define those to allow "size_t pos = p - s.c_str()" where p is
3623 // some pointer into the string
3624 inline size_t operator-(const char *p, const wxCStrData& cs)
3625 {
3626 return p - cs.AsChar();
3627 }
3628
3629 inline size_t operator-(const wchar_t *p, const wxCStrData& cs)
3630 {
3631 return p - cs.AsWChar();
3632 }
3633
3634 // ----------------------------------------------------------------------------
3635 // implementation of wx[W]CharBuffer inline methods using wxCStrData
3636 // ----------------------------------------------------------------------------
3637
3638 // FIXME-UTF8: move this to buffer.h
3639 inline wxCharBuffer::wxCharBuffer(const wxCStrData& cstr)
3640 : wxCharTypeBufferBase(cstr.AsCharBuf())
3641 {
3642 }
3643
3644 inline wxWCharBuffer::wxWCharBuffer(const wxCStrData& cstr)
3645 : wxCharTypeBufferBase(cstr.AsWCharBuf())
3646 {
3647 }
3648
3649 #if wxUSE_UNICODE_UTF8
3650 // ----------------------------------------------------------------------------
3651 // implementation of wxStringIteratorNode inline methods
3652 // ----------------------------------------------------------------------------
3653
3654 void wxStringIteratorNode::DoSet(const wxString *str,
3655 wxStringImpl::const_iterator *citer,
3656 wxStringImpl::iterator *iter)
3657 {
3658 m_prev = NULL;
3659 m_iter = iter;
3660 m_citer = citer;
3661 m_str = str;
3662 if ( str )
3663 {
3664 m_next = str->m_iterators.ptr;
3665 wx_const_cast(wxString*, m_str)->m_iterators.ptr = this;
3666 if ( m_next )
3667 m_next->m_prev = this;
3668 }
3669 else
3670 {
3671 m_next = NULL;
3672 }
3673 }
3674
3675 void wxStringIteratorNode::clear()
3676 {
3677 if ( m_next )
3678 m_next->m_prev = m_prev;
3679 if ( m_prev )
3680 m_prev->m_next = m_next;
3681 else if ( m_str ) // first in the list
3682 wx_const_cast(wxString*, m_str)->m_iterators.ptr = m_next;
3683
3684 m_next = m_prev = NULL;
3685 m_citer = NULL;
3686 m_iter = NULL;
3687 m_str = NULL;
3688 }
3689 #endif // wxUSE_UNICODE_UTF8
3690
3691 #if WXWIN_COMPATIBILITY_2_8
3692 // lot of code out there doesn't explicitly include wx/crt.h, but uses
3693 // CRT wrappers that are now declared in wx/wxcrt.h and wx/wxcrtvararg.h,
3694 // so let's include this header now that wxString is defined and it's safe
3695 // to do it:
3696 #include "wx/crt.h"
3697 #endif
3698
3699 #endif // _WX_WXSTRING_H_