Merge branch 'av/maint-config-reader'
[git] / compat / snprintf.c
1 #include "../git-compat-util.h"
2
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 without the trailing NUL.
7  */
8 #ifndef SNPRINTF_SIZE_CORR
9 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ < 4
10 #define SNPRINTF_SIZE_CORR 1
11 #else
12 #define SNPRINTF_SIZE_CORR 0
13 #endif
14 #endif
15
16 #undef vsnprintf
17 int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)
18 {
19         char *s;
20         int ret = -1;
21
22         if (maxsize > 0) {
23                 ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
24                 if (ret == maxsize-1)
25                         ret = -1;
26                 /* Windows does not NUL-terminate if result fills buffer */
27                 str[maxsize-1] = 0;
28         }
29         if (ret != -1)
30                 return ret;
31
32         s = NULL;
33         if (maxsize < 128)
34                 maxsize = 128;
35
36         while (ret == -1) {
37                 maxsize *= 4;
38                 str = realloc(s, maxsize);
39                 if (! str)
40                         break;
41                 s = str;
42                 ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
43                 if (ret == maxsize-1)
44                         ret = -1;
45         }
46         free(s);
47         return ret;
48 }
49
50 int git_snprintf(char *str, size_t maxsize, const char *format, ...)
51 {
52         va_list ap;
53         int ret;
54
55         va_start(ap, format);
56         ret = git_vsnprintf(str, maxsize, format, ap);
57         va_end(ap);
58
59         return ret;
60 }
61