]> git.saurik.com Git - wxWidgets.git/blame - src/common/string.cpp
tell that there was an error...
[wxWidgets.git] / src / common / string.cpp
CommitLineData
c801d85f
KB
1/////////////////////////////////////////////////////////////////////////////
2// Name: string.cpp
3// Purpose: wxString class
4// Author: Vadim Zeitlin
5// Modified by:
6// Created: 29/01/98
7// RCS-ID: $Id$
8// Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
dd1eaa89 9// Licence: wxWindows license
c801d85f
KB
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
30b21f9a 13 #pragma implementation "string.h"
c801d85f
KB
14#endif
15
16/*
17 * About ref counting:
18 * 1) all empty strings use g_strEmpty, nRefs = -1 (set in Init())
19 * 2) AllocBuffer() sets nRefs to 1, Lock() increments it by one
20 * 3) Unlock() decrements nRefs and frees memory if it goes to 0
21 */
22
23// ===========================================================================
24// headers, declarations, constants
25// ===========================================================================
26
27// For compilers that support precompilation, includes "wx.h".
28#include "wx/wxprec.h"
29
30#ifdef __BORLANDC__
30b21f9a 31 #pragma hdrstop
c801d85f
KB
32#endif
33
34#ifndef WX_PRECOMP
3c024cc2
VZ
35 #include "wx/defs.h"
36 #include "wx/string.h"
37 #include "wx/intl.h"
3096bd2f 38 #include "wx/thread.h"
6b769f3d 39#endif
c801d85f
KB
40
41#include <ctype.h>
42#include <string.h>
43#include <stdlib.h>
44
ce3ed50d 45#ifdef __SALFORDC__
30b21f9a 46 #include <clib.h>
ce3ed50d
JS
47#endif
48
ec2ba3aa 49#if wxUSE_UNICODE
5737d05f 50 #undef wxUSE_EXPERIMENTAL_PRINTF
a59c124d
RR
51 #ifndef wvsnprintf
52 #define wxUSE_EXPERIMENTAL_PRINTF 1
53 #endif
ec2ba3aa
OK
54#endif
55
3168a13f
VZ
56// allocating extra space for each string consumes more memory but speeds up
57// the concatenation operations (nLen is the current string's length)
77ca46e7
VZ
58// NB: EXTRA_ALLOC must be >= 0!
59#define EXTRA_ALLOC (19 - nLen % 16)
3168a13f 60
c801d85f
KB
61// ---------------------------------------------------------------------------
62// static class variables definition
63// ---------------------------------------------------------------------------
64
75ad8feb
DW
65#if defined(__VISAGECPP__) && __IBMCPP__ >= 400
66// must define this static for VA or else you get multiply defined symbols
67// everywhere
68const unsigned int wxSTRING_MAXLEN = UINT_MAX - 100;
69#endif // Visual Age
70
8de2e39c 71#ifdef wxSTD_STRING_COMPATIBILITY
566b84d2 72 const size_t wxString::npos = wxSTRING_MAXLEN;
8de2e39c 73#endif // wxSTD_STRING_COMPATIBILITY
c801d85f 74
3168a13f
VZ
75// ----------------------------------------------------------------------------
76// static data
77// ----------------------------------------------------------------------------
c801d85f 78
3c024cc2
VZ
79// for an empty string, GetStringData() will return this address: this
80// structure has the same layout as wxStringData and it's data() method will
81// return the empty string (dummy pointer)
82static const struct
83{
84 wxStringData data;
2bb67b80 85 wxChar dummy;
223d09f6 86} g_strEmpty = { {-1, 0, 0}, wxT('\0') };
3c024cc2 87
c801d85f 88// empty C style string: points to 'string data' byte of g_strEmpty
e90c1d2a 89extern const wxChar WXDLLEXPORT *wxEmptyString = &g_strEmpty.dummy;
c801d85f 90
89b892a2
VZ
91// ----------------------------------------------------------------------------
92// conditional compilation
93// ----------------------------------------------------------------------------
94
dcf924a3
RR
95#if !defined(__WXSW__) && wxUSE_UNICODE
96 #ifdef wxUSE_EXPERIMENTAL_PRINTF
97 #undef wxUSE_EXPERIMENTAL_PRINTF
98 #endif
99 #define wxUSE_EXPERIMENTAL_PRINTF 1
100#endif
101
89b892a2
VZ
102// we want to find out if the current platform supports vsnprintf()-like
103// function: for Unix this is done with configure, for Windows we test the
104// compiler explicitly.
378b05f7
VZ
105//
106// FIXME currently, this is only for ANSI (!Unicode) strings, so we call this
107// function wxVsnprintfA (A for ANSI), should also find one for Unicode
108// strings in Unicode build
89b892a2 109#ifdef __WXMSW__
012286eb 110 #if defined(__VISUALC__) || (defined(__MINGW32__) && wxUSE_NORLANDER_HEADERS)
378b05f7 111 #define wxVsnprintfA _vsnprintf
89b892a2 112 #endif
03e11df5
GD
113#elif defined(__WXMAC__)
114 #define wxVsnprintfA vsnprintf
89b892a2
VZ
115#else // !Windows
116 #ifdef HAVE_VSNPRINTF
378b05f7 117 #define wxVsnprintfA vsnprintf
89b892a2
VZ
118 #endif
119#endif // Windows/!Windows
120
378b05f7 121#ifndef wxVsnprintfA
89b892a2
VZ
122 // in this case we'll use vsprintf() (which is ANSI and thus should be
123 // always available), but it's unsafe because it doesn't check for buffer
124 // size - so give a warning
378b05f7 125 #define wxVsnprintfA(buf, len, format, arg) vsprintf(buf, format, arg)
566b84d2 126
57493f9f
VZ
127 #if defined(__VISUALC__)
128 #pragma message("Using sprintf() because no snprintf()-like function defined")
03e11df5 129 #elif defined(__GNUG__)
378b05f7 130 #warning "Using sprintf() because no snprintf()-like function defined"
57493f9f 131 #endif //compiler
3f4a0c5b 132#endif // no vsnprintf
89b892a2 133
783fab59 134#if defined(_AIX)
227b5cd7
VZ
135 // AIX has vsnprintf, but there's no prototype in the system headers.
136 extern "C" int vsnprintf(char* str, size_t n, const char* format, va_list ap);
137#endif
138
3168a13f 139// ----------------------------------------------------------------------------
c801d85f 140// global functions
3168a13f 141// ----------------------------------------------------------------------------
c801d85f 142
a533f5c1 143#if defined(wxSTD_STRING_COMPATIBILITY) && wxUSE_STD_IOSTREAM
c801d85f
KB
144
145// MS Visual C++ version 5.0 provides the new STL headers as well as the old
146// iostream ones.
147//
148// ATTN: you can _not_ use both of these in the same program!
a38b83c3 149
dd107c50 150wxSTD istream& operator>>(wxSTD istream& is, wxString& WXUNUSED(str))
c801d85f
KB
151{
152#if 0
153 int w = is.width(0);
154 if ( is.ipfx(0) ) {
3f4a0c5b 155 streambuf *sb = is.rdbuf();
c801d85f
KB
156 str.erase();
157 while ( true ) {
158 int ch = sb->sbumpc ();
159 if ( ch == EOF ) {
3f4a0c5b 160 is.setstate(ios::eofbit);
c801d85f
KB
161 break;
162 }
163 else if ( isspace(ch) ) {
164 sb->sungetc();
165 break;
166 }
dd1eaa89 167
c801d85f
KB
168 str += ch;
169 if ( --w == 1 )
170 break;
171 }
172 }
173
174 is.isfx();
175 if ( str.length() == 0 )
3f4a0c5b 176 is.setstate(ios::failbit);
c801d85f
KB
177#endif
178 return is;
179}
180
dd107c50 181wxSTD ostream& operator<<(wxSTD ostream& os, const wxString& str)
825ba8f0
SB
182{
183 os << str.c_str();
184 return os;
185}
186
c801d85f
KB
187#endif //std::string compatibility
188
a59c124d
RR
189#ifndef wxVsnprintf
190int WXDLLEXPORT wxVsnprintf(wxChar *buf, size_t len,
191 const wxChar *format, va_list argptr)
378b05f7
VZ
192{
193#if wxUSE_UNICODE
378b05f7
VZ
194 wxString s;
195 int iLen = s.PrintfV(format, argptr);
196 if ( iLen != -1 )
197 {
7f017c64
VZ
198 wxStrncpy(buf, s.c_str(), len);
199 buf[len-1] = wxT('\0');
378b05f7
VZ
200 }
201
202 return iLen;
203#else // ANSI
b568d04f
VZ
204 // vsnprintf() will not terminate the string with '\0' if there is not
205 // enough place, but we want the string to always be NUL terminated
206 int rc = wxVsnprintfA(buf, len - 1, format, argptr);
2f02cb89
VZ
207 if ( rc == -1 )
208 {
209 buf[len] = 0;
210 }
b568d04f
VZ
211
212 return rc;
378b05f7
VZ
213#endif // Unicode/ANSI
214}
a59c124d
RR
215#else
216// GNU libc 2.2 only has for wxVsnprintf for Unicode called vswprintf
217// so we imitate wxVsprintf using it.
218int WXDLLEXPORT wxVsprintf(wxChar *buf,
219 const wxChar *format,
220 va_list argptr)
221{
222 return vswprintf( buf, 10000, format, argptr );
223}
224#endif
378b05f7 225
a59c124d
RR
226#ifndef wxSnprintf
227int WXDLLEXPORT wxSnprintf(wxChar *buf, size_t len,
228 const wxChar *format, ...)
378b05f7
VZ
229{
230 va_list argptr;
231 va_start(argptr, format);
232
233 int iLen = wxVsnprintf(buf, len, format, argptr);
234
235 va_end(argptr);
236
237 return iLen;
238}
a59c124d
RR
239#else
240// GNU libc 2.2 only has for wxSnprintf for Unicode called swprintf
241// so we imitate wxSprintf using it.
242int WXDLLEXPORT wxSprintf(wxChar *buf,
243 const wxChar *format,
244 ...) ATTRIBUTE_PRINTF_2
245{
246 va_list argptr;
247 va_start(argptr, format);
248
249 int iLen = swprintf(buf, 10000, format, argptr);
250
251 va_end(argptr);
252
253 return iLen;
254}
255#endif
378b05f7 256
3168a13f
VZ
257// ----------------------------------------------------------------------------
258// private classes
259// ----------------------------------------------------------------------------
260
261// this small class is used to gather statistics for performance tuning
262//#define WXSTRING_STATISTICS
263#ifdef WXSTRING_STATISTICS
264 class Averager
265 {
266 public:
267 Averager(const char *sz) { m_sz = sz; m_nTotal = m_nCount = 0; }
2c3b684c 268 ~Averager()
3168a13f
VZ
269 { printf("wxString: average %s = %f\n", m_sz, ((float)m_nTotal)/m_nCount); }
270
c86f1403 271 void Add(size_t n) { m_nTotal += n; m_nCount++; }
3168a13f
VZ
272
273 private:
c86f1403 274 size_t m_nCount, m_nTotal;
3168a13f
VZ
275 const char *m_sz;
276 } g_averageLength("allocation size"),
277 g_averageSummandLength("summand length"),
278 g_averageConcatHit("hit probability in concat"),
279 g_averageInitialLength("initial string length");
280
281 #define STATISTICS_ADD(av, val) g_average##av.Add(val)
282#else
283 #define STATISTICS_ADD(av, val)
284#endif // WXSTRING_STATISTICS
285
c801d85f
KB
286// ===========================================================================
287// wxString class core
288// ===========================================================================
289
290// ---------------------------------------------------------------------------
291// construction
292// ---------------------------------------------------------------------------
293
c801d85f 294// constructs string of <nLength> copies of character <ch>
2bb67b80 295wxString::wxString(wxChar ch, size_t nLength)
c801d85f
KB
296{
297 Init();
298
299 if ( nLength > 0 ) {
b1801e0e
GD
300 if ( !AllocBuffer(nLength) ) {
301 wxFAIL_MSG( _T("out of memory in wxString::wxString") );
302 return;
303 }
f1da2f03 304
2bb67b80
OK
305#if wxUSE_UNICODE
306 // memset only works on char
307 for (size_t n=0; n<nLength; n++) m_pchData[n] = ch;
308#else
c801d85f 309 memset(m_pchData, ch, nLength);
2bb67b80 310#endif
c801d85f
KB
311 }
312}
313
314// takes nLength elements of psz starting at nPos
2bb67b80 315void wxString::InitWith(const wxChar *psz, size_t nPos, size_t nLength)
c801d85f
KB
316{
317 Init();
318
f6bcfd97
BP
319 // if the length is not given, assume the string to be NUL terminated
320 if ( nLength == wxSTRING_MAXLEN ) {
321 wxASSERT_MSG( nPos <= wxStrlen(psz), _T("index out of bounds") );
c801d85f 322
f6bcfd97
BP
323 nLength = wxStrlen(psz + nPos);
324 }
6c68273f 325
3168a13f
VZ
326 STATISTICS_ADD(InitialLength, nLength);
327
c801d85f
KB
328 if ( nLength > 0 ) {
329 // trailing '\0' is written in AllocBuffer()
b1801e0e
GD
330 if ( !AllocBuffer(nLength) ) {
331 wxFAIL_MSG( _T("out of memory in wxString::InitWith") );
332 return;
333 }
2bb67b80 334 memcpy(m_pchData, psz + nPos, nLength*sizeof(wxChar));
c801d85f
KB
335 }
336}
dd1eaa89 337
8de2e39c 338#ifdef wxSTD_STRING_COMPATIBILITY
c801d85f 339
c801d85f
KB
340// poor man's iterators are "void *" pointers
341wxString::wxString(const void *pStart, const void *pEnd)
342{
2bb67b80
OK
343 InitWith((const wxChar *)pStart, 0,
344 (const wxChar *)pEnd - (const wxChar *)pStart);
c801d85f
KB
345}
346
347#endif //std::string compatibility
348
2bb67b80
OK
349#if wxUSE_UNICODE
350
351// from multibyte string
cf2f341a 352wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength)
2bb67b80
OK
353{
354 // first get necessary size
435595e0 355 size_t nLen = psz ? conv.MB2WC((wchar_t *) NULL, psz, 0) : 0;
2bb67b80
OK
356
357 // nLength is number of *Unicode* characters here!
eea4f86a 358 if ((nLen != (size_t)-1) && (nLen > nLength))
2bb67b80
OK
359 nLen = nLength;
360
361 // empty?
eea4f86a 362 if ( (nLen != 0) && (nLen != (size_t)-1) ) {
b1801e0e
GD
363 if ( !AllocBuffer(nLen) ) {
364 wxFAIL_MSG( _T("out of memory in wxString::wxString") );
365 return;
366 }
2bb67b80
OK
367 conv.MB2WC(m_pchData, psz, nLen);
368 }
369 else {
370 Init();
371 }
372}
373
e90c1d2a 374#else // ANSI
2bb67b80 375
0f3e3e0c 376#if wxUSE_WCHAR_T
c801d85f 377// from wide string
1c2e6a28 378wxString::wxString(const wchar_t *pwz, wxMBConv& conv, size_t nLength)
c801d85f
KB
379{
380 // first get necessary size
1c2e6a28
VS
381 size_t nLen = 0;
382 if (pwz)
383 {
384 if (nLength == wxSTRING_MAXLEN)
385 nLen = conv.WC2MB((char *) NULL, pwz, 0);
386 else
387 nLen = nLength;
388 }
c801d85f
KB
389
390 // empty?
eea4f86a 391 if ( (nLen != 0) && (nLen != (size_t)-1) ) {
b1801e0e
GD
392 if ( !AllocBuffer(nLen) ) {
393 wxFAIL_MSG( _T("out of memory in wxString::wxString") );
394 return;
395 }
f6bcfd97 396 conv.WC2MB(m_pchData, pwz, nLen);
c801d85f
KB
397 }
398 else {
399 Init();
400 }
401}
e90c1d2a 402#endif // wxUSE_WCHAR_T
c801d85f 403
e90c1d2a 404#endif // Unicode/ANSI
2bb67b80 405
c801d85f
KB
406// ---------------------------------------------------------------------------
407// memory allocation
408// ---------------------------------------------------------------------------
409
410// allocates memory needed to store a C string of length nLen
b1801e0e 411bool wxString::AllocBuffer(size_t nLen)
c801d85f 412{
13111b2a
VZ
413 // allocating 0 sized buffer doesn't make sense, all empty strings should
414 // reuse g_strEmpty
415 wxASSERT( nLen > 0 );
416
417 // make sure that we don't overflow
418 wxASSERT( nLen < (INT_MAX / sizeof(wxChar)) -
419 (sizeof(wxStringData) + EXTRA_ALLOC + 1) );
c801d85f 420
3168a13f
VZ
421 STATISTICS_ADD(Length, nLen);
422
c801d85f
KB
423 // allocate memory:
424 // 1) one extra character for '\0' termination
425 // 2) sizeof(wxStringData) for housekeeping info
3168a13f 426 wxStringData* pData = (wxStringData*)
2bb67b80 427 malloc(sizeof(wxStringData) + (nLen + EXTRA_ALLOC + 1)*sizeof(wxChar));
b1801e0e
GD
428
429 if ( pData == NULL ) {
430 // allocation failures are handled by the caller
431 return FALSE;
432 }
433
c801d85f 434 pData->nRefs = 1;
c801d85f 435 pData->nDataLength = nLen;
3168a13f 436 pData->nAllocLength = nLen + EXTRA_ALLOC;
c801d85f 437 m_pchData = pData->data(); // data starts after wxStringData
223d09f6 438 m_pchData[nLen] = wxT('\0');
b1801e0e 439 return TRUE;
c801d85f
KB
440}
441
c801d85f 442// must be called before changing this string
b1801e0e 443bool wxString::CopyBeforeWrite()
c801d85f
KB
444{
445 wxStringData* pData = GetStringData();
446
447 if ( pData->IsShared() ) {
448 pData->Unlock(); // memory not freed because shared
c86f1403 449 size_t nLen = pData->nDataLength;
b1801e0e
GD
450 if ( !AllocBuffer(nLen) ) {
451 // allocation failures are handled by the caller
452 return FALSE;
453 }
2bb67b80 454 memcpy(m_pchData, pData->data(), nLen*sizeof(wxChar));
c801d85f
KB
455 }
456
3bbb630a 457 wxASSERT( !GetStringData()->IsShared() ); // we must be the only owner
b1801e0e
GD
458
459 return TRUE;
c801d85f
KB
460}
461
462// must be called before replacing contents of this string
b1801e0e 463bool wxString::AllocBeforeWrite(size_t nLen)
c801d85f
KB
464{
465 wxASSERT( nLen != 0 ); // doesn't make any sense
466
467 // must not share string and must have enough space
3168a13f 468 wxStringData* pData = GetStringData();
fbf0c83d 469 if ( pData->IsShared() || pData->IsEmpty() ) {
c801d85f
KB
470 // can't work with old buffer, get new one
471 pData->Unlock();
b1801e0e
GD
472 if ( !AllocBuffer(nLen) ) {
473 // allocation failures are handled by the caller
474 return FALSE;
475 }
c801d85f 476 }
471aebdd 477 else {
fbf0c83d
VZ
478 if ( nLen > pData->nAllocLength ) {
479 // realloc the buffer instead of calling malloc() again, this is more
480 // efficient
481 STATISTICS_ADD(Length, nLen);
482
483 nLen += EXTRA_ALLOC;
484
fbf0c83d
VZ
485 pData = (wxStringData*)
486 realloc(pData, sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar));
b1801e0e
GD
487
488 if ( pData == NULL ) {
489 // allocation failures are handled by the caller
490 // keep previous data since reallocation failed
491 return FALSE;
fbf0c83d
VZ
492 }
493
494 pData->nAllocLength = nLen;
495 m_pchData = pData->data();
496 }
497
498 // now we have enough space, just update the string length
471aebdd
VZ
499 pData->nDataLength = nLen;
500 }
c801d85f 501
f1da2f03 502 wxASSERT( !GetStringData()->IsShared() ); // we must be the only owner
b1801e0e
GD
503
504 return TRUE;
c801d85f
KB
505}
506
dd1eaa89 507// allocate enough memory for nLen characters
b1801e0e 508bool wxString::Alloc(size_t nLen)
dd1eaa89
VZ
509{
510 wxStringData *pData = GetStringData();
511 if ( pData->nAllocLength <= nLen ) {
9fbd8b8d
VZ
512 if ( pData->IsEmpty() ) {
513 nLen += EXTRA_ALLOC;
514
515 wxStringData* pData = (wxStringData*)
b1801e0e
GD
516 malloc(sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar));
517
518 if ( pData == NULL ) {
519 // allocation failure handled by caller
520 return FALSE;
521 }
522
9fbd8b8d
VZ
523 pData->nRefs = 1;
524 pData->nDataLength = 0;
525 pData->nAllocLength = nLen;
526 m_pchData = pData->data(); // data starts after wxStringData
223d09f6 527 m_pchData[0u] = wxT('\0');
9fbd8b8d 528 }
3168a13f
VZ
529 else if ( pData->IsShared() ) {
530 pData->Unlock(); // memory not freed because shared
c86f1403 531 size_t nOldLen = pData->nDataLength;
b1801e0e
GD
532 if ( !AllocBuffer(nLen) ) {
533 // allocation failure handled by caller
534 return FALSE;
535 }
2bb67b80 536 memcpy(m_pchData, pData->data(), nOldLen*sizeof(wxChar));
3168a13f 537 }
dd1eaa89 538 else {
3168a13f
VZ
539 nLen += EXTRA_ALLOC;
540
b1801e0e 541 pData = (wxStringData *)
2bb67b80 542 realloc(pData, sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar));
3168a13f 543
b1801e0e
GD
544 if ( pData == NULL ) {
545 // allocation failure handled by caller
546 // keep previous data since reallocation failed
547 return FALSE;
dd1eaa89 548 }
3168a13f
VZ
549
550 // it's not important if the pointer changed or not (the check for this
551 // is not faster than assigning to m_pchData in all cases)
b1801e0e
GD
552 pData->nAllocLength = nLen;
553 m_pchData = pData->data();
dd1eaa89
VZ
554 }
555 }
556 //else: we've already got enough
b1801e0e 557 return TRUE;
dd1eaa89
VZ
558}
559
560// shrink to minimal size (releasing extra memory)
b1801e0e 561bool wxString::Shrink()
dd1eaa89
VZ
562{
563 wxStringData *pData = GetStringData();
3bbb630a 564
337a0010
VZ
565 size_t nLen = pData->nDataLength;
566 void *p = realloc(pData, sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar));
567
b1801e0e
GD
568 if ( p == NULL) {
569 wxFAIL_MSG( _T("out of memory reallocating wxString data") );
570 // keep previous data since reallocation failed
571 return FALSE;
572 }
337a0010
VZ
573
574 if ( p != pData )
575 {
576 // contrary to what one might believe, some realloc() implementation do
577 // move the memory block even when its size is reduced
578 pData = (wxStringData *)p;
3bbb630a 579
337a0010
VZ
580 m_pchData = pData->data();
581 }
fbf0c83d 582
337a0010 583 pData->nAllocLength = nLen;
b1801e0e
GD
584
585 return TRUE;
dd1eaa89
VZ
586}
587
c801d85f 588// get the pointer to writable buffer of (at least) nLen bytes
2bb67b80 589wxChar *wxString::GetWriteBuf(size_t nLen)
c801d85f 590{
b1801e0e
GD
591 if ( !AllocBeforeWrite(nLen) ) {
592 // allocation failure handled by caller
593 return NULL;
594 }
097c080b
VZ
595
596 wxASSERT( GetStringData()->nRefs == 1 );
597 GetStringData()->Validate(FALSE);
598
c801d85f
KB
599 return m_pchData;
600}
601
097c080b
VZ
602// put string back in a reasonable state after GetWriteBuf
603void wxString::UngetWriteBuf()
604{
2bb67b80 605 GetStringData()->nDataLength = wxStrlen(m_pchData);
097c080b
VZ
606 GetStringData()->Validate(TRUE);
607}
608
8f06a017
RD
609void wxString::UngetWriteBuf(size_t nLen)
610{
611 GetStringData()->nDataLength = nLen;
612 GetStringData()->Validate(TRUE);
613}
614
c801d85f
KB
615// ---------------------------------------------------------------------------
616// data access
617// ---------------------------------------------------------------------------
618
619// all functions are inline in string.h
620
621// ---------------------------------------------------------------------------
622// assignment operators
623// ---------------------------------------------------------------------------
624
dd1eaa89 625// helper function: does real copy
b1801e0e 626bool wxString::AssignCopy(size_t nSrcLen, const wxChar *pszSrcData)
c801d85f
KB
627{
628 if ( nSrcLen == 0 ) {
629 Reinit();
630 }
631 else {
b1801e0e
GD
632 if ( !AllocBeforeWrite(nSrcLen) ) {
633 // allocation failure handled by caller
634 return FALSE;
635 }
2bb67b80 636 memcpy(m_pchData, pszSrcData, nSrcLen*sizeof(wxChar));
c801d85f 637 GetStringData()->nDataLength = nSrcLen;
223d09f6 638 m_pchData[nSrcLen] = wxT('\0');
c801d85f 639 }
b1801e0e 640 return TRUE;
c801d85f
KB
641}
642
643// assigns one string to another
644wxString& wxString::operator=(const wxString& stringSrc)
645{
097c080b
VZ
646 wxASSERT( stringSrc.GetStringData()->IsValid() );
647
c801d85f
KB
648 // don't copy string over itself
649 if ( m_pchData != stringSrc.m_pchData ) {
650 if ( stringSrc.GetStringData()->IsEmpty() ) {
651 Reinit();
652 }
653 else {
654 // adjust references
655 GetStringData()->Unlock();
656 m_pchData = stringSrc.m_pchData;
657 GetStringData()->Lock();
658 }
659 }
660
661 return *this;
662}
663
664// assigns a single character
2bb67b80 665wxString& wxString::operator=(wxChar ch)
c801d85f 666{
b1801e0e
GD
667 if ( !AssignCopy(1, &ch) ) {
668 wxFAIL_MSG( _T("out of memory in wxString::operator=(wxChar)") );
669 }
c801d85f
KB
670 return *this;
671}
672
a3291804 673
c801d85f 674// assigns C string
2bb67b80 675wxString& wxString::operator=(const wxChar *psz)
c801d85f 676{
b1801e0e
GD
677 if ( !AssignCopy(wxStrlen(psz), psz) ) {
678 wxFAIL_MSG( _T("out of memory in wxString::operator=(const wxChar *)") );
679 }
c801d85f
KB
680 return *this;
681}
682
2bb67b80
OK
683#if !wxUSE_UNICODE
684
c801d85f
KB
685// same as 'signed char' variant
686wxString& wxString::operator=(const unsigned char* psz)
687{
688 *this = (const char *)psz;
689 return *this;
690}
691
0f3e3e0c 692#if wxUSE_WCHAR_T
c801d85f
KB
693wxString& wxString::operator=(const wchar_t *pwz)
694{
695 wxString str(pwz);
696 *this = str;
697 return *this;
698}
0f3e3e0c 699#endif
c801d85f 700
2bb67b80
OK
701#endif
702
c801d85f
KB
703// ---------------------------------------------------------------------------
704// string concatenation
705// ---------------------------------------------------------------------------
706
c801d85f 707// add something to this string
b1801e0e 708bool wxString::ConcatSelf(int nSrcLen, const wxChar *pszSrcData)
c801d85f 709{
3168a13f 710 STATISTICS_ADD(SummandLength, nSrcLen);
c801d85f 711
05488905
VZ
712 // concatenating an empty string is a NOP
713 if ( nSrcLen > 0 ) {
714 wxStringData *pData = GetStringData();
715 size_t nLen = pData->nDataLength;
716 size_t nNewLen = nLen + nSrcLen;
c801d85f 717
05488905
VZ
718 // alloc new buffer if current is too small
719 if ( pData->IsShared() ) {
720 STATISTICS_ADD(ConcatHit, 0);
3168a13f 721
05488905
VZ
722 // we have to allocate another buffer
723 wxStringData* pOldData = GetStringData();
b1801e0e
GD
724 if ( !AllocBuffer(nNewLen) ) {
725 // allocation failure handled by caller
726 return FALSE;
727 }
2bb67b80 728 memcpy(m_pchData, pOldData->data(), nLen*sizeof(wxChar));
05488905
VZ
729 pOldData->Unlock();
730 }
731 else if ( nNewLen > pData->nAllocLength ) {
732 STATISTICS_ADD(ConcatHit, 0);
3168a13f 733
05488905 734 // we have to grow the buffer
b1801e0e
GD
735 if ( !Alloc(nNewLen) ) {
736 // allocation failure handled by caller
737 return FALSE;
738 }
05488905
VZ
739 }
740 else {
741 STATISTICS_ADD(ConcatHit, 1);
3168a13f 742
05488905
VZ
743 // the buffer is already big enough
744 }
3168a13f 745
05488905
VZ
746 // should be enough space
747 wxASSERT( nNewLen <= GetStringData()->nAllocLength );
3168a13f 748
05488905 749 // fast concatenation - all is done in our buffer
2bb67b80 750 memcpy(m_pchData + nLen, pszSrcData, nSrcLen*sizeof(wxChar));
3168a13f 751
223d09f6 752 m_pchData[nNewLen] = wxT('\0'); // put terminating '\0'
05488905
VZ
753 GetStringData()->nDataLength = nNewLen; // and fix the length
754 }
755 //else: the string to append was empty
b1801e0e 756 return TRUE;
c801d85f
KB
757}
758
759/*
c801d85f
KB
760 * concatenation functions come in 5 flavours:
761 * string + string
762 * char + string and string + char
763 * C str + string and string + C str
764 */
765
b1801e0e 766wxString operator+(const wxString& str1, const wxString& str2)
c801d85f 767{
b1801e0e
GD
768 wxASSERT( str1.GetStringData()->IsValid() );
769 wxASSERT( str2.GetStringData()->IsValid() );
097c080b 770
b1801e0e
GD
771 wxString s = str1;
772 s += str2;
3168a13f 773
c801d85f
KB
774 return s;
775}
776
b1801e0e 777wxString operator+(const wxString& str, wxChar ch)
c801d85f 778{
b1801e0e 779 wxASSERT( str.GetStringData()->IsValid() );
3168a13f 780
b1801e0e 781 wxString s = str;
3168a13f 782 s += ch;
097c080b 783
c801d85f
KB
784 return s;
785}
786
b1801e0e 787wxString operator+(wxChar ch, const wxString& str)
c801d85f 788{
b1801e0e 789 wxASSERT( str.GetStringData()->IsValid() );
097c080b 790
3168a13f 791 wxString s = ch;
b1801e0e 792 s += str;
3168a13f 793
c801d85f
KB
794 return s;
795}
796
b1801e0e 797wxString operator+(const wxString& str, const wxChar *psz)
c801d85f 798{
b1801e0e 799 wxASSERT( str.GetStringData()->IsValid() );
097c080b 800
c801d85f 801 wxString s;
b1801e0e
GD
802 if ( !s.Alloc(wxStrlen(psz) + str.Len()) ) {
803 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
804 }
805 s = str;
3168a13f
VZ
806 s += psz;
807
c801d85f
KB
808 return s;
809}
810
b1801e0e 811wxString operator+(const wxChar *psz, const wxString& str)
c801d85f 812{
b1801e0e 813 wxASSERT( str.GetStringData()->IsValid() );
097c080b 814
c801d85f 815 wxString s;
b1801e0e
GD
816 if ( !s.Alloc(wxStrlen(psz) + str.Len()) ) {
817 wxFAIL_MSG( _T("out of memory in wxString::operator+") );
818 }
3168a13f 819 s = psz;
b1801e0e 820 s += str;
3168a13f 821
c801d85f
KB
822 return s;
823}
824
825// ===========================================================================
826// other common string functions
827// ===========================================================================
828
829// ---------------------------------------------------------------------------
830// simple sub-string extraction
831// ---------------------------------------------------------------------------
832
833// helper function: clone the data attached to this string
b1801e0e 834bool wxString::AllocCopy(wxString& dest, int nCopyLen, int nCopyIndex) const
c801d85f 835{
3168a13f 836 if ( nCopyLen == 0 ) {
c801d85f
KB
837 dest.Init();
838 }
3168a13f 839 else {
b1801e0e
GD
840 if ( !dest.AllocBuffer(nCopyLen) ) {
841 // allocation failure handled by caller
842 return FALSE;
843 }
2bb67b80 844 memcpy(dest.m_pchData, m_pchData + nCopyIndex, nCopyLen*sizeof(wxChar));
c801d85f 845 }
b1801e0e 846 return TRUE;
c801d85f
KB
847}
848
849// extract string of length nCount starting at nFirst
c801d85f
KB
850wxString wxString::Mid(size_t nFirst, size_t nCount) const
851{
30d9011f
VZ
852 wxStringData *pData = GetStringData();
853 size_t nLen = pData->nDataLength;
854
566b84d2
VZ
855 // default value of nCount is wxSTRING_MAXLEN and means "till the end"
856 if ( nCount == wxSTRING_MAXLEN )
30d9011f
VZ
857 {
858 nCount = nLen - nFirst;
859 }
860
c801d85f 861 // out-of-bounds requests return sensible things
30d9011f
VZ
862 if ( nFirst + nCount > nLen )
863 {
864 nCount = nLen - nFirst;
865 }
c801d85f 866
30d9011f
VZ
867 if ( nFirst > nLen )
868 {
869 // AllocCopy() will return empty string
c801d85f 870 nCount = 0;
30d9011f 871 }
c801d85f
KB
872
873 wxString dest;
b1801e0e
GD
874 if ( !AllocCopy(dest, nCount, nFirst) ) {
875 wxFAIL_MSG( _T("out of memory in wxString::Mid") );
876 }
30d9011f 877
c801d85f
KB
878 return dest;
879}
880
f6bcfd97
BP
881// check that the tring starts with prefix and return the rest of the string
882// in the provided pointer if it is not NULL, otherwise return FALSE
883bool wxString::StartsWith(const wxChar *prefix, wxString *rest) const
884{
885 wxASSERT_MSG( prefix, _T("invalid parameter in wxString::StartsWith") );
886
887 // first check if the beginning of the string matches the prefix: note
888 // that we don't have to check that we don't run out of this string as
889 // when we reach the terminating NUL, either prefix string ends too (and
890 // then it's ok) or we break out of the loop because there is no match
891 const wxChar *p = c_str();
892 while ( *prefix )
893 {
894 if ( *prefix++ != *p++ )
895 {
896 // no match
897 return FALSE;
898 }
899 }
900
901 if ( rest )
902 {
903 // put the rest of the string into provided pointer
904 *rest = p;
905 }
906
907 return TRUE;
908}
909
c801d85f
KB
910// extract nCount last (rightmost) characters
911wxString wxString::Right(size_t nCount) const
912{
913 if ( nCount > (size_t)GetStringData()->nDataLength )
914 nCount = GetStringData()->nDataLength;
915
916 wxString dest;
b1801e0e
GD
917 if ( !AllocCopy(dest, nCount, GetStringData()->nDataLength - nCount) ) {
918 wxFAIL_MSG( _T("out of memory in wxString::Right") );
919 }
c801d85f
KB
920 return dest;
921}
922
923// get all characters after the last occurence of ch
924// (returns the whole string if ch not found)
2bb67b80 925wxString wxString::AfterLast(wxChar ch) const
c801d85f
KB
926{
927 wxString str;
928 int iPos = Find(ch, TRUE);
3c67202d 929 if ( iPos == wxNOT_FOUND )
c801d85f
KB
930 str = *this;
931 else
c8cfb486 932 str = c_str() + iPos + 1;
c801d85f
KB
933
934 return str;
935}
936
937// extract nCount first (leftmost) characters
938wxString wxString::Left(size_t nCount) const
939{
940 if ( nCount > (size_t)GetStringData()->nDataLength )
941 nCount = GetStringData()->nDataLength;
942
943 wxString dest;
b1801e0e
GD
944 if ( !AllocCopy(dest, nCount, 0) ) {
945 wxFAIL_MSG( _T("out of memory in wxString::Left") );
946 }
c801d85f
KB
947 return dest;
948}
949
950// get all characters before the first occurence of ch
951// (returns the whole string if ch not found)
2bb67b80 952wxString wxString::BeforeFirst(wxChar ch) const
c801d85f
KB
953{
954 wxString str;
223d09f6 955 for ( const wxChar *pc = m_pchData; *pc != wxT('\0') && *pc != ch; pc++ )
c801d85f
KB
956 str += *pc;
957
958 return str;
959}
960
961/// get all characters before the last occurence of ch
962/// (returns empty string if ch not found)
2bb67b80 963wxString wxString::BeforeLast(wxChar ch) const
c801d85f
KB
964{
965 wxString str;
966 int iPos = Find(ch, TRUE);
3c67202d 967 if ( iPos != wxNOT_FOUND && iPos != 0 )
d1c9bbf6 968 str = wxString(c_str(), iPos);
c801d85f
KB
969
970 return str;
971}
972
973/// get all characters after the first occurence of ch
974/// (returns empty string if ch not found)
2bb67b80 975wxString wxString::AfterFirst(wxChar ch) const
c801d85f
KB
976{
977 wxString str;
978 int iPos = Find(ch);
3c67202d 979 if ( iPos != wxNOT_FOUND )
c801d85f
KB
980 str = c_str() + iPos + 1;
981
982 return str;
983}
984
985// replace first (or all) occurences of some substring with another one
2bb67b80 986size_t wxString::Replace(const wxChar *szOld, const wxChar *szNew, bool bReplaceAll)
c801d85f 987{
c86f1403 988 size_t uiCount = 0; // count of replacements made
c801d85f 989
2bb67b80 990 size_t uiOldLen = wxStrlen(szOld);
c801d85f
KB
991
992 wxString strTemp;
2bb67b80
OK
993 const wxChar *pCurrent = m_pchData;
994 const wxChar *pSubstr;
223d09f6 995 while ( *pCurrent != wxT('\0') ) {
2bb67b80 996 pSubstr = wxStrstr(pCurrent, szOld);
c801d85f
KB
997 if ( pSubstr == NULL ) {
998 // strTemp is unused if no replacements were made, so avoid the copy
999 if ( uiCount == 0 )
1000 return 0;
1001
1002 strTemp += pCurrent; // copy the rest
1003 break; // exit the loop
1004 }
1005 else {
1006 // take chars before match
b1801e0e
GD
1007 if ( !strTemp.ConcatSelf(pSubstr - pCurrent, pCurrent) ) {
1008 wxFAIL_MSG( _T("out of memory in wxString::Replace") );
1009 return 0;
1010 }
c801d85f
KB
1011 strTemp += szNew;
1012 pCurrent = pSubstr + uiOldLen; // restart after match
1013
1014 uiCount++;
1015
1016 // stop now?
1017 if ( !bReplaceAll ) {
1018 strTemp += pCurrent; // copy the rest
1019 break; // exit the loop
1020 }
1021 }
1022 }
1023
1024 // only done if there were replacements, otherwise would have returned above
1025 *this = strTemp;
1026
1027 return uiCount;
1028}
1029
1030bool wxString::IsAscii() const
1031{
2bb67b80 1032 const wxChar *s = (const wxChar*) *this;
c801d85f
KB
1033 while(*s){
1034 if(!isascii(*s)) return(FALSE);
1035 s++;
1036 }
1037 return(TRUE);
1038}
dd1eaa89 1039
c801d85f
KB
1040bool wxString::IsWord() const
1041{
2bb67b80 1042 const wxChar *s = (const wxChar*) *this;
c801d85f 1043 while(*s){
2bb67b80 1044 if(!wxIsalpha(*s)) return(FALSE);
c801d85f
KB
1045 s++;
1046 }
1047 return(TRUE);
1048}
dd1eaa89 1049
c801d85f
KB
1050bool wxString::IsNumber() const
1051{
2bb67b80 1052 const wxChar *s = (const wxChar*) *this;
2f74ed28
GT
1053 if (wxStrlen(s))
1054 if ((s[0] == '-') || (s[0] == '+')) s++;
c801d85f 1055 while(*s){
2bb67b80 1056 if(!wxIsdigit(*s)) return(FALSE);
c801d85f
KB
1057 s++;
1058 }
1059 return(TRUE);
1060}
1061
c801d85f
KB
1062wxString wxString::Strip(stripType w) const
1063{
1064 wxString s = *this;
1065 if ( w & leading ) s.Trim(FALSE);
1066 if ( w & trailing ) s.Trim(TRUE);
1067 return s;
1068}
1069
c801d85f
KB
1070// ---------------------------------------------------------------------------
1071// case conversion
1072// ---------------------------------------------------------------------------
1073
1074wxString& wxString::MakeUpper()
1075{
b1801e0e
GD
1076 if ( !CopyBeforeWrite() ) {
1077 wxFAIL_MSG( _T("out of memory in wxString::MakeUpper") );
1078 return *this;
1079 }
1080
2bb67b80
OK
1081 for ( wxChar *p = m_pchData; *p; p++ )
1082 *p = (wxChar)wxToupper(*p);
c801d85f
KB
1083
1084 return *this;
1085}
1086
1087wxString& wxString::MakeLower()
1088{
b1801e0e
GD
1089 if ( !CopyBeforeWrite() ) {
1090 wxFAIL_MSG( _T("out of memory in wxString::MakeLower") );
1091 return *this;
1092 }
dd1eaa89 1093
2bb67b80
OK
1094 for ( wxChar *p = m_pchData; *p; p++ )
1095 *p = (wxChar)wxTolower(*p);
c801d85f
KB
1096
1097 return *this;
1098}
1099
1100// ---------------------------------------------------------------------------
1101// trimming and padding
1102// ---------------------------------------------------------------------------
1103
576c608d
VZ
1104// some compilers (VC++ 6.0 not to name them) return TRUE for a call to
1105