X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/6b583d40a8cd1dd38de2ad84e650023b857f80f7..529e491ce038ad3a3aef4f3247ff7e16767d9734:/src/common/string.cpp diff --git a/src/common/string.cpp b/src/common/string.cpp index fcdca45d58..ed7a6a8670 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -36,6 +36,8 @@ #include #include "wx/hashmap.h" +#include "wx/vector.h" +#include "wx/xlocale.h" // string handling functions used by wxString: #if wxUSE_UNICODE_UTF8 @@ -50,6 +52,18 @@ #define wxStringStrlen wxStrlen #endif +// ---------------------------------------------------------------------------- +// global variables +// ---------------------------------------------------------------------------- + +namespace wxPrivate +{ + +static UntypedBufferData s_untypedNullData(NULL); + +UntypedBufferData * const untypedNullDataPtr = &s_untypedNullData; + +} // namespace wxPrivate // --------------------------------------------------------------------------- // static class variables definition @@ -1103,6 +1117,7 @@ size_t wxString::find_last_not_of(const wxOtherCharType* sz, size_t nStart, int wxString::CmpNoCase(const wxString& s) const { +#if wxUSE_UNICODE_UTF8 // FIXME-UTF8: use wxUniChar::ToLower/ToUpper once added const_iterator i1 = begin(); @@ -1126,6 +1141,9 @@ int wxString::CmpNoCase(const wxString& s) const else if ( len1 > len2 ) return 1; return 0; +#else // wxUSE_UNICODE_WCHAR or ANSI + return wxStricmp(m_impl.c_str(), s.m_impl.c_str()); +#endif } @@ -1381,30 +1399,62 @@ size_t wxString::Replace(const wxString& strOld, break; } } - else // general case + else if ( !bReplaceAll) + { + size_t pos = m_impl.find(strOld, 0); + if ( pos != npos ) + { + m_impl.replace(pos, strOld.m_impl.length(), strNew.m_impl); + uiCount = 1; + } + } + else // replace all occurrences { const size_t uiOldLen = strOld.m_impl.length(); const size_t uiNewLen = strNew.m_impl.length(); - for ( size_t pos = 0; ; ) + // first scan the string to find all positions at which the replacement + // should be made + wxVector replacePositions; + + size_t pos; + for ( pos = m_impl.find(strOld.m_impl, 0); + pos != npos; + pos = m_impl.find(strOld.m_impl, pos + uiOldLen)) { - pos = m_impl.find(strOld.m_impl, pos); - if ( pos == npos ) - break; + replacePositions.push_back(pos); + ++uiCount; + } - // replace this occurrence of the old string with the new one - m_impl.replace(pos, uiOldLen, strNew.m_impl); + if ( !uiCount ) + return 0; - // move up pos past the string that was replaced - pos += uiNewLen; + // allocate enough memory for the whole new string + wxString tmp; + tmp.m_impl.reserve(m_impl.length() + uiCount*(uiNewLen - uiOldLen)); - // increase replace count - uiCount++; + // copy this string to tmp doing replacements on the fly + size_t replNum = 0; + for ( pos = 0; replNum < uiCount; replNum++ ) + { + const size_t nextReplPos = replacePositions[replNum]; - // stop after the first one? - if ( !bReplaceAll ) - break; + if ( pos != nextReplPos ) + { + tmp.m_impl.append(m_impl, pos, nextReplPos - pos); + } + + tmp.m_impl.append(strNew.m_impl); + pos = nextReplPos + uiOldLen; } + + if ( pos != m_impl.length() ) + { + // append the rest of the string unchanged + tmp.m_impl.append(m_impl, pos, m_impl.length() - pos); + } + + swap(tmp); } return uiCount; @@ -1595,64 +1645,105 @@ int wxString::Find(wxUniChar ch, bool bFromEnd) const #define DO_IF_NOT_WINCE(x) #endif -#define WX_STRING_TO_INT_TYPE(out, base, func, T) \ - wxCHECK_MSG( out, false, _T("NULL output pointer") ); \ - wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") ); \ - \ +#define WX_STRING_TO_X_TYPE_START \ + wxCHECK_MSG( pVal, false, _T("NULL output pointer") ); \ DO_IF_NOT_WINCE( errno = 0; ) \ - \ const wxStringCharType *start = wx_str(); \ - wxStringCharType *end; \ - T val = func(start, &end, base); \ - \ + wxStringCharType *end; + +#define WX_STRING_TO_X_TYPE_END \ /* return true only if scan was stopped by the terminating NUL and */ \ /* if the string was not empty to start with and no under/overflow */ \ /* occurred: */ \ if ( *end || end == start DO_IF_NOT_WINCE(|| errno == ERANGE) ) \ return false; \ - *out = val; \ - return true + *pVal = val; \ + return true; bool wxString::ToLong(long *pVal, int base) const { - WX_STRING_TO_INT_TYPE(pVal, base, wxStrtol, long); + wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") ); + + WX_STRING_TO_X_TYPE_START + long val = wxStrtol(start, &end, base); + WX_STRING_TO_X_TYPE_END } bool wxString::ToULong(unsigned long *pVal, int base) const { - WX_STRING_TO_INT_TYPE(pVal, base, wxStrtoul, unsigned long); + wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") ); + + WX_STRING_TO_X_TYPE_START + unsigned long val = wxStrtoul(start, &end, base); + WX_STRING_TO_X_TYPE_END } bool wxString::ToLongLong(wxLongLong_t *pVal, int base) const { - WX_STRING_TO_INT_TYPE(pVal, base, wxStrtoll, wxLongLong_t); + wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") ); + + WX_STRING_TO_X_TYPE_START + wxLongLong_t val = wxStrtoll(start, &end, base); + WX_STRING_TO_X_TYPE_END } bool wxString::ToULongLong(wxULongLong_t *pVal, int base) const { - WX_STRING_TO_INT_TYPE(pVal, base, wxStrtoull, wxULongLong_t); + wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") ); + + WX_STRING_TO_X_TYPE_START + wxULongLong_t val = wxStrtoull(start, &end, base); + WX_STRING_TO_X_TYPE_END } bool wxString::ToDouble(double *pVal) const { - wxCHECK_MSG( pVal, false, _T("NULL output pointer") ); + WX_STRING_TO_X_TYPE_START + double val = wxStrtod(start, &end); + WX_STRING_TO_X_TYPE_END +} - DO_IF_NOT_WINCE( errno = 0; ) +#if wxUSE_XLOCALE - const wxChar *start = c_str(); - wxChar *end; - double val = wxStrtod(start, &end); +bool wxString::ToCLong(long *pVal, int base) const +{ + wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") ); - // return true only if scan was stopped by the terminating NUL and if the - // string was not empty to start with and no under/overflow occurred - if ( *end || end == start DO_IF_NOT_WINCE(|| errno == ERANGE) ) - return false; + WX_STRING_TO_X_TYPE_START +#if wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE + long val = wxStrtol_lA(start, &end, base, wxCLocale); +#else + long val = wxStrtol_l(start, &end, base, wxCLocale); +#endif + WX_STRING_TO_X_TYPE_END +} - *pVal = val; +bool wxString::ToCULong(unsigned long *pVal, int base) const +{ + wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") ); - return true; + WX_STRING_TO_X_TYPE_START +#if wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE + unsigned long val = wxStrtoul_lA(start, &end, base, wxCLocale); +#else + unsigned long val = wxStrtoul_l(start, &end, base, wxCLocale); +#endif + WX_STRING_TO_X_TYPE_END +} + +bool wxString::ToCDouble(double *pVal) const +{ + WX_STRING_TO_X_TYPE_START +#if wxUSE_UNICODE_UTF8 || !wxUSE_UNICODE + double val = wxStrtod_lA(start, &end, wxCLocale); +#else + double val = wxStrtod_l(start, &end, wxCLocale); +#endif + WX_STRING_TO_X_TYPE_END } +#endif // wxUSE_XLOCALE + // --------------------------------------------------------------------------- // formatted output // --------------------------------------------------------------------------- @@ -2096,3 +2187,4 @@ int wxString::Freq(wxUniChar ch) const } return count; } +