]>
Commit | Line | Data |
---|---|---|
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 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. | |
10 | */ | |
11 | #ifndef SNPRINTF_SIZE_CORR | |
12 | #if defined(WIN32) && (!defined(__GNUC__) || __GNUC__ < 4) && (!defined(_MSC_VER) || _MSC_VER < 1900) | |
13 | #define SNPRINTF_SIZE_CORR 1 | |
14 | #else | |
15 | #define SNPRINTF_SIZE_CORR 0 | |
16 | #endif | |
17 | #endif | |
18 | ||
19 | #undef vsnprintf | |
20 | int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap) | |
21 | { | |
22 | va_list cp; | |
23 | char *s; | |
24 | int ret = -1; | |
25 | ||
26 | if (maxsize > 0) { | |
27 | va_copy(cp, ap); | |
28 | ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, cp); | |
29 | va_end(cp); | |
30 | if (ret == maxsize-1) | |
31 | ret = -1; | |
32 | /* Windows does not NUL-terminate if result fills buffer */ | |
33 | str[maxsize-1] = 0; | |
34 | } | |
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; | |
48 | va_copy(cp, ap); | |
49 | ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, cp); | |
50 | va_end(cp); | |
51 | if (ret == maxsize-1) | |
52 | ret = -1; | |
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 |