about summary refs log tree commit diff
path: root/third_party/git/compat/snprintf.c
diff options
context:
space:
mode:
authorVincent Ambo <Vincent Ambo>2020-01-11T23·36+0000
committerVincent Ambo <Vincent Ambo>2020-01-11T23·40+0000
commit7ef0d62730840ded097b524104cc0a0904591a63 (patch)
treea670f96103667aeca4789a95d94ca0dff550c4ce /third_party/git/compat/snprintf.c
parent6a2a3007077818e24a3d56fc492ada9206a10cf0 (diff)
parent1b593e1ea4d2af0f6444d9a7788d5d99abd6fde5 (diff)
merge(third_party/git): Merge squashed git subtree at v2.23.0 r/373
Merge commit '1b593e1ea4d2af0f6444d9a7788d5d99abd6fde5' as 'third_party/git'
Diffstat (limited to 'third_party/git/compat/snprintf.c')
-rw-r--r--third_party/git/compat/snprintf.c69
1 files changed, 69 insertions, 0 deletions
diff --git a/third_party/git/compat/snprintf.c b/third_party/git/compat/snprintf.c
new file mode 100644
index 0000000000..0b11688537
--- /dev/null
+++ b/third_party/git/compat/snprintf.c
@@ -0,0 +1,69 @@
+#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;
+}
+