Merge branch 'nd/sparse' (early part)
[git/dscho.git] / compat / snprintf.c
blob4d07087abd4f956b4dbe209236e6abafd459b1e4
1 #include "../git-compat-util.h"
3 /*
4 * The size parameter specifies the available space, i.e. includes
5 * the trailing NUL byte; but Windows's vsnprintf expects the
6 * number of characters to write, and does not necessarily write the
7 * trailing NUL.
8 */
9 #ifndef SNPRINTF_SIZE_CORR
10 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ < 4
11 #define SNPRINTF_SIZE_CORR 1
12 #else
13 #define SNPRINTF_SIZE_CORR 0
14 #endif
15 #endif
17 #undef vsnprintf
18 int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)
20 char *s;
21 int ret = -1;
23 if (maxsize > 0) {
24 ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
25 if (ret == maxsize-1)
26 ret = -1;
27 /* Windows does not NUL-terminate if result fills buffer */
28 str[maxsize-1] = 0;
30 if (ret != -1)
31 return ret;
33 s = NULL;
34 if (maxsize < 128)
35 maxsize = 128;
37 while (ret == -1) {
38 maxsize *= 4;
39 str = realloc(s, maxsize);
40 if (! str)
41 break;
42 s = str;
43 ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
44 if (ret == maxsize-1)
45 ret = -1;
47 free(s);
48 return ret;
51 int git_snprintf(char *str, size_t maxsize, const char *format, ...)
53 va_list ap;
54 int ret;
56 va_start(ap, format);
57 ret = git_vsnprintf(str, maxsize, format, ap);
58 va_end(ap);
60 return ret;