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