X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/9f96b16267a51aadbb9c388f5c3bc028fd9e9387..594f0f5bf1355fb8d58f403d3ebacc1c1767c429:/src/common/string.cpp diff --git a/src/common/string.cpp b/src/common/string.cpp index b0550b816f..7f856761a9 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -38,6 +38,8 @@ #include "wx/thread.h" #endif +#include "wx/regex.h" // for wxString::Matches() + #include #include #include @@ -46,10 +48,6 @@ #include #endif -#if wxUSE_WCSRTOMBS - #include // for wcsrtombs(), see comments where it's used -#endif // GNU - #ifdef WXSTRING_IS_WXOBJECT IMPLEMENT_DYNAMIC_CLASS(wxString, wxObject) #endif //WXSTRING_IS_WXOBJECT @@ -68,6 +66,12 @@ // static class variables definition // --------------------------------------------------------------------------- +#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 // Visual Age + #ifdef wxSTD_STRING_COMPATIBILITY const size_t wxString::npos = wxSTRING_MAXLEN; #endif // wxSTD_STRING_COMPATIBILITY @@ -85,12 +89,6 @@ static const struct wxChar dummy; } 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 *wxEmptyString = &g_strEmpty.dummy; @@ -153,7 +151,7 @@ extern const wxChar WXDLLEXPORT *wxEmptyString = &g_strEmpty.dummy; // // ATTN: you can _not_ use both of these in the same program! -istream& operator>>(istream& is, wxString& WXUNUSED(str)) +wxSTD istream& operator>>(wxSTD istream& is, wxString& WXUNUSED(str)) { #if 0 int w = is.width(0); @@ -184,7 +182,7 @@ istream& operator>>(istream& is, wxString& WXUNUSED(str)) return is; } -ostream& operator<<(ostream& os, const wxString& str) +wxSTD ostream& operator<<(wxSTD ostream& os, const wxString& str) { os << str.c_str(); return os; @@ -201,7 +199,8 @@ extern int WXDLLEXPORT wxVsnprintf(wxChar *buf, size_t len, int iLen = s.PrintfV(format, argptr); if ( iLen != -1 ) { - wxStrncpy(buf, s.c_str(), iLen); + wxStrncpy(buf, s.c_str(), len); + buf[len-1] = wxT('\0'); } return iLen; @@ -588,6 +587,7 @@ wxString& wxString::operator=(wxChar ch) return *this; } + // assigns C string wxString& wxString::operator=(const wxChar *psz) { @@ -1455,21 +1455,77 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr) // of them) bool wxString::Matches(const wxChar *pszMask) const { - // check char by char - const wxChar *pszTxt; - for ( pszTxt = c_str(); *pszMask != wxT('\0'); pszMask++, pszTxt++ ) { +#if wxUSE_REGEX + // first translate the shell-like mask into a regex + wxString pattern; + pattern.reserve(wxStrlen(pszMask)); + + pattern += _T('^'); + while ( *pszMask ) + { + switch ( *pszMask ) + { + case _T('?'): + pattern += _T('.'); + break; + + case _T('*'): + pattern += _T(".*"); + break; + + case _T('^'): + case _T('.'): + case _T('$'): + case _T('('): + case _T(')'): + case _T('|'): + case _T('+'): + case _T('\\'): + // these characters are special in a RE, quote them + // (however note that we don't quote '[' and ']' to allow + // using them for Unix shell like matching) + pattern += _T('\\'); + // fall through + + default: + pattern += *pszMask; + } + + pszMask++; + } + pattern += _T('$'); + + // and now use it + return wxRegEx(pattern, wxRE_NOSUB | wxRE_EXTENDED).Matches(c_str()); +#else // !wxUSE_REGEX + // TODO: this is, of course, awfully inefficient... + + // the char currently being checked + const wxChar *pszTxt = c_str(); + + // the last location where '*' matched + const wxChar *pszLastStarInText = NULL; + const wxChar *pszLastStarInMask = NULL; + +match: + for ( ; *pszMask != wxT('\0'); pszMask++, pszTxt++ ) { switch ( *pszMask ) { case wxT('?'): if ( *pszTxt == wxT('\0') ) return FALSE; - // pszText and pszMask will be incremented in the loop statement + // pszTxt and pszMask will be incremented in the loop statement break; case wxT('*'): { + // remember where we started to be able to backtrack later + pszLastStarInText = pszTxt; + pszLastStarInMask = pszMask; + // ignore special chars immediately following this one + // (should this be an error?) while ( *pszMask == wxT('*') || *pszMask == wxT('?') ) pszMask++; @@ -1509,7 +1565,23 @@ bool wxString::Matches(const wxChar *pszMask) const } // match only if nothing left - return *pszTxt == wxT('\0'); + if ( *pszTxt == wxT('\0') ) + return TRUE; + + // if we failed to match, backtrack if we can + if ( pszLastStarInText ) { + pszTxt = pszLastStarInText + 1; + pszMask = pszLastStarInMask; + + pszLastStarInText = NULL; + + // don't bother resetting pszLastStarInMask, it's unnecessary + + goto match; + } + + return FALSE; +#endif // wxUSE_REGEX/!wxUSE_REGEX } // Count the number of chars @@ -1853,6 +1925,8 @@ wxArrayString& wxArrayString::operator=(const wxArrayString& src) Copy(src); + m_autoSort = src.m_autoSort; + return *this; } @@ -1869,8 +1943,14 @@ void wxArrayString::Copy(const wxArrayString& src) void wxArrayString::Grow() { // only do it if no more place - if( m_nCount == m_nSize ) { - if( m_nSize == 0 ) { + if ( m_nCount == m_nSize ) { + // if ARRAY_DEFAULT_INITIAL_SIZE were set to 0, the initially empty would + // be never resized! + #if ARRAY_DEFAULT_INITIAL_SIZE == 0 + #error "ARRAY_DEFAULT_INITIAL_SIZE must be > 0!" + #endif + + if ( m_nSize == 0 ) { // was empty, alloc some memory m_nSize = ARRAY_DEFAULT_INITIAL_SIZE; m_pItems = new wxChar *[m_nSize]; @@ -1878,13 +1958,6 @@ 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__) && defined(__WXDEBUG__) - int array_size = ARRAY_DEFAULT_INITIAL_SIZE; - wxASSERT( array_size != 0 ); -#else - wxASSERT( ARRAY_DEFAULT_INITIAL_SIZE != 0 ); -#endif - // add 50% but not too much size_t nIncrement = m_nSize < ARRAY_DEFAULT_INITIAL_SIZE ? ARRAY_DEFAULT_INITIAL_SIZE : m_nSize >> 1;