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