How to determine buffer size for vswprintf under Linux gcc
I need to allocate a sufficient buffer for format function vswprintf(). When doing the same thing with ANSI string, I'm using:
vsnprintf( NULL, NULL, pszFormat, args );
which returns me required size of a buffer. But it seems that unicode version of this function doesn't have this functionality. When I execute:
vswprintf( NULL, NULL, pszFormat, args );
result value is always -1.
Only solution which I found is using a large static buffer for calculation required size. But I don't like this solution:
static const int nBuffSize = 1024;
static XCHAR evalBuff[nBuffSize];
int nSize = vswprintf( evalBuff, nBuffSize, pszFormat, args );
if ( nSize != -1 )
{
return nSize;
}
else
开发者_运维知识库{
throw XXX;
}
Is there any way how to measure required buffer size for unicode strings?
Regards Ludek
Opening a dummy file to /dev/null (or NUL under windows) and printing to that file to retrieve the size works very well (it is faster than printing to a string):
#if !defined(_MSC_VER)
printf_dummy_file = fopen("/dev/null", "wb");
#else
printf_dummy_file = fopen("NUL", "wb");
#endif
...
n = vfprintf(printf_dummy_file, format, args);
The "fopen" part should be done once (you can use a static variable, or the constructor of a global variable if you are using C++).
A bit heavyweight, but if nobody comes up with anything better you could exponentially grow a buffer until it's big enough:
std::vector<wchar_t> vec(512);
int nSize;
do {
vec.resize(vec.size()*2);
va_list args2;
va_copy args2, args;
nSize = vswprintf(&vec[0], vec.size(), format, args2);
va_end args2
} while(nSize < 0);
// now I have the length, and the formatted string to copy if required.
Since you're on POSIX, you'd think that an errno would be defined for insufficient buffer space, and that this errno should be checked in the while
condition, so that other errors don't cause a resource-hungry loop. But there's no such errno defined at http://opengroup.org/onlinepubs/007908775/xsh/fwprintf.html, so I guess you'll have to test what errno you actually get on your implementation (if any).
Another option is to get rid of the format strings, and instead write to a wostringstream
. But that's not much use if your format string needs to be configured after compile-time.
I have found a C++ only solution:
libfmt has its own sprintf implementation, applicable to both std::string
and std::wstring
.
Ex :
#include <fmt/core.h>
#include <fmt/printf.h>
std::wstring ws = fmt::sprintf(L"The answer is %d.", 42);
This will get the buffer size:
vswprintf(nullptr, -1, pszFormat, args);
精彩评论