diff options
Diffstat (limited to 'src/buffer.c')
-rw-r--r-- | src/buffer.c | 95 |
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); +} |