summaryrefslogtreecommitdiff
path: root/src/buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/buffer.c')
-rw-r--r--src/buffer.c95
1 files changed, 95 insertions, 0 deletions
diff --git a/src/buffer.c b/src/buffer.c
new file mode 100644
index 000000000..6af4c9195
--- /dev/null
+++ b/src/buffer.c
@@ -0,0 +1,95 @@
+#include "buffer.h"
+#include "posix.h"
+#include <stdarg.h>
+
+#define ENSURE_SIZE(b, d) \
+ if ((ssize_t)(d) >= buf->asize && git_buf_grow(b, (d)) < GIT_SUCCESS)\
+ return;
+
+int git_buf_grow(git_buf *buf, size_t target_size)
+{
+ char *new_ptr;
+
+ if (buf->asize < 0)
+ return GIT_ENOMEM;
+
+ if (buf->asize == 0)
+ buf->asize = target_size;
+
+ /* grow the buffer size by 1.5, until it's big enough
+ * to fit our target size */
+ while (buf->asize < (int)target_size)
+ buf->asize = (buf->asize << 1) - (buf->asize >> 1);
+
+ new_ptr = git__realloc(buf->ptr, buf->asize);
+ if (!new_ptr) {
+ buf->asize = -1;
+ return GIT_ENOMEM;
+ }
+
+ buf->ptr = new_ptr;
+ return GIT_SUCCESS;
+}
+
+int git_buf_oom(const git_buf *buf)
+{
+ return (buf->asize < 0);
+}
+
+void git_buf_putc(git_buf *buf, char c)
+{
+ ENSURE_SIZE(buf, buf->size + 1);
+ buf->ptr[buf->size++] = c;
+}
+
+void git_buf_put(git_buf *buf, const char *data, size_t len)
+{
+ ENSURE_SIZE(buf, buf->size + len);
+ memcpy(buf->ptr + buf->size, data, len);
+ buf->size += len;
+}
+
+void git_buf_puts(git_buf *buf, const char *string)
+{
+ git_buf_put(buf, string, strlen(string));
+}
+
+void git_buf_printf(git_buf *buf, const char *format, ...)
+{
+ int len;
+ va_list arglist;
+
+ ENSURE_SIZE(buf, buf->size + 1);
+
+ while (1) {
+ va_start(arglist, format);
+ len = p_vsnprintf(buf->ptr + buf->size, buf->asize - buf->size, format, arglist);
+ va_end(arglist);
+
+ if (len < 0) {
+ buf->asize = -1;
+ return;
+ }
+
+ if (len + 1 <= buf->asize - buf->size) {
+ buf->size += len;
+ return;
+ }
+
+ ENSURE_SIZE(buf, buf->size + len + 1);
+ }
+}
+
+const char *git_buf_cstr(git_buf *buf)
+{
+ if (buf->size + 1 >= buf->asize && git_buf_grow(buf, buf->size + 1) < GIT_SUCCESS)
+ return NULL;
+
+ buf->ptr[buf->size] = '\0';
+ return buf->ptr;
+}
+
+void git_buf_free(git_buf *buf)
+{
+ free(buf->ptr);
+}