X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/fbc535ff084f61ec376f339c515d96d74065c18b..518f33a4e50585cab19757375a2c348e61d2594f:/src/common/string.cpp diff --git a/src/common/string.cpp b/src/common/string.cpp index 3cb10f3186..77026933c0 100644 --- a/src/common/string.cpp +++ b/src/common/string.cpp @@ -41,6 +41,12 @@ #include #include +// This probably isn't right, what should it be Vadim? +// Otherwise we end up with no wxVsprintf defined. +#ifdef __WXMOTIF__ +#define HAVE_VPRINTF +#endif + #ifdef wxUSE_WCSRTOMBS #include // for wcsrtombs(), see comments where it's used #endif // GNU @@ -78,6 +84,31 @@ static const struct // empty C style string: points to 'string data' byte of g_strEmpty extern const char *g_szNul = &g_strEmpty.dummy; +// ---------------------------------------------------------------------------- +// conditional compilation +// ---------------------------------------------------------------------------- + +// we want to find out if the current platform supports vsnprintf()-like +// function: for Unix this is done with configure, for Windows we test the +// compiler explicitly. +#ifdef __WXMSW__ + #ifdef _MSC_VER + #define wxVsprintf _vsnprintf + #endif +#else // !Windows + #ifdef HAVE_VSNPRINTF + #define wxVsprintf vsnprintf + #endif +#endif // Windows/!Windows + +#ifndef wxVsprintf + // in this case we'll use vsprintf() (which is ANSI and thus should be + // always available), but it's unsafe because it doesn't check for buffer + // size - so give a warning + #define wxVsprintf(buffer,len,format,argptr) vsprintf(buffer,format, argptr) + #pragma message("Using sprintf() because no snprintf()-like function defined") +#endif + // ---------------------------------------------------------------------------- // global functions // ---------------------------------------------------------------------------- @@ -88,14 +119,6 @@ extern const char *g_szNul = &g_strEmpty.dummy; // iostream ones. // // ATTN: you can _not_ use both of these in the same program! -#if 0 // def _MSC_VER - #include - #define NAMESPACE std:: -#else - #include - #define NAMESPACE -#endif //Visual C++ - #if wxUSE_IOSTREAMH #include #define NAMESPACE @@ -104,9 +127,26 @@ extern const char *g_szNul = &g_strEmpty.dummy; # ifdef _MSC_VER using namespace std; # endif +// for msvc (bcc50+ also) you don't need these NAMESPACE defines, +// using namespace std; takes care of that. #define NAMESPACE std:: #endif +#ifdef __WXMSW__ + #ifdef _MSC_VER + #define wxVsprintf _vsnprintf + #endif +#else + #if defined ( HAVE_VSNPRINTF ) + #define wxVsprintf vsnprintf + #endif +#endif + +#ifndef wxVsprintf + // vsprintf() is ANSI so we can always use it, but it's unsafe! + #define wxVsprintf(buffer,len,format,argptr) vsprintf(buffer,format, argptr) + #pragma message("Using sprintf() because no snprintf()-like function defined") +#endif NAMESPACE istream& operator>>(NAMESPACE istream& is, wxString& WXUNUSED(str)) { @@ -859,8 +899,13 @@ wxString& wxString::Pad(size_t nCount, char chPad, bool bFromRight) // truncate the string wxString& wxString::Truncate(size_t uiLen) { - *(m_pchData + uiLen) = '\0'; - GetStringData()->nDataLength = uiLen; + if ( uiLen < Len() ) { + CopyBeforeWrite(); + + *(m_pchData + uiLen) = '\0'; + GetStringData()->nDataLength = uiLen; + } + //else: nothing to do, string is already short enough return *this; } @@ -885,6 +930,33 @@ int wxString::Find(const char *pszSub) const return (psz == NULL) ? NOT_FOUND : psz - m_pchData; } +// --------------------------------------------------------------------------- +// stream-like operators +// --------------------------------------------------------------------------- +wxString& wxString::operator<<(int i) +{ + wxString res; + res.Printf("%d", i); + + return (*this) << res; +} + +wxString& wxString::operator<<(float f) +{ + wxString res; + res.Printf("%f", f); + + return (*this) << res; +} + +wxString& wxString::operator<<(double d) +{ + wxString res; + res.Printf("%g", d); + + return (*this) << res; +} + // --------------------------------------------------------------------------- // formatted output // --------------------------------------------------------------------------- @@ -902,11 +974,41 @@ int wxString::Printf(const char *pszFormat, ...) int wxString::PrintfV(const char* pszFormat, va_list argptr) { + // static buffer to avoid dynamic memory allocation each time static char s_szScratch[1024]; - int iLen = vsprintf(s_szScratch, pszFormat, argptr); + // NB: wxVsprintf() may return either less than the buffer size or -1 if there + // is not enough place depending on implementation + int iLen = wxVsprintf(s_szScratch, WXSIZEOF(s_szScratch), pszFormat, argptr); + char *buffer; + if ( iLen < (int)WXSIZEOF(s_szScratch) ) { + buffer = s_szScratch; + } + else { + int size = WXSIZEOF(s_szScratch) * 2; + buffer = (char *)malloc(size); + while ( buffer != NULL ) { + iLen = wxVsprintf(buffer, WXSIZEOF(s_szScratch), pszFormat, argptr); + if ( iLen < size ) { + // ok, there was enough space + break; + } + + // still not enough, double it again + buffer = (char *)realloc(buffer, size *= 2); + } + + if ( !buffer ) { + // out of memory + return -1; + } + } + AllocBeforeWrite(iLen); - strcpy(m_pchData, s_szScratch); + strcpy(m_pchData, buffer); + + if ( buffer != s_szScratch ) + free(buffer); return iLen; }