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