2

What is the direct alternative for the vsnwprintf function on linux machines and what headers should be included to use it?

Thanks for any advice

Ulterior
  • 2,786
  • 3
  • 30
  • 58

7 Answers7

3

Linux variant of this function is snprintf and vsnprintf which are kindly provided by stdio.h:

int snprintf(char *str, size_t size, const char *format, ...);
int vsnprintf(char *str, size_t size, const char *format, va_list args);

and Unicode versions provided by wchar.h:

int swprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, ...);
int vswprintf(wchar_t *wcs, size_t maxlen, const wchar_t *format, va_list args);

http://linux.die.net/man/3/snprintf
http://linux.die.net/man/3/swprintf

Andrejs Cainikovs
  • 27,428
  • 2
  • 75
  • 95
3

It depends on what vsnwprintf() (sic) does and what is its parameter list.

The C99 Standard describes vswprintf() (in section 7.24.2.7). To use it you need to #include <stdarg.h> and <wchar.h>. The implementation should be in the Standard library.

pmg
  • 106,608
  • 13
  • 126
  • 198
  • It appears this function is the correct alternative, even without `n` in its name, thanks! – Ulterior May 04 '12 at 10:25
  • One of the parameters to `vswprintf()` is the (maximum) size of the output array. It's *only* the return value that is different than the return value of, for example, `snprintf()`. – pmg May 04 '12 at 10:25
  • Downvoting for the 'sic'. printf -> wprintf, vprintf -> vwprintf, sprintf -> swprintf, vsprintf -> vswprintf.. But vsnwprintf elicits sarcasm from you? It's pretty obvious what it is: v = vararg, s = string-dest, n = numeric limit, w = widestring. – kfsone Dec 28 '13 at 20:16
1

There’s no alternative for that.

vswprintf suggested in other answers doesn’t tell required buffer length. When you’ll pass nullptr and 0 to the first two arguments, it will returns -1, not the required buffer length. This is both how it's documented, and how it works in practice in clang 4.

There’s a workaround in that answer https://stackoverflow.com/a/16352146/126995 Scroll to the end of that for vscwprintf source code. The workaround works for small strings, but relatively slow for larger strings, and can even exhaust stack space for a very large string.

Soonts
  • 20,079
  • 9
  • 57
  • 130
0

Seems that u_vsnprintf() or u_vsnprintf_u() from libicu is what you need

0

The truncating version of vswprintf() is unsafe. You really want the C11 vswprintf_s(), which ensures a null delimited wide string, and errors when the destination buffer is too small.

As you know, the wide variants have no API to calculate the size with a NULL buffer. You need to extend the buffer on errors, if the buffer is too small.

Anyway, safeclib-3.0 will provide all of them. safe and unsafe with --enable-unsafe, wide or non-wide, truncating ('n') or not-truncating. https://github.com/rurban/safeclib/blob/wchar/src/wchar/vsnwprintf_s.c

vsnwprintf is in C99, MSVC, and a few others. Not in musl. -stc=c99 should be enough for glibc.

rurban
  • 4,025
  • 24
  • 27
0

Here an example of workaround:

  int vsnwprintf(wchar_t* buffer, size_t size, const wchar_t* format, va_list& params)
  {
    if(buffer || size)
      return vswprintf(buffer, size, format, params);

    int result = -1;
    for(size = 100; result < 0; size += 100)
    {
      unique_ptr<wchar_t[]> guard(buffer = new wchar_t[size]);
      va_list copy;
      va_copy(copy, params);
      result = vswprintf(buffer, size, format, copy);
      va_end(copy);
    }
  
    return result;
  };

Probably, it's needed to limit a number of iterations in some way.

Serge Roussak
  • 1,731
  • 1
  • 14
  • 28
0

For C++, you can use fmt::sprintf of libfmt from <fmt/printf.h>

Kiruahxh
  • 1,276
  • 13
  • 30