]>
Commit | Line | Data |
---|---|---|
c4582f93 MR |
1 | #include "../git-compat-util.h" |
2 | ||
f4626df5 JS |
3 | /* |
4 | * The size parameter specifies the available space, i.e. includes | |
71064e3f FL |
5 | * the trailing NUL byte; but Windows's vsnprintf uses the entire |
6 | * buffer and avoids the trailing NUL, should the buffer be exactly | |
7 | * big enough for the result. Defining SNPRINTF_SIZE_CORR to 1 will | |
8 | * therefore remove 1 byte from the reported buffer size, so we | |
9 | * always have room for a trailing NUL byte. | |
f4626df5 JS |
10 | */ |
11 | #ifndef SNPRINTF_SIZE_CORR | |
dae26d30 | 12 | #if defined(WIN32) && (!defined(__GNUC__) || __GNUC__ < 4) && (!defined(_MSC_VER) || _MSC_VER < 1900) |
f90cf2b9 JS |
13 | #define SNPRINTF_SIZE_CORR 1 |
14 | #else | |
f4626df5 JS |
15 | #define SNPRINTF_SIZE_CORR 0 |
16 | #endif | |
f90cf2b9 | 17 | #endif |
f4626df5 | 18 | |
c4582f93 MR |
19 | #undef vsnprintf |
20 | int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap) | |
21 | { | |
a9bfbc5b | 22 | va_list cp; |
c4582f93 | 23 | char *s; |
f4626df5 | 24 | int ret = -1; |
c4582f93 | 25 | |
f4626df5 | 26 | if (maxsize > 0) { |
a9bfbc5b JK |
27 | va_copy(cp, ap); |
28 | ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, cp); | |
29 | va_end(cp); | |
a81892dd BC |
30 | if (ret == maxsize-1) |
31 | ret = -1; | |
f4626df5 JS |
32 | /* Windows does not NUL-terminate if result fills buffer */ |
33 | str[maxsize-1] = 0; | |
34 | } | |
c4582f93 MR |
35 | if (ret != -1) |
36 | return ret; | |
37 | ||
38 | s = NULL; | |
39 | if (maxsize < 128) | |
40 | maxsize = 128; | |
41 | ||
42 | while (ret == -1) { | |
43 | maxsize *= 4; | |
44 | str = realloc(s, maxsize); | |
45 | if (! str) | |
46 | break; | |
47 | s = str; | |
a9bfbc5b JK |
48 | va_copy(cp, ap); |
49 | ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, cp); | |
50 | va_end(cp); | |
a81892dd BC |
51 | if (ret == maxsize-1) |
52 | ret = -1; | |
c4582f93 MR |
53 | } |
54 | free(s); | |
55 | return ret; | |
56 | } | |
57 | ||
58 | int git_snprintf(char *str, size_t maxsize, const char *format, ...) | |
59 | { | |
60 | va_list ap; | |
61 | int ret; | |
62 | ||
63 | va_start(ap, format); | |
64 | ret = git_vsnprintf(str, maxsize, format, ap); | |
65 | va_end(ap); | |
66 | ||
67 | return ret; | |
68 | } | |
69 |