fmt(): use dynamically allocated buffer

Avoid big stack allocation and remove the 2KiB limit for formatted
strings!
This should allow logging large response headers (>2KiB).
There should be no performance impact when the first guess works.
Otherwise, a single buffer resize is necessary.
pull/1581/head
Ali MJ Al-Nasrawy 2020-03-09 19:54:17 +03:00
parent 9d0a48ac81
commit 25abe60164
1 changed files with 23 additions and 15 deletions

View File

@ -37,29 +37,37 @@
#include <cstring> #include <cstring>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <vector>
namespace aria2 { namespace aria2 {
std::string fmt(const char* fmtTemplate, ...) std::string fmt(const char* fmtTemplate, ...)
{ {
// guess initial buffer size!
std::vector<char> buf(strlen(fmtTemplate) * 4);
va_list ap; va_list ap;
va_start(ap, fmtTemplate);
char buf[2048]; while (1) {
int rv; va_start(ap, fmtTemplate);
rv = vsnprintf(buf, sizeof(buf), fmtTemplate, ap); int rv = vsnprintf(buf.data(), buf.size(), fmtTemplate, ap);
va_end(ap);
if (rv >= buf.size()) { // truncated
buf.resize(rv + 1);
}
else if (rv >= 0) { // success
return buf.data();
}
#ifdef __MINGW32__ #ifdef __MINGW32__
// MINGW32 vsnprintf returns -1 if output is truncated. else if (rv == -1 && buf.size() < 4096) { // truncated?
if (rv < 0 && rv != -1) { buf.resize(buf.size() * 4);
// Reachable? }
buf[0] = '\0'; #endif // __MINGW32__
else { // error
buf[0] = '\0';
return buf.data();
}
} }
#else // !__MINGW32__
if (rv < 0) {
buf[0] = '\0';
}
#endif // !__MINGW32__
va_end(ap);
return buf;
} }
} // namespace aria2 } // namespace aria2