Merge branch 'jc/maint-1.6.0-read-tree-overlay' into maint
[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 #define SNPRINTF_SIZE_CORR 0
10 #endif
11
12 #undef vsnprintf
13 int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)
14 {
15         char *s;
16         int ret = -1;
17
18         if (maxsize > 0) {
19                 ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
20                 if (ret == maxsize-1)
21                         ret = -1;
22                 /* Windows does not NUL-terminate if result fills buffer */
23                 str[maxsize-1] = 0;
24         }
25         if (ret != -1)
26                 return ret;
27
28         s = NULL;
29         if (maxsize < 128)
30                 maxsize = 128;
31
32         while (ret == -1) {
33                 maxsize *= 4;
34                 str = realloc(s, maxsize);
35                 if (! str)
36                         break;
37                 s = str;
38                 ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
39                 if (ret == maxsize-1)
40                         ret = -1;
41         }
42         free(s);
43         return ret;
44 }
45
46 int git_snprintf(char *str, size_t maxsize, const char *format, ...)
47 {
48         va_list ap;
49         int ret;
50
51         va_start(ap, format);
52         ret = git_vsnprintf(str, maxsize, format, ap);
53         va_end(ap);
54
55         return ret;
56 }
57