1

When using standard char* strings, the snprintf and vsnprintf functions will return the length of the output string, even if that string was truncated due to overflow.* It seems like the ISO C committee didn't like this functionality when they added swprintf and vswprintf, which return -1 on overflow.

Does anyone know of a function that will provide this length? I don't know the size of the potential strings. I might be asking too much, but.. I'd rather not:

  • allocate a huge static temp buffer
  • iteratively allocate and free memory until i've found a size that fits
  • add an additional library dependency
  • write my own format string parser

*I realize MSVC doesn't do this, and instead provides the scprintf and vscprintf functions, but I'm looking for other compilers, mainly GCC.

justinian
  • 300
  • 2
  • 8

2 Answers2

2

My best suggestion to you would be not to use wchar_t strings at all, especially if you're not writing Windows-oriented code. In case that's not an option, here are some other ideas:

  1. If your format string does not contain non-ASCII characters itself, what about first calling vsnprintf with the same set of arguments to get the length in bytes, then use that as a safe upper bound for the length in wchar_t characters (if there are few or non-ASCII characters, the bound will be tight).

  2. If you're okay with introducing a dependency on a POSIX function (which is likely to be added to C1x), use open_wmemstream and fwprintf.

  3. Just iterate allocating larger buffers, but do it smart: increase the size geometrically at each step, e.g. 127, 255, 511, 1023, 2047, ... I like this pattern better than whole powers of 2 because it's easy to avoid dangerous case where allocation might succeed for SIZE_MAX/2+1 but then wrap to 0 at the next iteration.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • Sadly, I'm not writing from scratch - I'm fixing/extending an existing codebase. I didn't know about open_wmemstream.. that could be a good way to go. – justinian May 25 '11 at 23:33
  • Well note that, unless the distribution of string sizes you're dealing with is very spread out, you'll likely get the best performance with approach 3 and choosing an initial size that's at least as long as "most" strings you deal with. I would guess 127 would suffice for that. – R.. GitHub STOP HELPING ICE May 25 '11 at 23:36
0

This returns the buffer size for wide character strings:

vswprintf(nullptr, -1, aFormat, argPtr);
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Sam
  • 616
  • 7
  • 19
  • 1
    First, in C there isn't a predefined `nullptr`; that is a property of C++11. Secondly, the standard requires a non-null pointer for `vswprintf()` to work correctly. Thirdly, the `-1` argument is going to be interpreted as `size_t`, and is therefore enormous. While this means that you won't run out of space (so you won't get a negative response from `vswprintf()`), you still have problems with writing through a null pointer. – Jonathan Leffler Jul 23 '13 at 03:09