X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/378b05f7f86eda83452d67f182afc62a0f9b982f..4f6aed9c6a21d4bc732579aa564adf4cdb2c9aab:/src/common/string.cpp diff --git a/src/common/string.cpp b/src/common/string.cpp index 60fcb535a7..29dc8d60da 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -107,7 +107,7 @@ extern const wxChar WXDLLEXPORT *wxEmptyString = &g_strEmpty.dummy; // function wxVsnprintfA (A for ANSI), should also find one for Unicode // strings in Unicode build #ifdef __WXMSW__ - #ifdef __VISUALC__ + #if (defined(__VISUALC__) || defined(wxUSE_NORLANDER_HEADERS)) && !defined(__MINGW32__) #define wxVsnprintfA _vsnprintf #endif #else // !Windows @@ -200,7 +200,15 @@ extern int WXDLLEXPORT wxVsnprintf(wxChar *buf, size_t len, return iLen; #else // ANSI - return wxVsnprintfA(buf, len, format, argptr); + // vsnprintf() will not terminate the string with '\0' if there is not + // enough place, but we want the string to always be NUL terminated + int rc = wxVsnprintfA(buf, len - 1, format, argptr); + if ( rc == -1 ) + { + buf[len] = 0; + } + + return rc; #endif // Unicode/ANSI } @@ -352,8 +360,13 @@ wxString::wxString(const wchar_t *pwz) // allocates memory needed to store a C string of length nLen void wxString::AllocBuffer(size_t nLen) { - wxASSERT( nLen > 0 ); // - wxASSERT( nLen <= INT_MAX-1 ); // max size (enough room for 1 extra) + // allocating 0 sized buffer doesn't make sense, all empty strings should + // reuse g_strEmpty + wxASSERT( nLen > 0 ); + + // make sure that we don't overflow + wxASSERT( nLen < (INT_MAX / sizeof(wxChar)) - + (sizeof(wxStringData) + EXTRA_ALLOC + 1) ); STATISTICS_ADD(Length, nLen); @@ -391,13 +404,35 @@ void wxString::AllocBeforeWrite(size_t nLen) // must not share string and must have enough space wxStringData* pData = GetStringData(); - if ( pData->IsShared() || (nLen > pData->nAllocLength) ) { + if ( pData->IsShared() || pData->IsEmpty() ) { // can't work with old buffer, get new one pData->Unlock(); AllocBuffer(nLen); } else { - // update the string length + if ( nLen > pData->nAllocLength ) { + // realloc the buffer instead of calling malloc() again, this is more + // efficient + STATISTICS_ADD(Length, nLen); + + nLen += EXTRA_ALLOC; + + wxStringData *pDataOld = pData; + pData = (wxStringData*) + realloc(pData, sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar)); + if ( !pData ) { + // out of memory + free(pDataOld); + + // FIXME we're going to crash... + return; + } + + pData->nAllocLength = nLen; + m_pchData = pData->data(); + } + + // now we have enough space, just update the string length pData->nDataLength = nLen; } @@ -429,11 +464,15 @@ void wxString::Alloc(size_t nLen) else { nLen += EXTRA_ALLOC; + wxStringData *pDataOld = pData; wxStringData *p = (wxStringData *) realloc(pData, sizeof(wxStringData) + (nLen + 1)*sizeof(wxChar)); if ( p == NULL ) { - // @@@ what to do on memory error? + // don't leak memory + free(pDataOld); + + // FIXME what to do on memory error? return; } @@ -451,13 +490,16 @@ void wxString::Shrink() { wxStringData *pData = GetStringData(); - // this variable is unused in release build, so avoid the compiler warning by - // just not declaring it + // this variable is unused in release build, so avoid the compiler warning + // by just not declaring it #ifdef __WXDEBUG__ void *p = #endif realloc(pData, sizeof(wxStringData) + (pData->nDataLength + 1)*sizeof(wxChar)); + // we rely on a reasonable realloc() implementation here - so far I haven't + // seen any which wouldn't behave like this + wxASSERT( p != NULL ); // can't free memory? wxASSERT( p == pData ); // we're decrementing the size - block shouldn't move! } @@ -991,6 +1033,49 @@ int wxString::Find(const wxChar *pszSub) const return (psz == NULL) ? wxNOT_FOUND : psz - (const wxChar*) m_pchData; } +// ---------------------------------------------------------------------------- +// conversion to numbers +// ---------------------------------------------------------------------------- + +bool wxString::ToLong(long *val) const +{ + wxCHECK_MSG( val, FALSE, _T("NULL pointer in wxString::ToLong") ); + + const wxChar *start = c_str(); + wxChar *end; + *val = wxStrtol(start, &end, 10); + + // 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::ToULong(unsigned long *val) const +{ + wxCHECK_MSG( val, FALSE, _T("NULL pointer in wxString::ToULong") ); + + const wxChar *start = c_str(); + wxChar *end; + *val = wxStrtoul(start, &end, 10); + + // 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::ToDouble(double *val) const +{ + wxCHECK_MSG( val, FALSE, _T("NULL pointer in wxString::ToDouble") ); + + 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); +} + // --------------------------------------------------------------------------- // stream-like operators // --------------------------------------------------------------------------- @@ -1022,6 +1107,28 @@ wxString& wxString::operator<<(double d) // formatted output // --------------------------------------------------------------------------- +/* static */ +wxString wxString::Format(const wxChar *pszFormat, ...) +{ + va_list argptr; + va_start(argptr, pszFormat); + + wxString s; + s.PrintfV(pszFormat, argptr); + + va_end(argptr); + + return s; +} + +/* static */ +wxString wxString::FormatV(const wxChar *pszFormat, va_list argptr) +{ + wxString s; + s.Printf(pszFormat, argptr); + return s; +} + int wxString::Printf(const wxChar *pszFormat, ...) { va_list argptr; @@ -1606,17 +1713,6 @@ size_t wxString::find_last_not_of(wxChar ch, size_t nStart) const return npos; } -wxString wxString::substr(size_t nStart, size_t nLen) const -{ - // npos means 'take all' - if ( nLen == npos ) - nLen = 0; - - wxASSERT( nStart + nLen <= Len() ); - - return wxString(c_str() + nStart, nLen == npos ? 0 : nLen); -} - wxString& wxString::erase(size_t nStart, size_t nLen) { wxString strTmp(c_str(), nStart); @@ -1711,20 +1807,8 @@ 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 because strings are ref counted -#if 0 - if ( m_nCount != 0 ) - memcpy(m_pItems, src.m_pItems, m_nCount*sizeof(wxChar *)); -#endif // 0 - 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