Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/libgit2.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell Belfer <arrbee@arrbee.com>2011-11-30 23:27:15 +0400
committerRussell Belfer <arrbee@arrbee.com>2011-12-08 11:08:15 +0400
commit97769280ba9938ae27f6e06cbd0d5e8a768a86b9 (patch)
tree4fe43e99acb55f904f6b586bd7c5158610f9512f /src/buffer.c
parenta22b14d32dd8d5f06f121aa154d45bac3b10a305 (diff)
Use git_buf for path storage instead of stack-based buffers
This converts virtually all of the places that allocate GIT_PATH_MAX buffers on the stack for manipulating paths to use git_buf objects instead. The patch is pretty careful not to touch the public API for libgit2, so there are a few places that still use GIT_PATH_MAX. This extends and changes some details of the git_buf implementation to add a couple of extra functions and to make error handling easier. This includes serious alterations to all the path.c functions, and several of the fileops.c ones, too. Also, there are a number of new functions that parallel existing ones except that use a git_buf instead of a stack-based buffer (such as git_config_find_global_r that exists alongsize git_config_find_global). This also modifies the win32 version of p_realpath to allocate whatever buffer size is needed to accommodate the realpath instead of hardcoding a GIT_PATH_MAX limit, but that change needs to be tested still.
Diffstat (limited to 'src/buffer.c')
-rw-r--r--src/buffer.c96
1 files changed, 74 insertions, 22 deletions
diff --git a/src/buffer.c b/src/buffer.c
index b90dd29c5..295b87e1a 100644
--- a/src/buffer.c
+++ b/src/buffer.c
@@ -15,7 +15,8 @@ char git_buf_initbuf[1];
#define ENSURE_SIZE(b, d) \
if ((ssize_t)(d) > buf->asize && git_buf_grow(b, (d)) < GIT_SUCCESS)\
- return;
+ return GIT_ENOMEM;
+
void git_buf_init(git_buf *buf, size_t initial_size)
{
@@ -29,6 +30,14 @@ void git_buf_init(git_buf *buf, size_t initial_size)
int git_buf_grow(git_buf *buf, size_t target_size)
{
+ int error = git_buf_try_grow(buf, target_size);
+ if (error != GIT_SUCCESS)
+ buf->asize = -1;
+ return error;
+}
+
+int git_buf_try_grow(git_buf *buf, size_t target_size)
+{
char *new_ptr;
size_t new_size;
@@ -55,10 +64,9 @@ int git_buf_grow(git_buf *buf, size_t target_size)
new_size = (new_size + 7) & ~7;
new_ptr = git__realloc(new_ptr, new_size);
- if (!new_ptr) {
- buf->asize = -1;
+ /* if realloc fails, return without modifying the git_buf */
+ if (!new_ptr)
return GIT_ENOMEM;
- }
buf->asize = new_size;
buf->ptr = new_ptr;
@@ -93,7 +101,12 @@ int git_buf_oom(const git_buf *buf)
return (buf->asize < 0);
}
-void git_buf_set(git_buf *buf, const char *data, size_t len)
+int git_buf_lasterror(const git_buf *buf)
+{
+ return (buf->asize < 0) ? GIT_ENOMEM : GIT_SUCCESS;
+}
+
+int git_buf_set(git_buf *buf, const char *data, size_t len)
{
if (len == 0 || data == NULL) {
git_buf_clear(buf);
@@ -103,35 +116,38 @@ void git_buf_set(git_buf *buf, const char *data, size_t len)
buf->size = len;
buf->ptr[buf->size] = '\0';
}
+ return GIT_SUCCESS;
}
-void git_buf_sets(git_buf *buf, const char *string)
+int git_buf_sets(git_buf *buf, const char *string)
{
- git_buf_set(buf, string, string ? strlen(string) : 0);
+ return git_buf_set(buf, string, string ? strlen(string) : 0);
}
-void git_buf_putc(git_buf *buf, char c)
+int git_buf_putc(git_buf *buf, char c)
{
ENSURE_SIZE(buf, buf->size + 2);
buf->ptr[buf->size++] = c;
buf->ptr[buf->size] = '\0';
+ return GIT_SUCCESS;
}
-void git_buf_put(git_buf *buf, const char *data, size_t len)
+int git_buf_put(git_buf *buf, const char *data, size_t len)
{
ENSURE_SIZE(buf, buf->size + len + 1);
memmove(buf->ptr + buf->size, data, len);
buf->size += len;
buf->ptr[buf->size] = '\0';
+ return GIT_SUCCESS;
}
-void git_buf_puts(git_buf *buf, const char *string)
+int git_buf_puts(git_buf *buf, const char *string)
{
assert(string);
- git_buf_put(buf, string, strlen(string));
+ return git_buf_put(buf, string, strlen(string));
}
-void git_buf_printf(git_buf *buf, const char *format, ...)
+int git_buf_printf(git_buf *buf, const char *format, ...)
{
int len;
va_list arglist;
@@ -145,16 +161,18 @@ void git_buf_printf(git_buf *buf, const char *format, ...)
if (len < 0) {
buf->asize = -1;
- return;
+ return GIT_ENOMEM;
}
if (len + 1 <= buf->asize - buf->size) {
buf->size += len;
- return;
+ break;
}
ENSURE_SIZE(buf, buf->size + len + 1);
}
+
+ return GIT_SUCCESS;
}
const char *git_buf_cstr(git_buf *buf)
@@ -162,7 +180,7 @@ const char *git_buf_cstr(git_buf *buf)
return buf->ptr;
}
-void git_buf_copy_cstr(char *data, size_t datasize, git_buf *buf)
+void git_buf_copy_cstr(char *data, size_t datasize, const git_buf *buf)
{
size_t copylen;
@@ -190,6 +208,14 @@ void git_buf_consume(git_buf *buf, const char *end)
}
}
+void git_buf_truncate(git_buf *buf, ssize_t len)
+{
+ if (len < buf->size) {
+ buf->size = len;
+ buf->ptr[buf->size] = '\0';
+ }
+}
+
void git_buf_swap(git_buf *buf_a, git_buf *buf_b)
{
git_buf t = *buf_a;
@@ -197,7 +223,7 @@ void git_buf_swap(git_buf *buf_a, git_buf *buf_b)
*buf_b = t;
}
-char *git_buf_take_cstr(git_buf *buf)
+char *git_buf_detach(git_buf *buf)
{
char *data = buf->ptr;
@@ -209,18 +235,34 @@ char *git_buf_take_cstr(git_buf *buf)
return data;
}
-void git_buf_join_n(git_buf *buf, char separator, int nbuf, ...)
+void git_buf_attach(git_buf *buf, char *ptr, ssize_t asize)
{
- /* Make two passes to avoid multiple reallocation */
+ git_buf_free(buf);
+
+ if (ptr) {
+ buf->ptr = ptr;
+ buf->size = strlen(ptr);
+ if (asize)
+ buf->asize = (asize < buf->size) ? buf->size + 1 : asize;
+ else /* pass 0 to fall back on strlen + 1 */
+ buf->asize = buf->size + 1;
+ } else {
+ git_buf_grow(buf, asize);
+ }
+}
+int git_buf_join_n(git_buf *buf, char separator, int nbuf, ...)
+{
va_list ap;
- int i;
+ int i, error = GIT_SUCCESS;
size_t total_size = 0;
char *out;
if (buf->size > 0 && buf->ptr[buf->size - 1] != separator)
++total_size; /* space for initial separator */
+ /* Make two passes to avoid multiple reallocation */
+
va_start(ap, nbuf);
for (i = 0; i < nbuf; ++i) {
const char* segment;
@@ -237,7 +279,10 @@ void git_buf_join_n(git_buf *buf, char separator, int nbuf, ...)
}
va_end(ap);
- ENSURE_SIZE(buf, buf->size + total_size + 1);
+ /* expand buffer if needed */
+ if (total_size > 0 &&
+ (error = git_buf_grow(buf, buf->size + total_size + 1)) < GIT_SUCCESS)
+ return error;
out = buf->ptr + buf->size;
@@ -274,14 +319,17 @@ void git_buf_join_n(git_buf *buf, char separator, int nbuf, ...)
/* set size based on num characters actually written */
buf->size = out - buf->ptr;
buf->ptr[buf->size] = '\0';
+
+ return error;
}
-void git_buf_join(
+int git_buf_join(
git_buf *buf,
char separator,
const char *str_a,
const char *str_b)
{
+ int error = GIT_SUCCESS;
size_t strlen_a = strlen(str_a);
size_t strlen_b = strlen(str_b);
int need_sep = 0;
@@ -293,7 +341,9 @@ void git_buf_join(
need_sep = 1;
}
- ENSURE_SIZE(buf, strlen_a + strlen_b + need_sep + 1);
+ error = git_buf_grow(buf, strlen_a + strlen_b + need_sep + 1);
+ if (error < GIT_SUCCESS)
+ return error;
memmove(buf->ptr, str_a, strlen_a);
if (need_sep)
@@ -302,4 +352,6 @@ void git_buf_join(
buf->size = strlen_a + strlen_b + need_sep;
buf->ptr[buf->size] = '\0';
+
+ return error;
}