1 /////////////////////////////////////////////////////////////////////////////
3 // Purpose: wxString class
4 // Author: Vadim Zeitlin
8 // Copyright: (c) 1998 Vadim Zeitlin <zeitlin@dptmaths.ens-cachan.fr>
9 // Licence: wxWindows license
10 /////////////////////////////////////////////////////////////////////////////
13 #pragma implementation "string.h"
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
23 // ===========================================================================
24 // headers, declarations, constants
25 // ===========================================================================
27 // For compilers that support precompilation, includes "wx.h".
28 #include "wx/wxprec.h"
36 #include "wx/string.h"
43 #ifdef WXSTRING_IS_WXOBJECT
44 IMPLEMENT_DYNAMIC_CLASS(wxString
, wxObject
)
45 #endif //WXSTRING_IS_WXOBJECT
47 // ---------------------------------------------------------------------------
48 // static class variables definition
49 // ---------------------------------------------------------------------------
51 #ifdef STD_STRING_COMPATIBILITY
52 const size_t wxString::npos
= STRING_MAXLEN
;
55 // ===========================================================================
56 // static class data, special inlines
57 // ===========================================================================
59 // for an empty string, GetStringData() will return this address
60 static int g_strEmpty
[] = { -1, // ref count (locked)
62 0, // allocated memory
64 // empty C style string: points to 'string data' byte of g_strEmpty
65 extern const char *g_szNul
= (const char *)(&g_strEmpty
[3]);
67 // ===========================================================================
69 // ===========================================================================
71 #ifdef STD_STRING_COMPATIBILITY
73 // MS Visual C++ version 5.0 provides the new STL headers as well as the old
76 // ATTN: you can _not_ use both of these in the same program!
79 #define NAMESPACE std::
85 NAMESPACE istream
& operator>>(NAMESPACE istream
& is
, wxString
& WXUNUSED(str
))
90 NAMESPACE streambuf
*sb
= is
.rdbuf();
93 int ch
= sb
->sbumpc ();
95 is
.setstate(NAMESPACE
ios::eofbit
);
98 else if ( isspace(ch
) ) {
110 if ( str
.length() == 0 )
111 is
.setstate(NAMESPACE
ios::failbit
);
116 #endif //std::string compatibility
118 // ===========================================================================
119 // wxString class core
120 // ===========================================================================
122 // ---------------------------------------------------------------------------
124 // ---------------------------------------------------------------------------
126 // construct an empty string
133 wxString::wxString(const wxString
& stringSrc
)
135 wxASSERT( stringSrc
.GetStringData()->IsValid() );
137 if ( stringSrc
.IsEmpty() ) {
138 // nothing to do for an empty string
142 m_pchData
= stringSrc
.m_pchData
; // share same data
143 GetStringData()->Lock(); // => one more copy
147 // constructs string of <nLength> copies of character <ch>
148 wxString::wxString(char ch
, size_t nLength
)
153 AllocBuffer(nLength
);
155 wxASSERT( sizeof(char) == 1 ); // can't use memset if not
157 memset(m_pchData
, ch
, nLength
);
161 // takes nLength elements of psz starting at nPos
162 void wxString::InitWith(const char *psz
, size_t nPos
, size_t nLength
)
166 wxASSERT( nPos
<= Strlen(psz
) );
168 if ( nLength
== STRING_MAXLEN
)
169 nLength
= Strlen(psz
+ nPos
);
172 // trailing '\0' is written in AllocBuffer()
173 AllocBuffer(nLength
);
174 memcpy(m_pchData
, psz
+ nPos
, nLength
*sizeof(char));
178 // take first nLength characters of C string psz
179 // (default value of STRING_MAXLEN means take all the string)
180 wxString::wxString(const char *psz
, size_t nLength
)
182 InitWith(psz
, 0, nLength
);
185 // the same as previous constructor, but for compilers using unsigned char
186 wxString::wxString(const unsigned char* psz
, size_t nLength
)
188 InitWith((const char *)psz
, 0, nLength
);
191 #ifdef STD_STRING_COMPATIBILITY
193 // ctor from a substring
194 wxString::wxString(const wxString
& str
, size_t nPos
, size_t nLen
)
196 wxASSERT( str
.GetStringData()->IsValid() );
198 InitWith(str
.c_str(), nPos
, nLen
== npos
? 0 : nLen
);
201 // poor man's iterators are "void *" pointers
202 wxString::wxString(const void *pStart
, const void *pEnd
)
204 InitWith((const char *)pStart
, 0,
205 (const char *)pEnd
- (const char *)pStart
);
208 #endif //std::string compatibility
211 wxString::wxString(const wchar_t *pwz
)
213 // first get necessary size
214 size_t nLen
= wcstombs(NULL
, pwz
, 0);
219 wcstombs(m_pchData
, pwz
, nLen
);
226 // ---------------------------------------------------------------------------
228 // ---------------------------------------------------------------------------
230 // allocates memory needed to store a C string of length nLen
231 void wxString::AllocBuffer(size_t nLen
)
233 wxASSERT( nLen
> 0 ); //
234 wxASSERT( nLen
<= INT_MAX
-1 ); // max size (enough room for 1 extra)
237 // 1) one extra character for '\0' termination
238 // 2) sizeof(wxStringData) for housekeeping info
239 wxStringData
* pData
= (wxStringData
*)malloc(sizeof(wxStringData
) +
240 (nLen
+ 1)*sizeof(char));
242 pData
->data()[nLen
] = '\0';
243 pData
->nDataLength
= nLen
;
244 pData
->nAllocLength
= nLen
;
245 m_pchData
= pData
->data(); // data starts after wxStringData
248 // must be called before changing this string
249 void wxString::CopyBeforeWrite()
251 wxStringData
* pData
= GetStringData();
253 if ( pData
->IsShared() ) {
254 pData
->Unlock(); // memory not freed because shared
255 AllocBuffer(pData
->nDataLength
);
256 memcpy(m_pchData
, pData
->data(), (pData
->nDataLength
+ 1)*sizeof(char));
259 wxASSERT( !pData
->IsShared() ); // we must be the only owner
262 // must be called before replacing contents of this string
263 void wxString::AllocBeforeWrite(size_t nLen
)
265 wxASSERT( nLen
!= 0 ); // doesn't make any sense
267 // must not share string and must have enough space
268 register wxStringData
* pData
= GetStringData();
269 if ( pData
->IsShared() || (nLen
> pData
->nAllocLength
) ) {
270 // can't work with old buffer, get new one
275 wxASSERT( !GetStringData()->IsShared() ); // we must be the only owner
278 // allocate enough memory for nLen characters
279 void wxString::Alloc(uint nLen
)
281 wxStringData
*pData
= GetStringData();
282 if ( pData
->nAllocLength
<= nLen
) {
283 if ( pData
->IsEmpty() )
286 wxStringData
*p
= (wxStringData
*)
287 realloc(pData
, sizeof(wxStringData
) + (nLen
+ 1)*sizeof(char));
288 if ( p
!= NULL
&& p
!= pData
) {
289 // the call succeeded but the pointer changed
294 p
->nAllocLength
= nLen
;
295 m_pchData
= p
->data();
297 //else: do nothing: either the call failed or the pointer is unchanged
300 //else: we've already got enough
303 // shrink to minimal size (releasing extra memory)
304 void wxString::Shrink()
306 wxStringData
*pData
= GetStringData();
307 void *p
= realloc(pData
, sizeof(wxStringData
) +
308 (pData
->nDataLength
+ 1)*sizeof(char));
309 if ( p
== NULL
) // huh? can't unallocate memory? unlikely but possible.
311 wxASSERT( p
== pData
); // we're decrementing the size - block shouldn't move!
314 // get the pointer to writable buffer of (at least) nLen bytes
315 char *wxString::GetWriteBuf(uint nLen
)
317 AllocBeforeWrite(nLen
);
319 wxASSERT( GetStringData()->nRefs
== 1 );
320 GetStringData()->Validate(FALSE
);
325 // put string back in a reasonable state after GetWriteBuf
326 void wxString::UngetWriteBuf()
328 GetStringData()->nDataLength
= strlen(m_pchData
);
329 GetStringData()->Validate(TRUE
);
332 // dtor frees memory if no other strings use it
333 wxString::~wxString()
335 GetStringData()->Unlock();
338 // ---------------------------------------------------------------------------
340 // ---------------------------------------------------------------------------
342 // all functions are inline in string.h
344 // ---------------------------------------------------------------------------
345 // assignment operators
346 // ---------------------------------------------------------------------------
348 // helper function: does real copy
349 void wxString::AssignCopy(size_t nSrcLen
, const char *pszSrcData
)
351 if ( nSrcLen
== 0 ) {
355 AllocBeforeWrite(nSrcLen
);
356 memcpy(m_pchData
, pszSrcData
, nSrcLen
*sizeof(char));
357 GetStringData()->nDataLength
= nSrcLen
;
358 m_pchData
[nSrcLen
] = '\0';
362 // assigns one string to another
363 wxString
& wxString::operator=(const wxString
& stringSrc
)
365 wxASSERT( stringSrc
.GetStringData()->IsValid() );
367 // don't copy string over itself
368 if ( m_pchData
!= stringSrc
.m_pchData
) {
369 if ( stringSrc
.GetStringData()->IsEmpty() ) {
374 GetStringData()->Unlock();
375 m_pchData
= stringSrc
.m_pchData
;
376 GetStringData()->Lock();
383 // assigns a single character
384 wxString
& wxString::operator=(char ch
)
391 wxString
& wxString::operator=(const char *psz
)
393 AssignCopy(Strlen(psz
), psz
);
397 // same as 'signed char' variant
398 wxString
& wxString::operator=(const unsigned char* psz
)
400 *this = (const char *)psz
;
404 wxString
& wxString::operator=(const wchar_t *pwz
)
411 // ---------------------------------------------------------------------------
412 // string concatenation
413 // ---------------------------------------------------------------------------
415 // concatenate two sources
416 // NB: assume that 'this' is a new wxString object
417 void wxString::ConcatCopy(int nSrc1Len
, const char *pszSrc1Data
,
418 int nSrc2Len
, const char *pszSrc2Data
)
420 int nNewLen
= nSrc1Len
+ nSrc2Len
;
423 AllocBuffer(nNewLen
);
424 memcpy(m_pchData
, pszSrc1Data
, nSrc1Len
*sizeof(char));
425 memcpy(m_pchData
+ nSrc1Len
, pszSrc2Data
, nSrc2Len
*sizeof(char));
429 // add something to this string
430 void wxString::ConcatSelf(int nSrcLen
, const char *pszSrcData
)
432 // concatenating an empty string is a NOP
433 if ( nSrcLen
!= 0 ) {
434 register wxStringData
*pData
= GetStringData();
436 // alloc new buffer if current is too small
437 if ( pData
->IsShared() ||
438 pData
->nDataLength
+ nSrcLen
> pData
->nAllocLength
) {
439 // we have to grow the buffer, use the ConcatCopy routine
440 // (which will allocate memory)
441 wxStringData
* pOldData
= GetStringData();
442 ConcatCopy(pOldData
->nDataLength
, m_pchData
, nSrcLen
, pszSrcData
);
446 // fast concatenation when buffer big enough
447 memcpy(m_pchData
+ pData
->nDataLength
, pszSrcData
, nSrcLen
*sizeof(char));
448 pData
->nDataLength
+= nSrcLen
;
450 // should be enough space
451 wxASSERT( pData
->nDataLength
<= pData
->nAllocLength
);
453 m_pchData
[pData
->nDataLength
] = '\0'; // put terminating '\0'
459 * concatenation functions come in 5 flavours:
461 * char + string and string + char
462 * C str + string and string + C str
465 wxString
operator+(const wxString
& string1
, const wxString
& string2
)
467 wxASSERT( string1
.GetStringData()->IsValid() );
468 wxASSERT( string2
.GetStringData()->IsValid() );
471 s
.ConcatCopy(string1
.GetStringData()->nDataLength
, string1
.m_pchData
,
472 string2
.GetStringData()->nDataLength
, string2
.m_pchData
);
476 wxString
operator+(const wxString
& string1
, char ch
)
478 wxASSERT( string1
.GetStringData()->IsValid() );
481 s
.ConcatCopy(string1
.GetStringData()->nDataLength
, string1
.m_pchData
, 1, &ch
);
485 wxString
operator+(char ch
, const wxString
& string
)
487 wxASSERT( string
.GetStringData()->IsValid() );
490 s
.ConcatCopy(1, &ch
, string
.GetStringData()->nDataLength
, string
.m_pchData
);
494 wxString
operator+(const wxString
& string
, const char *psz
)
496 wxASSERT( string
.GetStringData()->IsValid() );
499 s
.ConcatCopy(string
.GetStringData()->nDataLength
, string
.m_pchData
,
504 wxString
operator+(const char *psz
, const wxString
& string
)
506 wxASSERT( string
.GetStringData()->IsValid() );
509 s
.ConcatCopy(Strlen(psz
), psz
,
510 string
.GetStringData()->nDataLength
, string
.m_pchData
);
514 // ===========================================================================
515 // other common string functions
516 // ===========================================================================
518 // ---------------------------------------------------------------------------
519 // simple sub-string extraction
520 // ---------------------------------------------------------------------------
522 // helper function: clone the data attached to this string
523 void wxString::AllocCopy(wxString
& dest
, int nCopyLen
, int nCopyIndex
) const
531 dest
.AllocBuffer(nCopyLen
);
532 memcpy(dest
.m_pchData
, m_pchData
+ nCopyIndex
, nCopyLen
*sizeof(char));
536 // extract string of length nCount starting at nFirst
537 // default value of nCount is 0 and means "till the end"
538 wxString
wxString::Mid(size_t nFirst
, size_t nCount
) const
540 // out-of-bounds requests return sensible things
542 nCount
= GetStringData()->nDataLength
- nFirst
;
544 if ( nFirst
+ nCount
> (size_t)GetStringData()->nDataLength
)
545 nCount
= GetStringData()->nDataLength
- nFirst
;
546 if ( nFirst
> (size_t)GetStringData()->nDataLength
)
550 AllocCopy(dest
, nCount
, nFirst
);
554 // extract nCount last (rightmost) characters
555 wxString
wxString::Right(size_t nCount
) const
557 if ( nCount
> (size_t)GetStringData()->nDataLength
)
558 nCount
= GetStringData()->nDataLength
;
561 AllocCopy(dest
, nCount
, GetStringData()->nDataLength
- nCount
);
565 // get all characters after the last occurence of ch
566 // (returns the whole string if ch not found)
567 wxString
wxString::Right(char ch
) const
570 int iPos
= Find(ch
, TRUE
);
571 if ( iPos
== NOT_FOUND
)
574 str
= c_str() + iPos
+ 1;
579 // extract nCount first (leftmost) characters
580 wxString
wxString::Left(size_t nCount
) const
582 if ( nCount
> (size_t)GetStringData()->nDataLength
)
583 nCount
= GetStringData()->nDataLength
;
586 AllocCopy(dest
, nCount
, 0);
590 // get all characters before the first occurence of ch
591 // (returns the whole string if ch not found)
592 wxString
wxString::Left(char ch
) const
595 for ( const char *pc
= m_pchData
; *pc
!= '\0' && *pc
!= ch
; pc
++ )
601 /// get all characters before the last occurence of ch
602 /// (returns empty string if ch not found)
603 wxString
wxString::Before(char ch
) const
606 int iPos
= Find(ch
, TRUE
);
607 if ( iPos
!= NOT_FOUND
&& iPos
!= 0 )
608 str
= wxString(c_str(), iPos
);
613 /// get all characters after the first occurence of ch
614 /// (returns empty string if ch not found)
615 wxString
wxString::After(char ch
) const
619 if ( iPos
!= NOT_FOUND
)
620 str
= c_str() + iPos
+ 1;
625 // replace first (or all) occurences of some substring with another one
626 uint
wxString::Replace(const char *szOld
, const char *szNew
, bool bReplaceAll
)
628 uint uiCount
= 0; // count of replacements made
630 uint uiOldLen
= Strlen(szOld
);
633 const char *pCurrent
= m_pchData
;
635 while ( *pCurrent
!= '\0' ) {
636 pSubstr
= strstr(pCurrent
, szOld
);
637 if ( pSubstr
== NULL
) {
638 // strTemp is unused if no replacements were made, so avoid the copy
642 strTemp
+= pCurrent
; // copy the rest
643 break; // exit the loop
646 // take chars before match
647 strTemp
.ConcatSelf(pSubstr
- pCurrent
, pCurrent
);
649 pCurrent
= pSubstr
+ uiOldLen
; // restart after match
654 if ( !bReplaceAll
) {
655 strTemp
+= pCurrent
; // copy the rest
656 break; // exit the loop
661 // only done if there were replacements, otherwise would have returned above
667 bool wxString::IsAscii() const
669 const char *s
= (const char*) *this;
671 if(!isascii(*s
)) return(FALSE
);
677 bool wxString::IsWord() const
679 const char *s
= (const char*) *this;
681 if(!isalpha(*s
)) return(FALSE
);
687 bool wxString::IsNumber() const
689 const char *s
= (const char*) *this;
691 if(!isdigit(*s
)) return(FALSE
);
697 wxString
wxString::Strip(stripType w
) const
700 if ( w
& leading
) s
.Trim(FALSE
);
701 if ( w
& trailing
) s
.Trim(TRUE
);
705 // ---------------------------------------------------------------------------
707 // ---------------------------------------------------------------------------
709 wxString
& wxString::MakeUpper()
713 for ( char *p
= m_pchData
; *p
; p
++ )
714 *p
= (char)toupper(*p
);
719 wxString
& wxString::MakeLower()
723 for ( char *p
= m_pchData
; *p
; p
++ )
724 *p
= (char)tolower(*p
);
729 // ---------------------------------------------------------------------------
730 // trimming and padding
731 // ---------------------------------------------------------------------------
733 // trims spaces (in the sense of isspace) from left or right side
734 wxString
& wxString::Trim(bool bFromRight
)
740 // find last non-space character
741 char *psz
= m_pchData
+ GetStringData()->nDataLength
- 1;
742 while ( isspace(*psz
) && (psz
>= m_pchData
) )
745 // truncate at trailing space start
747 GetStringData()->nDataLength
= psz
- m_pchData
;
751 // find first non-space character
752 const char *psz
= m_pchData
;
753 while ( isspace(*psz
) )
756 // fix up data and length
757 int nDataLength
= GetStringData()->nDataLength
- (psz
- m_pchData
);
758 memmove(m_pchData
, psz
, (nDataLength
+ 1)*sizeof(char));
759 GetStringData()->nDataLength
= nDataLength
;
765 // adds nCount characters chPad to the string from either side
766 wxString
& wxString::Pad(size_t nCount
, char chPad
, bool bFromRight
)
768 wxString
s(chPad
, nCount
);
781 // truncate the string
782 wxString
& wxString::Truncate(size_t uiLen
)
784 *(m_pchData
+ uiLen
) = '\0';
785 GetStringData()->nDataLength
= uiLen
;
790 // ---------------------------------------------------------------------------
791 // finding (return NOT_FOUND if not found and index otherwise)
792 // ---------------------------------------------------------------------------
795 int wxString::Find(char ch
, bool bFromEnd
) const
797 const char *psz
= bFromEnd
? strrchr(m_pchData
, ch
) : strchr(m_pchData
, ch
);
799 return (psz
== NULL
) ? NOT_FOUND
: psz
- m_pchData
;
802 // find a sub-string (like strstr)
803 int wxString::Find(const char *pszSub
) const
805 const char *psz
= strstr(m_pchData
, pszSub
);
807 return (psz
== NULL
) ? NOT_FOUND
: psz
- m_pchData
;
810 // ---------------------------------------------------------------------------
812 // ---------------------------------------------------------------------------
813 int wxString::Printf(const char *pszFormat
, ...)
816 va_start(argptr
, pszFormat
);
818 int iLen
= PrintfV(pszFormat
, argptr
);
825 int wxString::PrintfV(const char* pszFormat
, va_list argptr
)
827 static char s_szScratch
[1024];
829 int iLen
= vsprintf(s_szScratch
, pszFormat
, argptr
);
830 AllocBeforeWrite(iLen
);
831 strcpy(m_pchData
, s_szScratch
);
837 int wxString::Scanf(const char *pszFormat
, ...) const
840 va_start(argptr
, pszFormat
);
842 int iLen
= ScanfV(pszFormat
, argptr
);
849 int wxString::ScanfV(const char *pszFormat
, va_list argptr
) const
852 wxMessageBox("ScanfV not implemented");
855 return vsscanf(c_str(), pszFormat
, argptr
);
860 // ----------------------------------------------------------------------------
861 // misc other operations
862 // ----------------------------------------------------------------------------
863 bool wxString::Matches(const char *pszMask
) const
865 // check char by char
867 for ( pszTxt
= c_str(); *pszMask
!= '\0'; pszMask
++, pszTxt
++ ) {
868 switch ( *pszMask
) {
870 if ( *pszTxt
== '\0' )
879 // ignore special chars immediately following this one
880 while ( *pszMask
== '*' || *pszMask
== '?' )
883 // if there is nothing more, match
884 if ( *pszMask
== '\0' )
887 // are there any other metacharacters in the mask?
889 const char *pEndMask
= strpbrk(pszMask
, "*?");
891 if ( pEndMask
!= NULL
) {
892 // we have to match the string between two metachars
893 uiLenMask
= pEndMask
- pszMask
;
896 // we have to match the remainder of the string
897 uiLenMask
= strlen(pszMask
);
900 wxString
strToMatch(pszMask
, uiLenMask
);
901 const char* pMatch
= strstr(pszTxt
, strToMatch
);
902 if ( pMatch
== NULL
)
905 // -1 to compensate "++" in the loop
906 pszTxt
= pMatch
+ uiLenMask
- 1;
907 pszMask
+= uiLenMask
- 1;
912 if ( *pszMask
!= *pszTxt
)
918 // match only if nothing left
919 return *pszTxt
== '\0';
922 // ---------------------------------------------------------------------------
923 // standard C++ library string functions
924 // ---------------------------------------------------------------------------
925 #ifdef STD_STRING_COMPATIBILITY
927 wxString
& wxString::insert(size_t nPos
, const wxString
& str
)
929 wxASSERT( str
.GetStringData()->IsValid() );
930 wxASSERT( nPos
<= Len() );
933 char *pc
= strTmp
.GetWriteBuf(Len() + str
.Len());
934 strncpy(pc
, c_str(), nPos
);
935 strcpy(pc
+ nPos
, str
);
936 strcpy(pc
+ nPos
+ str
.Len(), c_str() + nPos
);
937 strTmp
.UngetWriteBuf();
943 size_t wxString::find(const wxString
& str
, size_t nStart
) const
945 wxASSERT( str
.GetStringData()->IsValid() );
946 wxASSERT( nStart
<= Len() );
948 const char *p
= strstr(c_str() + nStart
, str
);
950 return p
== NULL
? npos
: p
- c_str();
953 // VC++ 1.5 can't cope with the default argument in the header.
954 #if ! (defined(_MSC_VER) && !defined(__WIN32__))
955 size_t wxString::find(const char* sz
, size_t nStart
, size_t n
) const
957 return find(wxString(sz
, n
== npos
? 0 : n
), nStart
);
961 size_t wxString::find(char ch
, size_t nStart
) const
963 wxASSERT( nStart
<= Len() );
965 const char *p
= strchr(c_str() + nStart
, ch
);
967 return p
== NULL
? npos
: p
- c_str();
970 size_t wxString::rfind(const wxString
& str
, size_t nStart
) const
972 wxASSERT( str
.GetStringData()->IsValid() );
973 wxASSERT( nStart
<= Len() );
975 // # could be quicker than that
976 const char *p
= c_str() + (nStart
== npos
? Len() : nStart
);
977 while ( p
>= c_str() + str
.Len() ) {
978 if ( strncmp(p
- str
.Len(), str
, str
.Len()) == 0 )
979 return p
- str
.Len() - c_str();
986 // VC++ 1.5 can't cope with the default argument in the header.
987 #if ! (defined(_MSC_VER) && !defined(__WIN32__))
988 size_t wxString::rfind(const char* sz
, size_t nStart
, size_t n
) const
990 return rfind(wxString(sz
, n
== npos
? 0 : n
), nStart
);
993 size_t wxString::rfind(char ch
, size_t nStart
) const
995 wxASSERT( nStart
<= Len() );
997 const char *p
= strrchr(c_str() + nStart
, ch
);
999 return p
== NULL
? npos
: p
- c_str();
1003 wxString
wxString::substr(size_t nStart
, size_t nLen
) const
1005 // npos means 'take all'
1009 wxASSERT( nStart
+ nLen
<= Len() );
1011 return wxString(c_str() + nStart
, nLen
== npos
? 0 : nLen
);
1014 wxString
& wxString::erase(size_t nStart
, size_t nLen
)
1016 wxString
strTmp(c_str(), nStart
);
1017 if ( nLen
!= npos
) {
1018 wxASSERT( nStart
+ nLen
<= Len() );
1020 strTmp
.append(c_str() + nStart
+ nLen
);
1027 wxString
& wxString::replace(size_t nStart
, size_t nLen
, const char *sz
)
1029 wxASSERT( nStart
+ nLen
<= Strlen(sz
) );
1033 strTmp
.append(c_str(), nStart
);
1035 strTmp
.append(c_str() + nStart
+ nLen
);
1041 wxString
& wxString::replace(size_t nStart
, size_t nLen
, size_t nCount
, char ch
)
1043 return replace(nStart
, nLen
, wxString(ch
, nCount
));
1046 wxString
& wxString::replace(size_t nStart
, size_t nLen
,
1047 const wxString
& str
, size_t nStart2
, size_t nLen2
)
1049 return replace(nStart
, nLen
, str
.substr(nStart2
, nLen2
));
1052 wxString
& wxString::replace(size_t nStart
, size_t nLen
,
1053 const char* sz
, size_t nCount
)
1055 return replace(nStart
, nLen
, wxString(sz
, nCount
));
1058 #endif //std::string compatibility
1060 // ============================================================================
1062 // ============================================================================
1064 // size increment = max(50% of current size, ARRAY_MAXSIZE_INCREMENT)
1065 #define ARRAY_MAXSIZE_INCREMENT 4096
1066 #ifndef ARRAY_DEFAULT_INITIAL_SIZE // also defined in dynarray.h
1067 #define ARRAY_DEFAULT_INITIAL_SIZE (16)
1070 #define STRING(p) ((wxString *)(&(p)))
1073 wxArrayString::wxArrayString()
1081 wxArrayString::wxArrayString(const wxArrayString
& src
)
1083 m_nSize
= src
.m_nSize
;
1084 m_nCount
= src
.m_nCount
;
1087 m_pItems
= new char *[m_nSize
];
1091 if ( m_nCount
!= 0 )
1092 memcpy(m_pItems
, src
.m_pItems
, m_nCount
*sizeof(char *));
1096 wxArrayString
& wxArrayString::operator=(const wxArrayString
& src
)
1100 m_nSize
= src
.m_nSize
;
1101 m_nCount
= src
.m_nCount
;
1104 m_pItems
= new char *[m_nCount
];
1108 if ( m_nCount
!= 0 )
1109 memcpy(m_pItems
, src
.m_pItems
, m_nCount
*sizeof(char *));
1115 void wxArrayString::Grow()
1117 // only do it if no more place
1118 if( m_nCount
== m_nSize
) {
1119 if( m_nSize
== 0 ) {
1120 // was empty, alloc some memory
1121 m_nSize
= ARRAY_DEFAULT_INITIAL_SIZE
;
1122 m_pItems
= new char *[m_nSize
];
1125 // add 50% but not too much
1126 size_t nIncrement
= m_nSize
>> 1;
1127 if ( nIncrement
> ARRAY_MAXSIZE_INCREMENT
)
1128 nIncrement
= ARRAY_MAXSIZE_INCREMENT
;
1129 m_nSize
+= nIncrement
;
1130 char **pNew
= new char *[m_nSize
];
1132 // copy data to new location
1133 memcpy(pNew
, m_pItems
, m_nCount
*sizeof(char *));
1135 // delete old memory (but do not release the strings!)
1143 void wxArrayString::Free()
1145 for ( size_t n
= 0; n
< m_nCount
; n
++ ) {
1146 STRING(m_pItems
[n
])->GetStringData()->Unlock();
1150 // deletes all the strings from the list
1151 void wxArrayString::Empty()
1158 // as Empty, but also frees memory
1159 void wxArrayString::Clear()
1171 wxArrayString::~wxArrayString()
1178 // pre-allocates memory (frees the previous data!)
1179 void wxArrayString::Alloc(size_t nSize
)
1181 wxASSERT( nSize
> 0 );
1183 // only if old buffer was not big enough
1184 if ( nSize
> m_nSize
) {
1187 m_pItems
= new char *[nSize
];
1194 // searches the array for an item (forward or backwards)
1196 // Robert Roebling (changed to bool from bool)
1198 int wxArrayString::Index(const char *sz
, bool bCase
, bool bFromEnd
) const
1201 if ( m_nCount
> 0 ) {
1204 if ( STRING(m_pItems
[--ui
])->IsSameAs(sz
, bCase
) )
1211 for( uint ui
= 0; ui
< m_nCount
; ui
++ ) {
1212 if( STRING(m_pItems
[ui
])->IsSameAs(sz
, bCase
) )
1220 // add item at the end
1221 void wxArrayString::Add(const wxString
& str
)
1223 wxASSERT( str
.GetStringData()->IsValid() );
1227 // the string data must not be deleted!
1228 str
.GetStringData()->Lock();
1229 m_pItems
[m_nCount
++] = (char *)str
.c_str();
1232 // add item at the given position
1233 void wxArrayString::Insert(const wxString
& str
, size_t nIndex
)
1235 wxASSERT( str
.GetStringData()->IsValid() );
1237 wxCHECK_RET( nIndex
<= m_nCount
, "bad index in wxArrayString::Insert" );
1241 memmove(&m_pItems
[nIndex
+ 1], &m_pItems
[nIndex
],
1242 (m_nCount
- nIndex
)*sizeof(char *));
1244 str
.GetStringData()->Lock();
1245 m_pItems
[nIndex
] = (char *)str
.c_str();
1250 // removes item from array (by index)
1251 void wxArrayString::Remove(size_t nIndex
)
1253 wxCHECK_RET( nIndex
<= m_nCount
, "bad index in wxArrayString::Remove" );
1256 Item(nIndex
).GetStringData()->Unlock();
1258 memmove(&m_pItems
[nIndex
], &m_pItems
[nIndex
+ 1],
1259 (m_nCount
- nIndex
- 1)*sizeof(char *));
1263 // removes item from array (by value)
1264 void wxArrayString::Remove(const char *sz
)
1266 int iIndex
= Index(sz
);
1268 wxCHECK_RET( iIndex
!= NOT_FOUND
,
1269 "removing inexistent element in wxArrayString::Remove" );
1271 Remove((size_t)iIndex
);
1274 // sort array elements using passed comparaison function
1276 void wxArrayString::Sort(bool bCase
, bool bReverse
)
1279 //qsort(m_pItems, m_nCount, sizeof(char *), fCmp);