| #include "../git-compat-util.h" |
| |
| /* |
| * The size parameter specifies the available space, i.e. includes |
| * the trailing NUL byte; but Windows's vsnprintf uses the entire |
| * buffer and avoids the trailing NUL, should the buffer be exactly |
| * big enough for the result. Defining SNPRINTF_SIZE_CORR to 1 will |
| * therefore remove 1 byte from the reported buffer size, so we |
| * always have room for a trailing NUL byte. |
| */ |
| #ifndef SNPRINTF_SIZE_CORR |
| #if defined(WIN32) && (!defined(__GNUC__) || __GNUC__ < 4) && (!defined(_MSC_VER) || _MSC_VER < 1900) |
| #define SNPRINTF_SIZE_CORR 1 |
| #else |
| #define SNPRINTF_SIZE_CORR 0 |
| #endif |
| #endif |
| |
| #undef vsnprintf |
| int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap) |
| { |
| va_list cp; |
| char *s; |
| int ret = -1; |
| |
| if (maxsize > 0) { |
| va_copy(cp, ap); |
| ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, cp); |
| va_end(cp); |
| if (ret == maxsize-1) |
| ret = -1; |
| /* Windows does not NUL-terminate if result fills buffer */ |
| str[maxsize-1] = 0; |
| } |
| if (ret != -1) |
| return ret; |
| |
| s = NULL; |
| if (maxsize < 128) |
| maxsize = 128; |
| |
| while (ret == -1) { |
| maxsize *= 4; |
| str = realloc(s, maxsize); |
| if (! str) |
| break; |
| s = str; |
| va_copy(cp, ap); |
| ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, cp); |
| va_end(cp); |
| if (ret == maxsize-1) |
| ret = -1; |
| } |
| free(s); |
| return ret; |
| } |
| |
| int git_snprintf(char *str, size_t maxsize, const char *format, ...) |
| { |
| va_list ap; |
| int ret; |
| |
| va_start(ap, format); |
| ret = git_vsnprintf(str, maxsize, format, ap); |
| va_end(ap); |
| |
| return ret; |
| } |
| |