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