common: drop useless printf function + reimplement vssappend with C++11

Performance is not important here. I'm not sure Windows could handle VLA
* new/delete can still be used otherwise.
* Put an assert(0) because debugger surely don't use string bigger than
  128 bytes.

code is much more compact 20 lines vs 700 lines ...
This commit is contained in:
Gregory Hainaut 2015-03-23 23:11:17 +01:00
parent b2efa85a3f
commit fd71fc4fc9
2 changed files with 48 additions and 71 deletions

View File

@ -246,10 +246,4 @@ extern wxString operator+(const FastFormatUnicode& str1, const wxChar* str2);
// These functions are useful since they are ASCII always, even under Unicode. Typically // These functions are useful since they are ASCII always, even under Unicode. Typically
// even in a unicode app. // even in a unicode app.
extern void ssprintf(std::string& dest, const char* fmt, ...);
extern void ssappendf(std::string& dest, const char* format, ...); extern void ssappendf(std::string& dest, const char* format, ...);
extern void vssprintf(std::string& dest, const char* format, va_list args);
extern void vssappendf(std::string& dest, const char* format, va_list args);
extern std::string fmt_string( const char* fmt, ... );
extern std::string vfmt_string( const char* fmt, va_list args );

View File

@ -35,6 +35,8 @@
#include "PrecompiledHeader.h" #include "PrecompiledHeader.h"
#ifdef WIN32
#include <math.h> #include <math.h>
#ifdef KERNEL #ifdef KERNEL
@ -528,7 +530,7 @@ static void flt( std::string& dest, double num, int size, int precision, char fm
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// This is a "mostly" direct replacement for vsprintf, that is more secure and easier // This is a "mostly" direct replacement for vsprintf, that is more secure and easier
// to use than vsnprintf or vsprintf_s. See the docs for ssprintf for usage notes. // to use than vsnprintf or vsprintf_s. See the docs for ssprintf for usage notes.
void vssappendf(std::string& dest, const char* format, va_list args) static void vssappendf(std::string& dest, const char* format, va_list args)
{ {
int base; int base;
@ -760,17 +762,54 @@ repeat:
} }
} }
void vssprintf( std::string& dest, const char* format, va_list args ) #else
{ // To keep trace of license :)
// Optimization: Memory is cheap. Allocating it on the fly is not. Allocate more room
// than we'll likely need right upfront! Also, strlen is slow, so better to just pick an
// arbitrarily generous value to reserve instead of basing it on string length.
dest.clear(); /* PCSX2 - PS2 Emulator for PCs
dest.reserve( 96 ); * Copyright (C) 2002-2015 PCSX2 Dev Team
vssappendf( dest, format, args ); *
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
// Note: std::vsnprintf requires C++11 (and the function must return the total
// number of characters which would have been written even if a truncation occured)
// Note2: Code is only used in debugger (perf is not important)
static void vssappendf(std::string& dest, const char* format, va_list args)
{
char first_try[128]; // this function is called 99% (100%?) of the times for small string
va_list args_copy;
va_copy(args_copy, args);
s32 size = std::vsnprintf(first_try, 128, format, args_copy) + 1;
va_end(args_copy);
if (size < 0)
return;
if (size < 128) {
dest += first_try;
return;
}
// VLA extension. Not sure it is supported on windows. Maybe one days in C++ standard
// Performance is not important here
char output[size];
std::vsnprintf(output, size, format, args);
dest += output;
} }
#endif
void ssappendf( std::string& dest, const char* format, ...) void ssappendf( std::string& dest, const char* format, ...)
{ {
va_list args; va_list args;
@ -778,59 +817,3 @@ void ssappendf( std::string& dest, const char* format, ...)
vssappendf( dest, format, args ); vssappendf( dest, format, args );
va_end(args); va_end(args);
} }
// This is a "mostly" direct replacement for sprintf, based on std::string.
// The most notable difference in use is the requirement of a "params" keyword delimiting
// the format string from the parameters used to fill the string's tokens. It looks
// like this in practice:
//
// ssprintf( dest, "Yo Joe, %d. In the Hizzou %s.", intval, strval );
//
// In addition to all standard printf formatting tokens, ssprintf also supports a new token
// for std::string parameters as %hs (passed by reference/pointer). I opted for %hs (using 'h'
// as a qualifier) over %S because under MSVC %S acts as a char/widechar conversion. Note
// that these are passed by pointer so you *must* use the & operator most of the time.
// Example:
//
// ssprintf( dest, "Yo Joe, %hs.", &strval );
//
// This can be a cavet of sorts since forgetting to use the & will always compile but
// will cause undefined behavior and odd crashes (much like how the same thing happens
// when exchanging an intvalu for a c-string normally -- it's just more tricky with
// strings since we're not used to prefixing sprintf parameters with &s).
//
// === 64-bit -- s64 / u64 -- Support ===
//
// ssprintf supports u64/s64 via the L qualifier, which can be prefixed to any one of the
// integer tokens (d, i, x). This isn't standard, but it's easy and doesn't conflict with
// anything, and none of the other 64-bit qualifiers aren't really standard anyway.
// Example:
//
// ssprintf( dest, "Yo Joe, %Ld, %Lx.", int64, hex64 );
//
void ssprintf(std::string& str, const char* fmt, ...)
{
va_list args;
va_start(args, fmt);
vssprintf(str, fmt, args);
va_end(args);
}
// See ssprintf for usage details and differences from sprintf formatting.
std::string fmt_string( const char* fmt, ... )
{
std::string retval;
va_list args;
va_start( args, fmt );
vssprintf( retval, fmt, args );
va_end( args );
return retval;
}
std::string vfmt_string( const char* fmt, va_list args )
{
std::string retval;
vssprintf( retval, fmt, args );
return retval;
}