X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/0c5d3e1ccd1d27ab0cf913ddbffb1b54b5802f3a..f5ba273ecd799f652736ce2bc830283787302a56:/src/common/string.cpp diff --git a/src/common/string.cpp b/src/common/string.cpp index baa9fafce3..bd4dc94a62 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -35,9 +35,7 @@ #include "wx/defs.h" #include "wx/string.h" #include "wx/intl.h" -#if wxUSE_THREADS - #include -#endif + #include "wx/thread.h" #endif #include @@ -85,10 +83,16 @@ static const struct { wxStringData data; wxChar dummy; -} g_strEmpty = { {-1, 0, 0}, _T('\0') }; +} g_strEmpty = { {-1, 0, 0}, wxT('\0') }; + +#if defined(__VISAGECPP__) && __IBMCPP__ >= 400 +// must define this static for VA or else you get multiply defined symbols everywhere +const unsigned int wxSTRING_MAXLEN = UINT_MAX - 100; + +#endif // empty C style string: points to 'string data' byte of g_strEmpty -extern const wxChar WXDLLEXPORT *g_szNul = &g_strEmpty.dummy; +extern const wxChar WXDLLEXPORT *wxEmptyString = &g_strEmpty.dummy; // ---------------------------------------------------------------------------- // conditional compilation @@ -104,28 +108,32 @@ extern const wxChar WXDLLEXPORT *g_szNul = &g_strEmpty.dummy; // we want to find out if the current platform supports vsnprintf()-like // function: for Unix this is done with configure, for Windows we test the // compiler explicitly. +// +// FIXME currently, this is only for ANSI (!Unicode) strings, so we call this +// function wxVsnprintfA (A for ANSI), should also find one for Unicode +// strings in Unicode build #ifdef __WXMSW__ - #ifdef __VISUALC__ - #define wxVsnprintf _vsnprintf + #if defined(__VISUALC__) || wxUSE_NORLANDER_HEADERS + #define wxVsnprintfA _vsnprintf #endif #else // !Windows #ifdef HAVE_VSNPRINTF - #define wxVsnprintf vsnprintf + #define wxVsnprintfA vsnprintf #endif #endif // Windows/!Windows -#ifndef wxVsnprintf +#ifndef wxVsnprintfA // in this case we'll use vsprintf() (which is ANSI and thus should be // always available), but it's unsafe because it doesn't check for buffer // size - so give a warning - #define wxVsnprintf(buffer,len,format,argptr) vsprintf(buffer,format, argptr) + #define wxVsnprintfA(buf, len, format, arg) vsprintf(buf, format, arg) #if defined(__VISUALC__) #pragma message("Using sprintf() because no snprintf()-like function defined") #elif defined(__GNUG__) && !defined(__UNIX__) #warning "Using sprintf() because no snprintf()-like function defined" #elif defined(__MWERKS__) - #warning "Using sprintf() because no snprintf()-like function defined" + #warning "Using sprintf() because no snprintf()-like function defined" #endif //compiler #endif // no vsnprintf @@ -176,8 +184,53 @@ istream& operator>>(istream& is, wxString& WXUNUSED(str)) return is; } +ostream& operator<<(ostream& os, const wxString& str) +{ + os << str.c_str(); + return os; +} + #endif //std::string compatibility +extern int WXDLLEXPORT wxVsnprintf(wxChar *buf, size_t len, + const wxChar *format, va_list argptr) +{ +#if wxUSE_UNICODE + // FIXME should use wvsnprintf() or whatever if it's available + wxString s; + int iLen = s.PrintfV(format, argptr); + if ( iLen != -1 ) + { + wxStrncpy(buf, s.c_str(), iLen); + } + + return iLen; +#else // ANSI + // vsnprintf() will not terminate the string with '\0' if there is not + // enough place, but we want the string to always be NUL terminated + int rc = wxVsnprintfA(buf, len - 1, format, argptr); + if ( rc == -1 ) + { + buf[len] = 0; + } + + return rc; +#endif // Unicode/ANSI +} + +extern int WXDLLEXPORT wxSnprintf(wxChar *buf, size_t len, + const wxChar *format, ...) +{ + va_list argptr; + va_start(argptr, format); + + int iLen = wxVsnprintf(buf, len, format, argptr); + + va_end(argptr); + + return iLen; +} + // ---------------------------------------------------------------------------- // private classes // ---------------------------------------------------------------------------- @@ -237,11 +290,11 @@ void wxString::InitWith(const wxChar *psz, size_t nPos, size_t nLength) { Init(); - wxASSERT( nPos <= wxStrlen(psz) ); - if ( nLength == wxSTRING_MAXLEN ) nLength = wxStrlen(psz + nPos); + wxASSERT_MSG( nPos + nLength <= wxStrlen(psz), _T("index out of bounds") ); + STATISTICS_ADD(InitialLength, nLength); if ( nLength > 0 ) { @@ -284,7 +337,7 @@ wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength) } } -#else +#else // ANSI #if wxUSE_WCHAR_T // from wide string @@ -302,9 +355,9 @@ wxString::wxString(const wchar_t *pwz) Init(); } } -#endif +#endif // wxUSE_WCHAR_T -#endif +#endif // Unicode/ANSI // --------------------------------------------------------------------------- // memory allocation @@ -313,8 +366,13 @@ wxString::wxString(const wchar_t *pwz) // allocates memory needed to store a C string of length nLen void wxString::AllocBuffer(size_t nLen) { - wxASSERT( nLen > 0 ); // - wxASSERT( nLen <= INT_MAX-1 ); // max size (enough room for 1 extra) + // allocating 0 sized buffer doesn't make sense, all empty strings should + // reuse g_strEmpty + wxASSERT( nLen > 0 ); + + // make sure that we don't overflow + wxASSERT( nLen < (INT_MAX / sizeof(wxChar)) - + (sizeof(wxStringData) + EXTRA_ALLOC + 1) ); STATISTICS_ADD(Length, nLen); @@ -327,7 +385,7 @@ void wxString::AllocBuffer(size_t nLen) pData->nDataLength = nLen; pData->nAllocLength = nLen + EXTRA_ALLOC; m_pchData = pData->data(); // data starts after wxStringData - m_pchData[nLen] = _T('\0'); + m_pchData[nLen] = wxT('\0'); } // must be called before changing this string @@ -352,13 +410,35 @@ void wxString::AllocBeforeWrite(size_t nLen) // must not share string and must have enough space wxStringData* pData = GetStringData(); - if ( pData->IsShared() || (nLen > pData->nAllocLength) ) { + if ( pData->IsShared() || pData->IsEmpty() ) { // can't work with old buffer, get new one pData->Unlock(); AllocBuffer(nLen); } else { - // update the string length + if ( nLen > pData->nAllocLength ) { + // realloc the buffer instead of calling malloc() again, this is more + // efficient + STATISTICS_ADD(Length, nLen); + + nLen += EXTRA_ALLOC; + + wxStringData *pDataOld = pData; + pData = (wxStringData*) + realloc(pData, sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar)); + if ( !pData ) { + // out of memory + free(pDataOld); + + // FIXME we're going to crash... + return; + } + + pData->nAllocLength = nLen; + m_pchData = pData->data(); + } + + // now we have enough space, just update the string length pData->nDataLength = nLen; } @@ -379,7 +459,7 @@ void wxString::Alloc(size_t nLen) pData->nDataLength = 0; pData->nAllocLength = nLen; m_pchData = pData->data(); // data starts after wxStringData - m_pchData[0u] = _T('\0'); + m_pchData[0u] = wxT('\0'); } else if ( pData->IsShared() ) { pData->Unlock(); // memory not freed because shared @@ -390,11 +470,15 @@ void wxString::Alloc(size_t nLen) else { nLen += EXTRA_ALLOC; + wxStringData *pDataOld = pData; wxStringData *p = (wxStringData *) realloc(pData, sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar)); if ( p == NULL ) { - // @@@ what to do on memory error? + // don't leak memory + free(pDataOld); + + // FIXME what to do on memory error? return; } @@ -412,13 +496,16 @@ void wxString::Shrink() { wxStringData *pData = GetStringData(); - // this variable is unused in release build, so avoid the compiler warning by - // just not declaring it + // this variable is unused in release build, so avoid the compiler warning + // by just not declaring it #ifdef __WXDEBUG__ void *p = #endif realloc(pData, sizeof(wxStringData) + (pData->nDataLength + 1)*sizeof(wxChar)); + // we rely on a reasonable realloc() implementation here - so far I haven't + // seen any which wouldn't behave like this + wxASSERT( p != NULL ); // can't free memory? wxASSERT( p == pData ); // we're decrementing the size - block shouldn't move! } @@ -441,6 +528,12 @@ void wxString::UngetWriteBuf() GetStringData()->Validate(TRUE); } +void wxString::UngetWriteBuf(size_t nLen) +{ + GetStringData()->nDataLength = nLen; + GetStringData()->Validate(TRUE); +} + // --------------------------------------------------------------------------- // data access // --------------------------------------------------------------------------- @@ -461,7 +554,7 @@ void wxString::AssignCopy(size_t nSrcLen, const wxChar *pszSrcData) AllocBeforeWrite(nSrcLen); memcpy(m_pchData, pszSrcData, nSrcLen*sizeof(wxChar)); GetStringData()->nDataLength = nSrcLen; - m_pchData[nSrcLen] = _T('\0'); + m_pchData[nSrcLen] = wxT('\0'); } } @@ -563,7 +656,7 @@ void wxString::ConcatSelf(int nSrcLen, const wxChar *pszSrcData) // fast concatenation - all is done in our buffer memcpy(m_pchData + nLen, pszSrcData, nSrcLen*sizeof(wxChar)); - m_pchData[nNewLen] = _T('\0'); // put terminating '\0' + m_pchData[nNewLen] = wxT('\0'); // put terminating '\0' GetStringData()->nDataLength = nNewLen; // and fix the length } //else: the string to append was empty @@ -722,7 +815,7 @@ wxString wxString::Left(size_t nCount) const wxString wxString::BeforeFirst(wxChar ch) const { wxString str; - for ( const wxChar *pc = m_pchData; *pc != _T('\0') && *pc != ch; pc++ ) + for ( const wxChar *pc = m_pchData; *pc != wxT('\0') && *pc != ch; pc++ ) str += *pc; return str; @@ -762,7 +855,7 @@ size_t wxString::Replace(const wxChar *szOld, const wxChar *szNew, bool bReplace wxString strTemp; const wxChar *pCurrent = m_pchData; const wxChar *pSubstr; - while ( *pCurrent != _T('\0') ) { + while ( *pCurrent != wxT('\0') ) { pSubstr = wxStrstr(pCurrent, szOld); if ( pSubstr == NULL ) { // strTemp is unused if no replacements were made, so avoid the copy @@ -817,6 +910,8 @@ bool wxString::IsWord() const bool wxString::IsNumber() const { const wxChar *s = (const wxChar*) *this; + if (wxStrlen(s)) + if ((s[0] == '-') || (s[0] == '+')) s++; while(*s){ if(!wxIsdigit(*s)) return(FALSE); s++; @@ -882,7 +977,7 @@ wxString& wxString::Trim(bool bFromRight) psz--; // truncate at trailing space start - *++psz = _T('\0'); + *++psz = wxT('\0'); GetStringData()->nDataLength = psz - m_pchData; } else @@ -924,7 +1019,7 @@ wxString& wxString::Truncate(size_t uiLen) if ( uiLen < Len() ) { CopyBeforeWrite(); - *(m_pchData + uiLen) = _T('\0'); + *(m_pchData + uiLen) = wxT('\0'); GetStringData()->nDataLength = uiLen; } //else: nothing to do, string is already short enough @@ -952,36 +1047,75 @@ int wxString::Find(const wxChar *pszSub) const return (psz == NULL) ? wxNOT_FOUND : psz - (const wxChar*) m_pchData; } -// --------------------------------------------------------------------------- -// stream-like operators -// --------------------------------------------------------------------------- -wxString& wxString::operator<<(int i) +// ---------------------------------------------------------------------------- +// conversion to numbers +// ---------------------------------------------------------------------------- + +bool wxString::ToLong(long *val) const { - wxString res; - res.Printf(_T("%d"), i); + wxCHECK_MSG( val, FALSE, _T("NULL pointer in wxString::ToLong") ); - return (*this) << res; + const wxChar *start = c_str(); + wxChar *end; + *val = wxStrtol(start, &end, 10); + + // return TRUE only if scan was stopped by the terminating NUL and if the + // string was not empty to start with + return !*end && (end != start); } -wxString& wxString::operator<<(float f) +bool wxString::ToULong(unsigned long *val) const { - wxString res; - res.Printf(_T("%f"), f); + wxCHECK_MSG( val, FALSE, _T("NULL pointer in wxString::ToULong") ); + + const wxChar *start = c_str(); + wxChar *end; + *val = wxStrtoul(start, &end, 10); - return (*this) << res; + // return TRUE only if scan was stopped by the terminating NUL and if the + // string was not empty to start with + return !*end && (end != start); } -wxString& wxString::operator<<(double d) +bool wxString::ToDouble(double *val) const { - wxString res; - res.Printf(_T("%g"), d); + wxCHECK_MSG( val, FALSE, _T("NULL pointer in wxString::ToDouble") ); - return (*this) << res; + const wxChar *start = c_str(); + wxChar *end; + *val = wxStrtod(start, &end); + + // return TRUE only if scan was stopped by the terminating NUL and if the + // string was not empty to start with + return !*end && (end != start); } // --------------------------------------------------------------------------- // formatted output // --------------------------------------------------------------------------- + +/* static */ +wxString wxString::Format(const wxChar *pszFormat, ...) +{ + va_list argptr; + va_start(argptr, pszFormat); + + wxString s; + s.PrintfV(pszFormat, argptr); + + va_end(argptr); + + return s; +} + +/* static */ +wxString wxString::FormatV(const wxChar *pszFormat, va_list argptr) +{ + wxString s; + s.Printf(pszFormat, argptr); + return s; +} + int wxString::Printf(const wxChar *pszFormat, ...) { va_list argptr; @@ -996,22 +1130,15 @@ int wxString::Printf(const wxChar *pszFormat, ...) int wxString::PrintfV(const wxChar* pszFormat, va_list argptr) { - // static buffer to avoid dynamic memory allocation each time - char s_szScratch[1024]; // using static buffer causes internal compiler err -#if 0 -#if wxUSE_THREADS - // protect the static buffer - static wxCriticalSection critsect; - wxCriticalSectionLocker lock(critsect); -#endif -#endif - #if wxUSE_EXPERIMENTAL_PRINTF -// the new implementation + // the new implementation + + // buffer to avoid dynamic memory allocation each time for small strings + char szScratch[1024]; Reinit(); for (size_t n = 0; pszFormat[n]; n++) - if (pszFormat[n] == _T('%')) { + if (pszFormat[n] == wxT('%')) { static char s_szFlags[256] = "%"; size_t flagofs = 1; bool adj_left = FALSE, in_prec = FALSE, @@ -1021,55 +1148,55 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr) do { #define CHECK_PREC if (in_prec && !prec_dot) { s_szFlags[flagofs++] = '.'; prec_dot = TRUE; } switch (pszFormat[++n]) { - case _T('\0'): + case wxT('\0'): done = TRUE; break; - case _T('%'): - *this += _T('%'); + case wxT('%'): + *this += wxT('%'); done = TRUE; break; - case _T('#'): - case _T('0'): - case _T(' '): - case _T('+'): - case _T('\''): + case wxT('#'): + case wxT('0'): + case wxT(' '): + case wxT('+'): + case wxT('\''): CHECK_PREC s_szFlags[flagofs++] = pszFormat[n]; break; - case _T('-'): + case wxT('-'): CHECK_PREC adj_left = TRUE; s_szFlags[flagofs++] = pszFormat[n]; break; - case _T('.'): + case wxT('.'): CHECK_PREC in_prec = TRUE; prec_dot = FALSE; max_width = 0; // dot will be auto-added to s_szFlags if non-negative number follows break; - case _T('h'): + case wxT('h'): ilen = -1; CHECK_PREC s_szFlags[flagofs++] = pszFormat[n]; break; - case _T('l'): + case wxT('l'): ilen = 1; CHECK_PREC s_szFlags[flagofs++] = pszFormat[n]; break; - case _T('q'): - case _T('L'): + case wxT('q'): + case wxT('L'): ilen = 2; CHECK_PREC s_szFlags[flagofs++] = pszFormat[n]; break; - case _T('Z'): + case wxT('Z'): ilen = 3; CHECK_PREC s_szFlags[flagofs++] = pszFormat[n]; break; - case _T('*'): + case wxT('*'): { int len = va_arg(argptr, int); if (in_prec) { @@ -1087,15 +1214,15 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr) flagofs += ::sprintf(s_szFlags+flagofs,"%d",len); } break; - case _T('1'): case _T('2'): case _T('3'): - case _T('4'): case _T('5'): case _T('6'): - case _T('7'): case _T('8'): case _T('9'): + case wxT('1'): case wxT('2'): case wxT('3'): + case wxT('4'): case wxT('5'): case wxT('6'): + case wxT('7'): case wxT('8'): case wxT('9'): { int len = 0; CHECK_PREC - while ((pszFormat[n]>=_T('0')) && (pszFormat[n]<=_T('9'))) { + while ((pszFormat[n]>=wxT('0')) && (pszFormat[n]<=wxT('9'))) { s_szFlags[flagofs++] = pszFormat[n]; - len = len*10 + (pszFormat[n] - _T('0')); + len = len*10 + (pszFormat[n] - wxT('0')); n++; } if (in_prec) max_width = len; @@ -1103,73 +1230,73 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr) n--; // the main loop pre-increments n again } break; - case _T('d'): - case _T('i'): - case _T('o'): - case _T('u'): - case _T('x'): - case _T('X'): + case wxT('d'): + case wxT('i'): + case wxT('o'): + case wxT('u'): + case wxT('x'): + case wxT('X'): CHECK_PREC s_szFlags[flagofs++] = pszFormat[n]; s_szFlags[flagofs] = '\0'; if (ilen == 0 ) { int val = va_arg(argptr, int); - ::sprintf(s_szScratch, s_szFlags, val); + ::sprintf(szScratch, s_szFlags, val); } else if (ilen == -1) { short int val = va_arg(argptr, short int); - ::sprintf(s_szScratch, s_szFlags, val); + ::sprintf(szScratch, s_szFlags, val); } else if (ilen == 1) { long int val = va_arg(argptr, long int); - ::sprintf(s_szScratch, s_szFlags, val); + ::sprintf(szScratch, s_szFlags, val); } else if (ilen == 2) { #if SIZEOF_LONG_LONG long long int val = va_arg(argptr, long long int); - ::sprintf(s_szScratch, s_szFlags, val); + ::sprintf(szScratch, s_szFlags, val); #else long int val = va_arg(argptr, long int); - ::sprintf(s_szScratch, s_szFlags, val); + ::sprintf(szScratch, s_szFlags, val); #endif } else if (ilen == 3) { size_t val = va_arg(argptr, size_t); - ::sprintf(s_szScratch, s_szFlags, val); + ::sprintf(szScratch, s_szFlags, val); } - *this += wxString(s_szScratch); + *this += wxString(szScratch); done = TRUE; break; - case _T('e'): - case _T('E'): - case _T('f'): - case _T('g'): - case _T('G'): + case wxT('e'): + case wxT('E'): + case wxT('f'): + case wxT('g'): + case wxT('G'): CHECK_PREC s_szFlags[flagofs++] = pszFormat[n]; s_szFlags[flagofs] = '\0'; if (ilen == 2) { long double val = va_arg(argptr, long double); - ::sprintf(s_szScratch, s_szFlags, val); + ::sprintf(szScratch, s_szFlags, val); } else { double val = va_arg(argptr, double); - ::sprintf(s_szScratch, s_szFlags, val); + ::sprintf(szScratch, s_szFlags, val); } - *this += wxString(s_szScratch); + *this += wxString(szScratch); done = TRUE; break; - case _T('p'): + case wxT('p'): { void *val = va_arg(argptr, void *); CHECK_PREC s_szFlags[flagofs++] = pszFormat[n]; s_szFlags[flagofs] = '\0'; - ::sprintf(s_szScratch, s_szFlags, val); - *this += wxString(s_szScratch); + ::sprintf(szScratch, s_szFlags, val); + *this += wxString(szScratch); done = TRUE; } break; - case _T('c'): + case wxT('c'): { wxChar val = va_arg(argptr, int); // we don't need to honor padding here, do we? @@ -1177,7 +1304,7 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr) done = TRUE; } break; - case _T('s'): + case wxT('s'): if (ilen == -1) { // wx extension: we'll let %hs mean non-Unicode strings char *val = va_arg(argptr, char *); @@ -1188,26 +1315,26 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr) size_t len = wxSTRING_MAXLEN; if (val) { for (len = 0; val[len] && (len 0 ) Clear(); + Copy(src); + + return *this; +} + +void wxArrayString::Copy(const wxArrayString& src) +{ if ( src.m_nCount > ARRAY_DEFAULT_INITIAL_SIZE ) Alloc(src.m_nCount); - // we can't just copy the pointers here because otherwise we would share - // the strings with another array for ( size_t n = 0; n < src.m_nCount; n++ ) Add(src[n]); - - if ( m_nCount != 0 ) - memcpy(m_pItems, src.m_pItems, m_nCount*sizeof(wxChar *)); - - return *this; } // grow the array @@ -1689,8 +1811,8 @@ void wxArrayString::Grow() else { // otherwise when it's called for the first time, nIncrement would be 0 // and the array would never be expanded -#if defined(__VISAGECPP__) - int array_size = ARRAY_DEFAULT_INITIAL_SIZE; +#if defined(__VISAGECPP__) && defined(__WXDEBUG__) + int array_size = ARRAY_DEFAULT_INITIAL_SIZE; wxASSERT( array_size != 0 ); #else wxASSERT( ARRAY_DEFAULT_INITIAL_SIZE != 0 ); @@ -1783,20 +1905,46 @@ void wxArrayString::Shrink() // searches the array for an item (forward or backwards) int wxArrayString::Index(const wxChar *sz, bool bCase, bool bFromEnd) const { - if ( bFromEnd ) { - if ( m_nCount > 0 ) { - size_t ui = m_nCount; - do { - if ( STRING(m_pItems[--ui])->IsSameAs(sz, bCase) ) - return ui; - } - while ( ui != 0 ); + if ( m_autoSort ) { + // use binary search in the sorted array + wxASSERT_MSG( bCase && !bFromEnd, + wxT("search parameters ignored for auto sorted array") ); + + size_t i, + lo = 0, + hi = m_nCount; + int res; + while ( lo < hi ) { + i = (lo + hi)/2; + + res = wxStrcmp(sz, m_pItems[i]); + if ( res < 0 ) + hi = i; + else if ( res > 0 ) + lo = i + 1; + else + return i; } + + return wxNOT_FOUND; } else { - for( size_t ui = 0; ui < m_nCount; ui++ ) { - if( STRING(m_pItems[ui])->IsSameAs(sz, bCase) ) - return ui; + // use linear search in unsorted array + if ( bFromEnd ) { + if ( m_nCount > 0 ) { + size_t ui = m_nCount; + do { + if ( STRING(m_pItems[--ui])->IsSameAs(sz, bCase) ) + return ui; + } + while ( ui != 0 ); + } + } + else { + for( size_t ui = 0; ui < m_nCount; ui++ ) { + if( STRING(m_pItems[ui])->IsSameAs(sz, bCase) ) + return ui; + } } } @@ -1804,15 +1952,47 @@ int wxArrayString::Index(const wxChar *sz, bool bCase, bool bFromEnd) const } // add item at the end -void wxArrayString::Add(const wxString& str) -{ - wxASSERT( str.GetStringData()->IsValid() ); +size_t wxArrayString::Add(const wxString& str) +{ + if ( m_autoSort ) { + // insert the string at the correct position to keep the array sorted + size_t i, + lo = 0, + hi = m_nCount; + int res; + while ( lo < hi ) { + i = (lo + hi)/2; + + res = wxStrcmp(str, m_pItems[i]); + if ( res < 0 ) + hi = i; + else if ( res > 0 ) + lo = i + 1; + else { + lo = hi = i; + break; + } + } - Grow(); + wxASSERT_MSG( lo == hi, wxT("binary search broken") ); - // the string data must not be deleted! - str.GetStringData()->Lock(); - m_pItems[m_nCount++] = (wxChar *)str.c_str(); + Insert(str, lo); + + return (size_t)lo; + } + else { + wxASSERT( str.GetStringData()->IsValid() ); + + Grow(); + + // the string data must not be deleted! + str.GetStringData()->Lock(); + + // just append + m_pItems[m_nCount] = (wxChar *)str.c_str(); // const_cast + + return m_nCount++; + } } // add item at the given position @@ -1820,7 +2000,7 @@ void wxArrayString::Insert(const wxString& str, size_t nIndex) { wxASSERT( str.GetStringData()->IsValid() ); - wxCHECK_RET( nIndex <= m_nCount, _("bad index in wxArrayString::Insert") ); + wxCHECK_RET( nIndex <= m_nCount, wxT("bad index in wxArrayString::Insert") ); Grow(); @@ -1836,7 +2016,7 @@ void wxArrayString::Insert(const wxString& str, size_t nIndex) // removes item from array (by index) void wxArrayString::Remove(size_t nIndex) { - wxCHECK_RET( nIndex <= m_nCount, _("bad index in wxArrayString::Remove") ); + wxCHECK_RET( nIndex <= m_nCount, wxT("bad index in wxArrayString::Remove") ); // release our lock Item(nIndex).GetStringData()->Unlock(); @@ -1852,7 +2032,7 @@ void wxArrayString::Remove(const wxChar *sz) int iIndex = Index(sz); wxCHECK_RET( iIndex != wxNOT_FOUND, - _("removing inexistent element in wxArrayString::Remove") ); + wxT("removing inexistent element in wxArrayString::Remove") ); Remove(iIndex); } @@ -1932,6 +2112,8 @@ void wxArrayString::Sort(bool reverseOrder) void wxArrayString::DoSort() { + wxCHECK_RET( !m_autoSort, wxT("can't use this method with sorted arrays") ); + // just sort the pointers using qsort() - of course it only works because // wxString() *is* a pointer to its data qsort(m_pItems, m_nCount, sizeof(wxChar *), wxStringCompareFunction);