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 string shares memory with g_strEmpty
65 static wxStringData
*g_strNul
= (wxStringData
*)&g_strEmpty
;
66 // empty C style string: points to 'string data' byte of g_strEmpty
67 extern const char *g_szNul
= (const char *)(&g_strEmpty
[3]);
69 // ===========================================================================
71 // ===========================================================================
73 #ifdef STD_STRING_COMPATIBILITY
75 // MS Visual C++ version 5.0 provides the new STL headers as well as the old
78 // ATTN: you can _not_ use both of these in the same program!
81 #define NAMESPACE std::
87 NAMESPACE istream
& operator>>(NAMESPACE istream
& is
, wxString
& WXUNUSED(str
))
92 NAMESPACE streambuf
*sb
= is
.rdbuf();
95 int ch
= sb
->sbumpc ();
97 is
.setstate(NAMESPACE
ios::eofbit
);
100 else if ( isspace(ch
) ) {
112 if ( str
.length() == 0 )
113 is
.setstate(NAMESPACE
ios::failbit
);
118 #endif //std::string compatibility
120 // ===========================================================================
121 // wxString class core
122 // ===========================================================================
124 // ---------------------------------------------------------------------------
126 // ---------------------------------------------------------------------------
128 // construct an empty string
135 wxString::wxString(const wxString
& stringSrc
)
137 wxASSERT( stringSrc
.GetStringData()->IsValid() );
139 if ( stringSrc
.IsEmpty() ) {
140 // nothing to do for an empty string
144 m_pchData
= stringSrc
.m_pchData
; // share same data
145 GetStringData()->Lock(); // => one more copy
149 // constructs string of <nLength> copies of character <ch>
150 wxString::wxString(char ch
, size_t nLength
)
155 AllocBuffer(nLength
);
157 wxASSERT( sizeof(char) == 1 ); // can't use memset if not
159 memset(m_pchData
, ch
, nLength
);
163 // takes nLength elements of psz starting at nPos
164 void wxString::InitWith(const char *psz
, size_t nPos
, size_t nLength
)
168 wxASSERT( nPos
<= Strlen(psz
) );
170 if ( nLength
== STRING_MAXLEN
)
171 nLength
= Strlen(psz
+ nPos
);
174 // trailing '\0' is written in AllocBuffer()
175 AllocBuffer(nLength
);
176 memcpy(m_pchData
, psz
+ nPos
, nLength
*sizeof(char));
180 // take first nLength characters of C string psz
181 // (default value of STRING_MAXLEN means take all the string)
182 wxString::wxString(const char *psz
, size_t nLength
)
184 InitWith(psz
, 0, nLength
);
187 // the same as previous constructor, but for compilers using unsigned char
188 wxString::wxString(const unsigned char* psz
, size_t nLength
)
190 InitWith((const char *)psz
, 0, nLength
);
193 #ifdef STD_STRING_COMPATIBILITY
195 // ctor from a substring
196 wxString::wxString(const wxString
& s
, size_t nPos
, size_t nLen
)
198 InitWith(s
.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
*)new char[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 // releases the string memory and reinits it
249 void wxString::Reinit()
251 GetStringData()->Unlock();
255 // wrapper around wxString::Reinit
256 void wxString::Empty()
258 if ( GetStringData()->nDataLength
!= 0 )
261 wxASSERT( GetStringData()->nDataLength
== 0 );
262 wxASSERT( GetStringData()->nAllocLength
== 0 );
265 // must be called before changing this string
266 void wxString::CopyBeforeWrite()
268 wxStringData
* pData
= GetStringData();
270 if ( pData
->IsShared() ) {
271 pData
->Unlock(); // memory not freed because shared
272 AllocBuffer(pData
->nDataLength
);
273 memcpy(m_pchData
, pData
->data(), (pData
->nDataLength
+ 1)*sizeof(char));
276 wxASSERT( !pData
->IsShared() ); // we must be the only owner
279 // must be called before replacing contents of this string
280 void wxString::AllocBeforeWrite(size_t nLen
)
282 wxASSERT( nLen
!= 0 ); // doesn't make any sense
284 // must not share string and must have enough space
285 register wxStringData
* pData
= GetStringData();
286 if ( pData
->IsShared() || (nLen
> pData
->nAllocLength
) ) {
287 // can't work with old buffer, get new one
292 wxASSERT( !pData
->IsShared() ); // we must be the only owner
295 // get the pointer to writable buffer of (at least) nLen bytes
296 char *wxString::GetWriteBuf(size_t nLen
)
298 AllocBeforeWrite(nLen
);
302 // dtor frees memory if no other strings use it
303 wxString::~wxString()
305 GetStringData()->Unlock();
308 // ---------------------------------------------------------------------------
310 // ---------------------------------------------------------------------------
312 // all functions are inline in string.h
314 // ---------------------------------------------------------------------------
315 // assignment operators
316 // ---------------------------------------------------------------------------
318 // helper function: does real copy
319 void wxString::AssignCopy(size_t nSrcLen
, const char *pszSrcData
)
321 if ( nSrcLen
== 0 ) {
325 AllocBeforeWrite(nSrcLen
);
326 memcpy(m_pchData
, pszSrcData
, nSrcLen
*sizeof(char));
327 GetStringData()->nDataLength
= nSrcLen
;
328 m_pchData
[nSrcLen
] = '\0';
332 // assigns one string to another
333 wxString
& wxString::operator=(const wxString
& stringSrc
)
335 // don't copy string over itself
336 if ( m_pchData
!= stringSrc
.m_pchData
) {
337 if ( stringSrc
.GetStringData()->IsEmpty() ) {
342 GetStringData()->Unlock();
343 m_pchData
= stringSrc
.m_pchData
;
344 GetStringData()->Lock();
351 // assigns a single character
352 wxString
& wxString::operator=(char ch
)
359 wxString
& wxString::operator=(const char *psz
)
361 AssignCopy(Strlen(psz
), psz
);
365 // same as 'signed char' variant
366 wxString
& wxString::operator=(const unsigned char* psz
)
368 *this = (const char *)psz
;
372 wxString
& wxString::operator=(const wchar_t *pwz
)
379 // ---------------------------------------------------------------------------
380 // string concatenation
381 // ---------------------------------------------------------------------------
383 // concatenate two sources
384 // NB: assume that 'this' is a new wxString object
385 void wxString::ConcatCopy(int nSrc1Len
, const char *pszSrc1Data
,
386 int nSrc2Len
, const char *pszSrc2Data
)
388 int nNewLen
= nSrc1Len
+ nSrc2Len
;
391 AllocBuffer(nNewLen
);
392 memcpy(m_pchData
, pszSrc1Data
, nSrc1Len
*sizeof(char));
393 memcpy(m_pchData
+ nSrc1Len
, pszSrc2Data
, nSrc2Len
*sizeof(char));
397 // add something to this string
398 void wxString::ConcatSelf(int nSrcLen
, const char *pszSrcData
)
400 // concatenating an empty string is a NOP
401 if ( nSrcLen
!= 0 ) {
402 register wxStringData
*pData
= GetStringData();
404 // alloc new buffer if current is too small
405 if ( pData
->IsShared() ||
406 pData
->nDataLength
+ nSrcLen
> pData
->nAllocLength
) {
407 // we have to grow the buffer, use the ConcatCopy routine
408 // (which will allocate memory)
409 wxStringData
* pOldData
= GetStringData();
410 ConcatCopy(pOldData
->nDataLength
, m_pchData
, nSrcLen
, pszSrcData
);
414 // fast concatenation when buffer big enough
415 memcpy(m_pchData
+ pData
->nDataLength
, pszSrcData
, nSrcLen
*sizeof(char));
416 pData
->nDataLength
+= nSrcLen
;
418 // should be enough space
419 wxASSERT( pData
->nDataLength
<= pData
->nAllocLength
);
421 m_pchData
[pData
->nDataLength
] = '\0'; // put terminating '\0'
427 * string may be concatenated with other string, C string or a character
430 void wxString::operator+=(const wxString
& string
)
432 ConcatSelf(string
.Len(), string
);
435 void wxString::operator+=(const char *psz
)
437 ConcatSelf(Strlen(psz
), psz
);
440 void wxString::operator+=(char ch
)
446 * Same as above but return the result
449 wxString
& wxString::operator<<(const wxString
& string
)
451 ConcatSelf(string
.Len(), string
);
455 wxString
& wxString::operator<<(const char *psz
)
457 ConcatSelf(Strlen(psz
), psz
);
461 wxString
& wxString::operator<<(char ch
)
468 * concatenation functions come in 5 flavours:
470 * char + string and string + char
471 * C str + string and string + C str
474 wxString
operator+(const wxString
& string1
, const wxString
& string2
)
477 s
.ConcatCopy(string1
.GetStringData()->nDataLength
, string1
.m_pchData
,
478 string2
.GetStringData()->nDataLength
, string2
.m_pchData
);
482 wxString
operator+(const wxString
& string1
, char ch
)
485 s
.ConcatCopy(string1
.GetStringData()->nDataLength
, string1
.m_pchData
, 1, &ch
);
489 wxString
operator+(char ch
, const wxString
& string
)
492 s
.ConcatCopy(1, &ch
, string
.GetStringData()->nDataLength
, string
.m_pchData
);
496 wxString
operator+(const wxString
& string
, const char *psz
)
499 s
.ConcatCopy(string
.GetStringData()->nDataLength
, string
.m_pchData
,
504 wxString
operator+(const char *psz
, const wxString
& string
)
507 s
.ConcatCopy(Strlen(psz
), psz
,
508 string
.GetStringData()->nDataLength
, string
.m_pchData
);
512 // ===========================================================================
513 // other common string functions
514 // ===========================================================================
516 // ---------------------------------------------------------------------------
517 // simple sub-string extraction
518 // ---------------------------------------------------------------------------
520 // helper function: clone the data attached to this string
521 void wxString::AllocCopy(wxString
& dest
, int nCopyLen
, int nCopyIndex
) const
529 dest
.AllocBuffer(nCopyLen
);
530 memcpy(dest
.m_pchData
, m_pchData
+ nCopyIndex
, nCopyLen
*sizeof(char));
534 // extract string of length nCount starting at nFirst
535 // default value of nCount is 0 and means "till the end"
536 wxString
wxString::Mid(size_t nFirst
, size_t nCount
) const
538 // out-of-bounds requests return sensible things
540 nCount
= GetStringData()->nDataLength
- nFirst
;
542 if ( nFirst
+ nCount
> (size_t)GetStringData()->nDataLength
)
543 nCount
= GetStringData()->nDataLength
- nFirst
;
544 if ( nFirst
> (size_t)GetStringData()->nDataLength
)
548 AllocCopy(dest
, nCount
, nFirst
);
552 // extract nCount last (rightmost) characters
553 wxString
wxString::Right(size_t nCount
) const
555 if ( nCount
> (size_t)GetStringData()->nDataLength
)
556 nCount
= GetStringData()->nDataLength
;
559 AllocCopy(dest
, nCount
, GetStringData()->nDataLength
- nCount
);
563 // get all characters after the last occurence of ch
564 // (returns the whole string if ch not found)
565 wxString
wxString::Right(char ch
) const
568 int iPos
= Find(ch
, TRUE
);
569 if ( iPos
== NOT_FOUND
)
572 str
= c_str() + iPos
;
577 // extract nCount first (leftmost) characters
578 wxString
wxString::Left(size_t nCount
) const
580 if ( nCount
> (size_t)GetStringData()->nDataLength
)
581 nCount
= GetStringData()->nDataLength
;
584 AllocCopy(dest
, nCount
, 0);
588 // get all characters before the first occurence of ch
589 // (returns the whole string if ch not found)
590 wxString
wxString::Left(char ch
) const
593 for ( const char *pc
= m_pchData
; *pc
!= '\0' && *pc
!= ch
; pc
++ )
599 /// get all characters before the last occurence of ch
600 /// (returns empty string if ch not found)
601 wxString
wxString::Before(char ch
) const
604 int iPos
= Find(ch
, TRUE
);
605 if ( iPos
!= NOT_FOUND
&& iPos
!= 0 )
606 str
= wxString(c_str(), iPos
- 1);
611 /// get all characters after the first occurence of ch
612 /// (returns empty string if ch not found)
613 wxString
wxString::After(char ch
) const
617 if ( iPos
!= NOT_FOUND
)
618 str
= c_str() + iPos
+ 1;
623 // replace first (or all) occurences of some substring with another one
624 uint
wxString::Replace(const char *szOld
, const char *szNew
, bool bReplaceAll
)
626 uint uiCount
= 0; // count of replacements made
628 uint uiOldLen
= Strlen(szOld
);
631 const char *pCurrent
= m_pchData
;
633 while ( *pCurrent
!= '\0' ) {
634 pSubstr
= strstr(pCurrent
, szOld
);
635 if ( pSubstr
== NULL
) {
636 // strTemp is unused if no replacements were made, so avoid the copy
640 strTemp
+= pCurrent
; // copy the rest
641 break; // exit the loop
644 // take chars before match
645 strTemp
.ConcatSelf(pSubstr
- pCurrent
, pCurrent
);
647 pCurrent
= pSubstr
+ uiOldLen
; // restart after match
652 if ( !bReplaceAll
) {
653 strTemp
+= pCurrent
; // copy the rest
654 break; // exit the loop
659 // only done if there were replacements, otherwise would have returned above
665 bool wxString::IsAscii() const
667 const char *s
= (const char*) *this;
669 if(!isascii(*s
)) return(FALSE
);
675 bool wxString::IsWord() const
677 const char *s
= (const char*) *this;
679 if(!isalpha(*s
)) return(FALSE
);
685 bool wxString::IsNumber() const
687 const char *s
= (const char*) *this;
689 if(!isdigit(*s
)) return(FALSE
);
695 // kludge: we don't have declaraton of wxStringData here, so we add offsets
696 // manually to get to the "length" field of wxStringData structure
697 bool wxString::IsEmpty() const { return Len() == 0; }
699 wxString
wxString::Strip(stripType w
) const
702 if ( w
& leading
) s
.Trim(FALSE
);
703 if ( w
& trailing
) s
.Trim(TRUE
);
707 /// case-insensitive strcmp() (platform independent)
708 int Stricmp(const char *psz1
, const char *psz2
)
710 #if defined(_MSC_VER)
711 return _stricmp(psz1
, psz2
);
712 #elif defined(__BORLANDC__)
713 return stricmp(psz1
, psz2
);
714 #elif defined(__UNIX__) || defined(__GNUWIN32__)
715 return strcasecmp(psz1
, psz2
);
717 // almost all compilers/libraries provide this function (unfortunately under
718 // different names), that's why we don't implement our own which will surely
719 // be more efficient than this code (uncomment to use):
721 register char c1, c2;
723 c1 = tolower(*psz1++);
724 c2 = tolower(*psz2++);
725 } while ( c1 && (c1 == c2) );
730 #error "Please define string case-insensitive compare for your OS/compiler"
731 #endif // OS/compiler
734 // ---------------------------------------------------------------------------
736 // ---------------------------------------------------------------------------
738 wxString
& wxString::MakeUpper()
742 for ( char *p
= m_pchData
; *p
; p
++ )
743 *p
= (char)toupper(*p
);
748 wxString
& wxString::MakeLower()
752 for ( char *p
= m_pchData
; *p
; p
++ )
753 *p
= (char)tolower(*p
);
758 // ---------------------------------------------------------------------------
759 // trimming and padding
760 // ---------------------------------------------------------------------------
762 // trims spaces (in the sense of isspace) from left or right side
763 wxString
& wxString::Trim(bool bFromRight
)
769 // find last non-space character
770 char *psz
= m_pchData
+ GetStringData()->nDataLength
- 1;
771 while ( isspace(*psz
) && (psz
>= m_pchData
) )
774 // truncate at trailing space start
776 GetStringData()->nDataLength
= psz
- m_pchData
;
780 // find first non-space character
781 const char *psz
= m_pchData
;
782 while ( isspace(*psz
) )
785 // fix up data and length
786 int nDataLength
= GetStringData()->nDataLength
- (psz
- m_pchData
);
787 memmove(m_pchData
, psz
, (nDataLength
+ 1)*sizeof(char));
788 GetStringData()->nDataLength
= nDataLength
;
794 // adds nCount characters chPad to the string from either side
795 wxString
& wxString::Pad(size_t nCount
, char chPad
, bool bFromRight
)
797 wxString
s(chPad
, nCount
);
810 // truncate the string
811 wxString
& wxString::Truncate(size_t uiLen
)
813 *(m_pchData
+ uiLen
) = '\0';
814 GetStringData()->nDataLength
= uiLen
;
819 // ---------------------------------------------------------------------------
820 // finding (return NOT_FOUND if not found and index otherwise)
821 // ---------------------------------------------------------------------------
824 int wxString::Find(char ch
, bool bFromEnd
) const
826 const char *psz
= bFromEnd
? strrchr(m_pchData
, ch
) : strchr(m_pchData
, ch
);
828 return (psz
== NULL
) ? NOT_FOUND
: psz
- m_pchData
;
831 // find a sub-string (like strstr)
832 int wxString::Find(const char *pszSub
) const
834 const char *psz
= strstr(m_pchData
, pszSub
);
836 return (psz
== NULL
) ? NOT_FOUND
: psz
- m_pchData
;
839 // ---------------------------------------------------------------------------
841 // ---------------------------------------------------------------------------
842 int wxString::Printf(const char *pszFormat
, ...)
845 va_start(argptr
, pszFormat
);
847 int iLen
= PrintfV(pszFormat
, argptr
);
854 int wxString::PrintfV(const char* pszFormat
, va_list argptr
)
856 static char s_szScratch
[1024];
858 int iLen
= vsprintf(s_szScratch
, pszFormat
, argptr
);
859 AllocBeforeWrite(iLen
);
860 strcpy(m_pchData
, s_szScratch
);
865 // ---------------------------------------------------------------------------
866 // standard C++ library string functions
867 // ---------------------------------------------------------------------------
868 #ifdef STD_STRING_COMPATIBILITY
870 wxString
& wxString::insert(size_t nPos
, const wxString
& str
)
872 wxASSERT( nPos
<= Len() );
875 char *pc
= strTmp
.GetWriteBuf(Len() + str
.Len() + 1);
876 strncpy(pc
, c_str(), nPos
);
877 strcpy(pc
+ nPos
, str
);
878 strcpy(pc
+ nPos
+ str
.Len(), c_str() + nPos
);
884 size_t wxString::find(const wxString
& str
, size_t nStart
) const
886 wxASSERT( nStart
<= Len() );
888 const char *p
= strstr(c_str() + nStart
, str
);
890 return p
== NULL
? npos
: p
- c_str();
893 size_t wxString::find(const char* sz
, size_t nStart
, size_t n
) const
895 return find(wxString(sz
, n
== npos
? 0 : n
), nStart
);
898 size_t wxString::find(char ch
, size_t nStart
) const
900 wxASSERT( nStart
<= Len() );
902 const char *p
= strchr(c_str() + nStart
, ch
);
904 return p
== NULL
? npos
: p
- c_str();
907 size_t wxString::rfind(const wxString
& str
, size_t nStart
) const
909 wxASSERT( nStart
<= Len() );
911 // # could be quicker than that
912 const char *p
= c_str() + (nStart
== npos
? Len() : nStart
);
913 while ( p
>= c_str() + str
.Len() ) {
914 if ( strncmp(p
- str
.Len(), str
, str
.Len()) == 0 )
915 return p
- str
.Len() - c_str();
922 size_t wxString::rfind(const char* sz
, size_t nStart
, size_t n
) const
924 return rfind(wxString(sz
, n
== npos
? 0 : n
), nStart
);
927 size_t wxString::rfind(char ch
, size_t nStart
) const
929 wxASSERT( nStart
<= Len() );
931 const char *p
= strrchr(c_str() + nStart
, ch
);
933 return p
== NULL
? npos
: p
- c_str();
936 wxString
wxString::substr(size_t nStart
, size_t nLen
) const
938 // npos means 'take all'
942 wxASSERT( nStart
+ nLen
<= Len() );
944 return wxString(c_str() + nStart
, nLen
== npos
? 0 : nLen
);
947 wxString
& wxString::erase(size_t nStart
, size_t nLen
)
949 wxString
strTmp(c_str(), nStart
);
950 if ( nLen
!= npos
) {
951 wxASSERT( nStart
+ nLen
<= Len() );
953 strTmp
.append(c_str() + nStart
+ nLen
);
960 wxString
& wxString::replace(size_t nStart
, size_t nLen
, const char *sz
)
962 wxASSERT( nStart
+ nLen
<= Strlen(sz
) );
966 strTmp
.append(c_str(), nStart
);
968 strTmp
.append(c_str() + nStart
+ nLen
);
974 wxString
& wxString::replace(size_t nStart
, size_t nLen
, size_t nCount
, char ch
)
976 return replace(nStart
, nLen
, wxString(ch
, nCount
));
979 wxString
& wxString::replace(size_t nStart
, size_t nLen
,
980 const wxString
& str
, size_t nStart2
, size_t nLen2
)
982 return replace(nStart
, nLen
, str
.substr(nStart2
, nLen2
));
985 wxString
& wxString::replace(size_t nStart
, size_t nLen
,
986 const char* sz
, size_t nCount
)
988 return replace(nStart
, nLen
, wxString(sz
, nCount
));
991 #endif //std::string compatibility
993 // ============================================================================
995 // ============================================================================
997 // size increment = max(50% of current size, ARRAY_MAXSIZE_INCREMENT)
998 #define ARRAY_MAXSIZE_INCREMENT 4096
999 #ifndef ARRAY_DEFAULT_INITIAL_SIZE // also defined in dynarray.h
1000 #define ARRAY_DEFAULT_INITIAL_SIZE (16)
1003 #define STRING(p) ((wxString *)(&(p)))
1006 wxArrayString::wxArrayString()
1014 wxArrayString::wxArrayString(const wxArrayString
& src
)
1016 m_nSize
= src
.m_nSize
;
1017 m_nCount
= src
.m_nCount
;
1020 m_pItems
= new char *[m_nSize
];
1024 if ( m_nCount
!= 0 )
1025 memcpy(m_pItems
, src
.m_pItems
, m_nCount
*sizeof(char *));
1029 wxArrayString
& wxArrayString::operator=(const wxArrayString
& src
)
1033 m_nSize
= src
.m_nSize
;
1034 m_nCount
= src
.m_nCount
;
1037 m_pItems
= new char *[m_nSize
];
1041 if ( m_nCount
!= 0 )
1042 memcpy(m_pItems
, src
.m_pItems
, m_nCount
*sizeof(char *));
1048 void wxArrayString::Grow()
1050 // only do it if no more place
1051 if( m_nCount
== m_nSize
) {
1052 if( m_nSize
== 0 ) {
1053 // was empty, alloc some memory
1054 m_nSize
= ARRAY_DEFAULT_INITIAL_SIZE
;
1055 m_pItems
= new char *[m_nSize
];
1058 // add 50% but not too much
1059 size_t nIncrement
= m_nSize
>> 1;
1060 if ( nIncrement
> ARRAY_MAXSIZE_INCREMENT
)
1061 nIncrement
= ARRAY_MAXSIZE_INCREMENT
;
1062 m_nSize
+= nIncrement
;
1063 char **pNew
= new char *[m_nSize
];
1065 // copy data to new location
1066 memcpy(pNew
, m_pItems
, m_nCount
*sizeof(char *));
1068 // delete old memory (but do not release the strings!)
1076 void wxArrayString::Free()
1078 for ( size_t n
= 0; n
< m_nCount
; n
++ ) {
1079 STRING(m_pItems
[n
])->GetStringData()->Unlock();
1083 // deletes all the strings from the list
1084 void wxArrayString::Empty()
1091 // as Empty, but also frees memory
1092 void wxArrayString::Clear()
1104 wxArrayString::~wxArrayString()
1111 // pre-allocates memory (frees the previous data!)
1112 void wxArrayString::Alloc(size_t nSize
)
1114 wxASSERT( nSize
> 0 );
1116 // only if old buffer was not big enough
1117 if ( nSize
> m_nSize
) {
1120 m_pItems
= new char *[nSize
];
1127 // searches the array for an item (forward or backwards)
1129 // Robert Roebling (changed to bool from Bool)
1131 int wxArrayString::Index(const char *sz
, bool bCase
, bool bFromEnd
) const
1134 if ( m_nCount
> 0 ) {
1137 if ( STRING(m_pItems
[--ui
])->IsSameAs(sz
, bCase
) )
1144 for( uint ui
= 0; ui
< m_nCount
; ui
++ ) {
1145 if( STRING(m_pItems
[ui
])->IsSameAs(sz
, bCase
) )
1153 // add item at the end
1154 void wxArrayString::Add(const wxString
& src
)
1158 // the string data must not be deleted!
1159 src
.GetStringData()->Lock();
1160 m_pItems
[m_nCount
++] = (char *)src
.c_str();
1163 // add item at the given position
1164 void wxArrayString::Insert(const wxString
& src
, size_t nIndex
)
1166 wxCHECK( nIndex
<= m_nCount
);
1170 memmove(&m_pItems
[nIndex
+ 1], &m_pItems
[nIndex
],
1171 (m_nCount
- nIndex
)*sizeof(char *));
1173 src
.GetStringData()->Lock();
1174 m_pItems
[nIndex
] = (char *)src
.c_str();
1179 // removes item from array (by index)
1180 void wxArrayString::Remove(size_t nIndex
)
1182 wxCHECK( nIndex
<= m_nCount
);
1185 Item(nIndex
).GetStringData()->Unlock();
1187 memmove(&m_pItems
[nIndex
], &m_pItems
[nIndex
+ 1],
1188 (m_nCount
- nIndex
- 1)*sizeof(char *));
1192 // removes item from array (by value)
1193 void wxArrayString::Remove(const char *sz
)
1195 int iIndex
= Index(sz
);
1197 wxCHECK( iIndex
!= NOT_FOUND
);
1199 Remove((size_t)iIndex
);
1202 // sort array elements using passed comparaison function
1204 // Robert Roebling (changed to bool from Bool)
1206 void wxArrayString::Sort(bool bCase
, bool bReverse
)
1209 //qsort(m_pItems, m_nCount, sizeof(char *), fCmp);