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