X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/67612ff18e560669b337fa2c43f363f8be71b6d2..0bbe61b8c18a1795189f0cf73cc61c14a0fb846d:/src/common/string.cpp?ds=sidebyside diff --git a/src/common/string.cpp b/src/common/string.cpp index 84f285410c..6b65824622 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -35,10 +35,6 @@ #include #include -#ifdef __SALFORDC__ - #include -#endif - #include "wx/hashmap.h" // string handling functions used by wxString: @@ -1347,9 +1343,9 @@ wxString& wxString::MakeLower() // --------------------------------------------------------------------------- // some compilers (VC++ 6.0 not to name them) return true for a call to -// isspace('ê') in the C locale which seems to be broken to me, but we have to -// live with this by checking that the character is a 7 bit one - even if this -// may fail to detect some spaces (I don't know if Unicode doesn't have +// isspace('\xEA') in the C locale which seems to be broken to me, but we have +// to live with this by checking that the character is a 7 bit one - even if +// this may fail to detect some spaces (I don't know if Unicode doesn't have // space-like symbols somewhere except in the first 128 chars), it is arguably // still better than trimming away accented letters inline int wxSafeIsspace(wxChar ch) { return (ch < 127) && wxIsspace(ch); } @@ -1444,61 +1440,62 @@ int wxString::Find(wxUniChar ch, bool bFromEnd) const #define DO_IF_NOT_WINCE(x) #endif -#define WX_STRING_TO_INT_TYPE(val, base, func) \ - wxCHECK_MSG( val, false, _T("NULL output pointer") ); \ +#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") ); \ \ DO_IF_NOT_WINCE( errno = 0; ) \ \ const wxStringCharType *start = wx_str(); \ wxStringCharType *end; \ - *val = func(start, &end, base); \ + T 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 and no under/overflow */ \ /* occurred: */ \ - return !*end && (end != start) \ - DO_IF_NOT_WINCE( && (errno != ERANGE) ) + if ( *end || end == start DO_IF_NOT_WINCE(|| errno == ERANGE) ) \ + return false; \ + *out = val; \ + return true -bool wxString::ToLong(long *val, int base) const +bool wxString::ToLong(long *pVal, int base) const { - WX_STRING_TO_INT_TYPE(val, base, wxStrtol); + WX_STRING_TO_INT_TYPE(pVal, base, wxStrtol, long); } -bool wxString::ToULong(unsigned long *val, int base) const +bool wxString::ToULong(unsigned long *pVal, int base) const { - WX_STRING_TO_INT_TYPE(val, base, wxStrtoul); + WX_STRING_TO_INT_TYPE(pVal, base, wxStrtoul, unsigned long); } -bool wxString::ToLongLong(wxLongLong_t *val, int base) const +bool wxString::ToLongLong(wxLongLong_t *pVal, int base) const { - WX_STRING_TO_INT_TYPE(val, base, wxStrtoll); + WX_STRING_TO_INT_TYPE(pVal, base, wxStrtoll, wxLongLong_t); } -bool wxString::ToULongLong(wxULongLong_t *val, int base) const +bool wxString::ToULongLong(wxULongLong_t *pVal, int base) const { - WX_STRING_TO_INT_TYPE(val, base, wxStrtoull); + WX_STRING_TO_INT_TYPE(pVal, base, wxStrtoull, wxULongLong_t); } -bool wxString::ToDouble(double *val) const +bool wxString::ToDouble(double *pVal) const { - wxCHECK_MSG( val, false, _T("NULL pointer in wxString::ToDouble") ); + wxCHECK_MSG( pVal, false, _T("NULL output pointer") ); -#ifndef __WXWINCE__ - errno = 0; -#endif + DO_IF_NOT_WINCE( errno = 0; ) const wxChar *start = c_str(); wxChar *end; - *val = wxStrtod(start, &end); + double 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 and no under/overflow occurred - return !*end && (end != start) -#ifndef __WXWINCE__ - && (errno != ERANGE) -#endif - ; + if ( *end || end == start DO_IF_NOT_WINCE(|| errno == ERANGE) ) + return false; + + *pVal = val; + + return true; } // --------------------------------------------------------------------------- @@ -1603,11 +1600,23 @@ int wxString::DoPrintfUtf8(const char *format, ...) and set errno. What vswprintf sets errno to is undefined but Darwin seems to set it to - EOVERFLOW. The only expected errno that are defined anywhere are by an - addendum indicating that EILSEQ should be set for bad input characters and - EINVALID for bad arguments such as a NULL buffer pointer. It would appear - that setting EOVERFLOW is not documented anywhere and has only been at - this time observed on Darwin. + EOVERFLOW. The only expected errno are EILSEQ and EINVAL. Both of + those are defined in the standard and backed up by several conformance + statements. Note that ENOMEM mentioned in the manual page does not + apply to swprintf, only wprintf and fwprintf. + + Official manual page: + http://www.opengroup.org/onlinepubs/009695399/functions/swprintf.html + + Some conformance statements (AIX, Solaris): + http://www.opengroup.org/csq/view.mhtml?RID=ibm%2FSD1%2F3 + http://www.theopengroup.org/csq/view.mhtml?norationale=1&noreferences=1&RID=Fujitsu%2FSE2%2F10 + + Since EILSEQ and EINVAL are rather common but EOVERFLOW is not and since + EILSEQ and EINVAL are specifically defined to mean the error is other than + an undersized buffer and no other errno are defined we treat those two + as meaning hard errors and everything else gets the old behavior which + is to keep looping and increasing buffer size until the function succeeds. In practice it's impossible to determine before compilation which behavior may be used. The vswprintf function may have vsnprintf-like behavior or @@ -1704,22 +1713,21 @@ static int DoStringPrintfV(wxString& str, // as we don't know how much we need, double the current size of // the buffer #ifndef __WXWINCE__ - if( (errno == 0) || (errno == EOVERFLOW) ) + if( (errno == EILSEQ) || (errno == EINVAL) ) + // If errno was set to one of the two well-known hard errors + // then fail immediately to avoid an infinite loop. + return -1; + else +#endif // __WXWINCE__ // still not enough, as we don't know how much we need, double the // current size of the buffer size *= 2; - else - // If errno was set to something else, assume hard failure. - return -1; -#else - size *= 2; -#endif // __WXWINCE__ #endif // wxUSE_WXVSNPRINTF/!wxUSE_WXVSNPRINTF } else if ( len >= size ) { #if wxUSE_WXVSNPRINTF - // we know that our own implementation of wxVsnprintf() returns + // we know that our own implementation of wxVsnprintf() returns // size+1 when there's not enough space but that's not the size // of the required buffer! size *= 2; // so we just double the current size of the buffer