1
0
Fork 0

Another VarArgs fix.

This time using va_copy() on platforms that have it and simple assignment on platforms that don't.
This commit is contained in:
madmaxoft 2014-01-16 08:34:10 +01:00
parent 4974bf2832
commit ba49a32c3a
7 changed files with 39 additions and 43 deletions

View File

@ -446,12 +446,10 @@ bool cIniFile::SetValueF(const AString & a_KeyName, const AString & a_ValueName,
bool cIniFile::SetValueV(const AString & a_KeyName, const AString & a_ValueName, const char * a_Format, ...) bool cIniFile::SetValueV(const AString & a_KeyName, const AString & a_ValueName, const char * a_Format, ...)
{ {
va_list args, argsCopy; va_list args;
va_start(args, a_Format); va_start(args, a_Format);
va_start(argsCopy, a_Format);
AString Data; AString Data;
AppendVPrintf(Data, a_Format, args, argsCopy); AppendVPrintf(Data, a_Format, args);
va_end(argsCopy);
va_end(args); va_end(args);
return SetValue(a_KeyName, a_ValueName, Data); return SetValue(a_KeyName, a_ValueName, Data);
} }

View File

@ -16,11 +16,9 @@
void cCommandOutputCallback::Out(const char * a_Fmt, ...) void cCommandOutputCallback::Out(const char * a_Fmt, ...)
{ {
AString Output; AString Output;
va_list args, argsCopy; va_list args;
va_start(args, a_Fmt); va_start(args, a_Fmt);
va_start(argsCopy, a_Fmt); AppendVPrintf(Output, a_Fmt, args);
AppendVPrintf(Output, a_Fmt, args, argsCopy);
va_end(argsCopy);
va_end(args); va_end(args);
Output.append("\n"); Output.append("\n");
Out(Output); Out(Output);

View File

@ -99,10 +99,10 @@ void cLog::ClearLog()
void cLog::Log(const char * a_Format, va_list argList, va_list argListCopy) void cLog::Log(const char * a_Format, va_list argList)
{ {
AString Message; AString Message;
AppendVPrintf(Message, a_Format, argList, argListCopy); AppendVPrintf(Message, a_Format, argList);
time_t rawtime; time_t rawtime;
time ( &rawtime ); time ( &rawtime );
@ -149,11 +149,9 @@ void cLog::Log(const char * a_Format, va_list argList, va_list argListCopy)
void cLog::Log(const char * a_Format, ...) void cLog::Log(const char * a_Format, ...)
{ {
va_list argList, argListCopy; va_list argList;
va_start(argList, a_Format); va_start(argList, a_Format);
va_start(argListCopy, a_Format); Log(a_Format, argList);
Log(a_Format, argList, argListCopy);
va_end(argListCopy);
va_end(argList); va_end(argList);
} }

View File

@ -14,7 +14,7 @@ private:
public: public:
cLog(const AString & a_FileName); cLog(const AString & a_FileName);
~cLog(); ~cLog();
void Log(const char * a_Format, va_list argList, va_list argListCopy); void Log(const char * a_Format, va_list argList);
void Log(const char * a_Format, ...); void Log(const char * a_Format, ...);
// tolua_begin // tolua_begin
void SimpleLog(const char * a_String); void SimpleLog(const char * a_String);

View File

@ -440,11 +440,9 @@ AString cFile::ReadWholeFile(const AString & a_FileName)
int cFile::Printf(const char * a_Fmt, ...) int cFile::Printf(const char * a_Fmt, ...)
{ {
AString buf; AString buf;
va_list args, argsCopy; va_list args;
va_start(args, a_Fmt); va_start(args, a_Fmt);
va_start(argsCopy, a_Fmt); AppendVPrintf(buf, a_Fmt, args);
AppendVPrintf(buf, a_Fmt, args, argsCopy);
va_end(argsCopy);
va_end(args); va_end(args);
return Write(buf.c_str(), buf.length()); return Write(buf.c_str(), buf.length());
} }

View File

@ -14,39 +14,52 @@
#pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "ws2_32.lib")
#endif #endif
// For platforms that don't have va_copy, define out own, simplistic one:
#ifndef va_copy
#define va_copy(dst, src) dst = src
#endif va_copy
AString & AppendVPrintf(AString & str, const char *format, va_list args, va_list argsCopy)
AString & AppendVPrintf(AString & str, const char *format, va_list args)
{ {
ASSERT(format != NULL); ASSERT(format != NULL);
char buffer[2048]; char buffer[2048];
size_t len; size_t len;
va_list argsCopy;
va_copy(argsCopy, args);
#ifdef _MSC_VER #ifdef _MSC_VER
// MS CRT provides secure printf that doesn't behave like in the C99 standard // MS CRT provides secure printf that doesn't behave like in the C99 standard
if ((len = _vsnprintf_s(buffer, ARRAYCOUNT(buffer), _TRUNCATE, format, args)) != -1) if ((len = _vsnprintf_s(buffer, ARRAYCOUNT(buffer), _TRUNCATE, format, argsCopy)) != -1)
#else // _MSC_VER #else // _MSC_VER
if ((len = vsnprintf(buffer, ARRAYCOUNT(buffer), format, args)) < ARRAYCOUNT(buffer)) if ((len = vsnprintf(buffer, ARRAYCOUNT(buffer), format, argsCopy)) < ARRAYCOUNT(buffer))
#endif // else _MSC_VER #endif // else _MSC_VER
{ {
// The result did fit into the static buffer // The result did fit into the static buffer
va_end(argsCopy);
str.append(buffer, len); str.append(buffer, len);
return str; return str;
} }
va_end(argsCopy);
// The result did not fit into the static buffer // The result did not fit into the static buffer, use a dynamic buffer:
#ifdef _MSC_VER #ifdef _MSC_VER
// for MS CRT, we need to calculate the result length // for MS CRT, we need to calculate the result length
len = _vscprintf(format, args); va_copy(argsCopy, args);
len = _vscprintf(format, argsCopy);
if (len == -1) if (len == -1)
{ {
va_end(argsCopy);
return str; return str;
} }
va_end(argsCopy);
#endif // _MSC_VER #endif // _MSC_VER
// Allocate a buffer and printf into it: // Allocate a buffer and printf into it:
va_copy(argsCopy, args);
std::vector<char> Buffer(len + 1); std::vector<char> Buffer(len + 1);
#ifdef _MSC_VER #ifdef _MSC_VER
vsprintf_s((char *)&(Buffer.front()), Buffer.size(), format, argsCopy); vsprintf_s((char *)&(Buffer.front()), Buffer.size(), format, argsCopy);
@ -54,6 +67,7 @@ AString & AppendVPrintf(AString & str, const char *format, va_list args, va_list
vsnprintf((char *)&(Buffer.front()), Buffer.size(), format, argsCopy); vsnprintf((char *)&(Buffer.front()), Buffer.size(), format, argsCopy);
#endif // else _MSC_VER #endif // else _MSC_VER
str.append(&(Buffer.front()), Buffer.size() - 1); str.append(&(Buffer.front()), Buffer.size() - 1);
va_end(argsCopy);
return str; return str;
} }
@ -64,11 +78,9 @@ AString & AppendVPrintf(AString & str, const char *format, va_list args, va_list
AString & Printf(AString & str, const char * format, ...) AString & Printf(AString & str, const char * format, ...)
{ {
str.clear(); str.clear();
va_list args, argsCopy; va_list args;
va_start(args, format); va_start(args, format);
va_start(argsCopy, format); std::string &retval = AppendVPrintf(str, format, args);
std::string &retval = AppendVPrintf(str, format, args, argsCopy);
va_end(argsCopy);
va_end(args); va_end(args);
return retval; return retval;
} }
@ -80,11 +92,9 @@ AString & Printf(AString & str, const char * format, ...)
AString Printf(const char * format, ...) AString Printf(const char * format, ...)
{ {
AString res; AString res;
va_list args, argsCopy; va_list args;
va_start(args, format); va_start(args, format);
va_start(argsCopy, format); AppendVPrintf(res, format, args);
AppendVPrintf(res, format, args, argsCopy);
va_end(argsCopy);
va_end(args); va_end(args);
return res; return res;
} }
@ -93,13 +103,11 @@ AString Printf(const char * format, ...)
AString & AppendPrintf(AString &str, const char *format, ...) AString & AppendPrintf(AString &str, const char * format, ...)
{ {
va_list args, argsCopy; va_list args;
va_start(args, format); va_start(args, format);
va_start(argsCopy, format); std::string &retval = AppendVPrintf(str, format, args);
std::string &retval = AppendVPrintf(str, format, args, argsCopy);
va_end(argsCopy);
va_end(args); va_end(args);
return retval; return retval;
} }

View File

@ -21,12 +21,8 @@ typedef std::list<AString> AStringList;
/** Add the formated string to the existing data in the string /** Add the formated string to the existing data in the string */
It is silly to need to specify the arguments twice, but it is required for x64 / GCC: extern AString & AppendVPrintf(AString & str, const char * format, va_list args);
Ref.: issue #541, http://www.bailopan.net/blog/?p=30
va_copy is not available until C++11, so we need to make do with passing a duplicate.
*/
extern AString & AppendVPrintf(AString & str, const char * format, va_list args, va_list argsCopy);
/// Output the formatted text into the string /// Output the formatted text into the string
extern AString & Printf (AString & str, const char * format, ...); extern AString & Printf (AString & str, const char * format, ...);