X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6001e347baf63a91be525f3b9beeefde4bc16f19..5e84fc5a820a15a1ce2d32d2ae71f0bf92abda3d:/src/common/string.cpp diff --git a/src/common/string.cpp b/src/common/string.cpp index b7221a429a..c18e35f606 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -36,7 +36,7 @@ #include "wx/string.h" #include "wx/intl.h" #if wxUSE_THREADS - #include + #include "wx/thread.h" #endif #endif @@ -85,10 +85,10 @@ static const struct { wxStringData data; wxChar dummy; -} g_strEmpty = { {-1, 0, 0}, _T('\0') }; +} g_strEmpty = { {-1, 0, 0}, wxT('\0') }; // 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 @@ -176,6 +176,12 @@ 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 // ---------------------------------------------------------------------------- @@ -284,7 +290,7 @@ wxString::wxString(const char *psz, wxMBConv& conv, size_t nLength) } } -#else +#else // ANSI #if wxUSE_WCHAR_T // from wide string @@ -302,9 +308,9 @@ wxString::wxString(const wchar_t *pwz) Init(); } } -#endif +#endif // wxUSE_WCHAR_T -#endif +#endif // Unicode/ANSI // --------------------------------------------------------------------------- // memory allocation @@ -327,7 +333,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 @@ -379,7 +385,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 @@ -461,7 +467,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 +569,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 +728,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 +768,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 @@ -882,7 +888,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 +930,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 @@ -958,7 +964,7 @@ int wxString::Find(const wxChar *pszSub) const wxString& wxString::operator<<(int i) { wxString res; - res.Printf(_T("%d"), i); + res.Printf(wxT("%d"), i); return (*this) << res; } @@ -966,7 +972,7 @@ wxString& wxString::operator<<(int i) wxString& wxString::operator<<(float f) { wxString res; - res.Printf(_T("%f"), f); + res.Printf(wxT("%f"), f); return (*this) << res; } @@ -974,7 +980,7 @@ wxString& wxString::operator<<(float f) wxString& wxString::operator<<(double d) { wxString res; - res.Printf(_T("%g"), d); + res.Printf(wxT("%g"), d); return (*this) << res; } @@ -1011,7 +1017,7 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr) 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 +1027,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 +1093,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,12 +1109,12 @@ 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'; @@ -1140,11 +1146,11 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr) *this += wxString(s_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'; @@ -1158,7 +1164,7 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr) *this += wxString(s_szScratch); done = TRUE; break; - case _T('p'): + case wxT('p'): { void *val = va_arg(argptr, void *); CHECK_PREC @@ -1169,7 +1175,7 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr) 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 +1183,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 +1194,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]); - + // the strings with another array because strings are ref counted +#if 0 if ( m_nCount != 0 ) memcpy(m_pItems, src.m_pItems, m_nCount*sizeof(wxChar *)); +#endif // 0 - return *this; + for ( size_t n = 0; n < src.m_nCount; n++ ) + Add(src[n]); + + // if the other array is auto sorted too, we're already sorted, but + // otherwise we should rearrange the items + if ( m_autoSort && !src.m_autoSort ) + Sort(); } // grow the array @@ -1685,8 +1709,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 ); @@ -1779,20 +1803,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; + } } } @@ -1800,15 +1850,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 @@ -1816,7 +1898,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(); @@ -1832,7 +1914,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(); @@ -1848,7 +1930,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); } @@ -1928,6 +2010,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);