X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/639e001d875797ec81217f6a9b8cd93285b02e80..931483d799fcac4a442b123d32b14282ee17dc8d:/src/common/string.cpp?ds=inline diff --git a/src/common/string.cpp b/src/common/string.cpp index 98a635bc49..4551c66931 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -35,6 +35,11 @@ #endif #include + +#ifndef __WXWINCE__ + #include +#endif + #include #include @@ -174,8 +179,16 @@ void wxStringBase::InitWith(const wxChar *psz, size_t nPos, size_t nLength) // poor man's iterators are "void *" pointers wxStringBase::wxStringBase(const void *pStart, const void *pEnd) { - InitWith((const wxChar *)pStart, 0, - (const wxChar *)pEnd - (const wxChar *)pStart); + if ( pEnd >= pStart ) + { + InitWith((const wxChar *)pStart, 0, + (const wxChar *)pEnd - (const wxChar *)pStart); + } + else + { + wxFAIL_MSG( _T("pStart is not before pEnd") ); + Init(); + } } wxStringBase::wxStringBase(size_type n, wxChar ch) @@ -434,36 +447,47 @@ void wxStringBase::swap(wxStringBase& str) size_t wxStringBase::find(const wxStringBase& str, size_t nStart) const { + // deal with the special case of empty string first + const size_t nLen = length(); + const size_t nLenOther = str.length(); + + if ( !nLenOther ) + { + // empty string is a substring of anything + return 0; + } + + if ( !nLen ) + { + // the other string is non empty so can't be our substring + return npos; + } + wxASSERT( str.GetStringData()->IsValid() ); - wxASSERT( nStart <= length() ); + wxASSERT( nStart <= nLen ); + + const wxChar * const other = str.c_str(); - //anchor + // anchor const wxChar* p = (const wxChar*)wxTmemchr(c_str() + nStart, - str.c_str()[0], - length() - nStart); + *other, + nLen - nStart); - if(!p) + if ( !p ) return npos; - while(p - c_str() + str.length() <= length() && - wxTmemcmp(p, str.c_str(), str.length()) ) + while ( p - c_str() + nLenOther <= nLen && wxTmemcmp(p, other, nLenOther) ) { - //Previosly passed as the first argument to wxTmemchr, - //but C/C++ standard does not specify evaluation order - //of arguments to functions - - //http://embedded.com/showArticle.jhtml?articleID=9900607 - ++p; - - //anchor again - p = (const wxChar*)wxTmemchr(p, - str.c_str()[0], - length() - (p - c_str())); - - if(!p) + p++; + + // anchor again + p = (const wxChar*)wxTmemchr(p, *other, nLen - (p - c_str())); + + if ( !p ) return npos; } - return (p - c_str() + str.length() <= length()) ? p - c_str() : npos; + return p - c_str() + nLenOther <= nLen ? p - c_str() : npos; } size_t wxStringBase::find(const wxChar* sz, size_t nStart, size_t n) const @@ -1584,7 +1608,7 @@ wxString& wxString::Trim(bool bFromRight) reverse_iterator psz = rbegin(); while ( (psz != rend()) && wxSafeIsspace(*psz) ) psz++; - + // truncate at trailing space start erase(psz.base(), end()); } @@ -1655,45 +1679,93 @@ int wxString::Find(const wxChar *pszSub) const // conversion to numbers // ---------------------------------------------------------------------------- -bool wxString::ToLong(long *val, int base) const +// the implementation of all the functions below is exactly the same so factor +// it out + +#ifdef __WATCOMC__ + #define STR2INTLINK _WCRTLINK +#else + #define STR2INTLINK +#endif + +template +bool wxStringToIntType(const wxChar *start, + T *val, + int base, + T STR2INTLINK (*func)(const wxChar *, wxChar **, int)) { - wxCHECK_MSG( val, false, _T("NULL pointer in wxString::ToLong") ); + wxCHECK_MSG( val, false, _T("NULL output pointer") ); wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") ); - const wxChar *start = c_str(); +#ifndef __WXWINCE__ + errno = 0; +#endif + wxChar *end; - *val = wxStrtol(start, &end, base); + *val = (*func)(start, &end, base); // 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); + // string was not empty to start with and no under/overflow occurred + return !*end && (end != start) +#ifndef __WXWINCE__ + && (errno != ERANGE) +#endif + ; +} + +bool wxString::ToLong(long *val, int base) const +{ + return wxStringToIntType(c_str(), val, base, wxStrtol); } bool wxString::ToULong(unsigned long *val, int base) const { - wxCHECK_MSG( val, false, _T("NULL pointer in wxString::ToULong") ); - wxASSERT_MSG( !base || (base > 1 && base <= 36), _T("invalid base") ); + return wxStringToIntType(c_str(), val, base, wxStrtoul); +} - const wxChar *start = c_str(); - wxChar *end; - *val = wxStrtoul(start, &end, base); +bool wxString::ToLongLong(wxLongLong_t *val, int base) const +{ +#ifdef wxHAS_STRTOLL + return wxStringToIntType(c_str(), val, base, wxStrtoll); +#else + // TODO: implement this ourselves + wxUnusedVar(val); + wxUnusedVar(base); + return false; +#endif // wxHAS_STRTOLL +} - // 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); +bool wxString::ToULongLong(wxULongLong_t *val, int base) const +{ +#ifdef wxHAS_STRTOLL + return wxStringToIntType(c_str(), val, base, wxStrtoull); +#else + // TODO: implement this ourselves + wxUnusedVar(val); + wxUnusedVar(base); + return false; +#endif } bool wxString::ToDouble(double *val) const { wxCHECK_MSG( val, false, _T("NULL pointer in wxString::ToDouble") ); +#ifndef __WXWINCE__ + errno = 0; +#endif + 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); + // string was not empty to start with and no under/overflow occurred + return !*end && (end != start) +#ifndef __WXWINCE__ + && (errno != ERANGE) +#endif + ; } // --------------------------------------------------------------------------- @@ -1770,9 +1842,11 @@ int wxString::PrintfV(const wxChar* pszFormat, va_list argptr) // current size of the buffer size *= 2; } - else if ( len > size ) + else if ( len >= size ) { - size = len; + // some vsnprintf() implementations NUL-terminate the buffer and + // some don't in len == size case, to be safe always add 1 + size = len + 1; } else // ok, there was enough space {