mirror of
https://git.proxmox.com/git/libgit2
synced 2025-05-28 14:02:57 +00:00
Merge pull request #499 from arrbee/extend-git-buf
Extend git_buf with new utility functions and unit tests.
This commit is contained in:
commit
798dd36c08
198
src/buffer.c
198
src/buffer.c
@ -9,7 +9,7 @@
|
||||
#include <stdarg.h>
|
||||
|
||||
#define ENSURE_SIZE(b, d) \
|
||||
if ((ssize_t)(d) >= buf->asize && git_buf_grow(b, (d)) < GIT_SUCCESS)\
|
||||
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)
|
||||
@ -19,6 +19,9 @@ int git_buf_grow(git_buf *buf, size_t target_size)
|
||||
if (buf->asize < 0)
|
||||
return GIT_ENOMEM;
|
||||
|
||||
if (target_size <= (size_t)buf->asize)
|
||||
return GIT_SUCCESS;
|
||||
|
||||
if (buf->asize == 0)
|
||||
buf->asize = target_size;
|
||||
|
||||
@ -27,6 +30,9 @@ int git_buf_grow(git_buf *buf, size_t target_size)
|
||||
while (buf->asize < (int)target_size)
|
||||
buf->asize = (buf->asize << 1) - (buf->asize >> 1);
|
||||
|
||||
/* round allocation up to multiple of 8 */
|
||||
buf->asize = (buf->asize + 7) & ~7;
|
||||
|
||||
new_ptr = git__realloc(buf->ptr, buf->asize);
|
||||
if (!new_ptr) {
|
||||
buf->asize = -1;
|
||||
@ -42,6 +48,22 @@ 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)
|
||||
{
|
||||
if (len == 0 || data == NULL) {
|
||||
git_buf_clear(buf);
|
||||
} else {
|
||||
ENSURE_SIZE(buf, len);
|
||||
memmove(buf->ptr, data, len);
|
||||
buf->size = len;
|
||||
}
|
||||
}
|
||||
|
||||
void git_buf_sets(git_buf *buf, const char *string)
|
||||
{
|
||||
git_buf_set(buf, string, string ? strlen(string) : 0);
|
||||
}
|
||||
|
||||
void git_buf_putc(git_buf *buf, char c)
|
||||
{
|
||||
ENSURE_SIZE(buf, buf->size + 1);
|
||||
@ -51,12 +73,13 @@ void git_buf_putc(git_buf *buf, char 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);
|
||||
memmove(buf->ptr + buf->size, data, len);
|
||||
buf->size += len;
|
||||
}
|
||||
|
||||
void git_buf_puts(git_buf *buf, const char *string)
|
||||
{
|
||||
assert(string);
|
||||
git_buf_put(buf, string, strlen(string));
|
||||
}
|
||||
|
||||
@ -88,7 +111,8 @@ void git_buf_printf(git_buf *buf, const char *format, ...)
|
||||
|
||||
const char *git_buf_cstr(git_buf *buf)
|
||||
{
|
||||
if (buf->size + 1 >= buf->asize && git_buf_grow(buf, buf->size + 1) < GIT_SUCCESS)
|
||||
if (buf->size + 1 > buf->asize &&
|
||||
git_buf_grow(buf, buf->size + 1) < GIT_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
buf->ptr[buf->size] = '\0';
|
||||
@ -97,7 +121,12 @@ const char *git_buf_cstr(git_buf *buf)
|
||||
|
||||
void git_buf_free(git_buf *buf)
|
||||
{
|
||||
if (!buf) return;
|
||||
|
||||
git__free(buf->ptr);
|
||||
buf->ptr = NULL;
|
||||
buf->asize = 0;
|
||||
buf->size = 0;
|
||||
}
|
||||
|
||||
void git_buf_clear(git_buf *buf)
|
||||
@ -107,7 +136,164 @@ void git_buf_clear(git_buf *buf)
|
||||
|
||||
void git_buf_consume(git_buf *buf, const char *end)
|
||||
{
|
||||
size_t consumed = end - buf->ptr;
|
||||
memmove(buf->ptr, end, buf->size - consumed);
|
||||
buf->size -= consumed;
|
||||
if (end > buf->ptr && end <= buf->ptr + buf->size) {
|
||||
size_t consumed = end - buf->ptr;
|
||||
memmove(buf->ptr, end, buf->size - consumed);
|
||||
buf->size -= consumed;
|
||||
}
|
||||
}
|
||||
|
||||
void git_buf_swap(git_buf *buf_a, git_buf *buf_b)
|
||||
{
|
||||
git_buf t = *buf_a;
|
||||
*buf_a = *buf_b;
|
||||
*buf_b = t;
|
||||
}
|
||||
|
||||
char *git_buf_take_cstr(git_buf *buf)
|
||||
{
|
||||
char *data = NULL;
|
||||
|
||||
if (buf->ptr == NULL)
|
||||
return NULL;
|
||||
|
||||
if (buf->size + 1 > buf->asize &&
|
||||
git_buf_grow(buf, buf->size + 1) < GIT_SUCCESS)
|
||||
return NULL;
|
||||
|
||||
data = buf->ptr;
|
||||
data[buf->size] = '\0';
|
||||
|
||||
buf->ptr = NULL;
|
||||
buf->asize = 0;
|
||||
buf->size = 0;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void git_buf_join_n(git_buf *buf, char separator, int nbuf, ...)
|
||||
{
|
||||
/* Make two passes to avoid multiple reallocation */
|
||||
|
||||
va_list ap;
|
||||
int i;
|
||||
size_t total_size = 0;
|
||||
char *out;
|
||||
|
||||
if (buf->size > 0 && buf->ptr[buf->size - 1] != separator)
|
||||
++total_size; /* space for initial separator */
|
||||
|
||||
va_start(ap, nbuf);
|
||||
for (i = 0; i < nbuf; ++i) {
|
||||
const char* segment;
|
||||
size_t segment_len;
|
||||
|
||||
segment = va_arg(ap, const char *);
|
||||
if (!segment)
|
||||
continue;
|
||||
|
||||
segment_len = strlen(segment);
|
||||
total_size += segment_len;
|
||||
if (segment_len == 0 || segment[segment_len - 1] != separator)
|
||||
++total_size; /* space for separator */
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
ENSURE_SIZE(buf, buf->size + total_size);
|
||||
|
||||
out = buf->ptr + buf->size;
|
||||
|
||||
/* append separator to existing buf if needed */
|
||||
if (buf->size > 0 && out[-1] != separator)
|
||||
*out++ = separator;
|
||||
|
||||
va_start(ap, nbuf);
|
||||
for (i = 0; i < nbuf; ++i) {
|
||||
const char* segment;
|
||||
size_t segment_len;
|
||||
|
||||
segment = va_arg(ap, const char *);
|
||||
if (!segment)
|
||||
continue;
|
||||
|
||||
/* skip leading separators */
|
||||
if (out > buf->ptr && out[-1] == separator)
|
||||
while (*segment == separator) segment++;
|
||||
|
||||
/* copy over next buffer */
|
||||
segment_len = strlen(segment);
|
||||
if (segment_len > 0) {
|
||||
memmove(out, segment, segment_len);
|
||||
out += segment_len;
|
||||
}
|
||||
|
||||
/* append trailing separator (except for last item) */
|
||||
if (i < nbuf - 1 && out > buf->ptr && out[-1] != separator)
|
||||
*out++ = separator;
|
||||
}
|
||||
va_end(ap);
|
||||
|
||||
/* set size based on num characters actually written */
|
||||
buf->size = out - buf->ptr;
|
||||
}
|
||||
|
||||
void git_buf_join(
|
||||
git_buf *buf,
|
||||
char separator,
|
||||
const char *str_a,
|
||||
const char *str_b)
|
||||
{
|
||||
size_t add_size = 0;
|
||||
size_t sep_a = 0;
|
||||
size_t strlen_a = 0;
|
||||
size_t sep_b = 0;
|
||||
size_t strlen_b = 0;
|
||||
char *ptr;
|
||||
|
||||
/* calculate string lengths and need for added separators */
|
||||
if (str_a) {
|
||||
while (*str_a == separator) { sep_a = 1; str_a++; }
|
||||
strlen_a = strlen(str_a);
|
||||
}
|
||||
if (str_b) {
|
||||
while (*str_b == separator) { sep_b = 1; str_b++; }
|
||||
strlen_b = strlen(str_b);
|
||||
}
|
||||
if (buf->size > 0) {
|
||||
if (buf->ptr[buf->size - 1] == separator) {
|
||||
sep_a = 0;
|
||||
if (!strlen_a) sep_b = 0;
|
||||
} else if (!strlen_a)
|
||||
sep_b = (str_b != NULL);
|
||||
}
|
||||
if (strlen_a > 0) {
|
||||
if (str_a[strlen_a - 1] == separator)
|
||||
sep_b = 0;
|
||||
else if (str_b)
|
||||
sep_b = 1;
|
||||
}
|
||||
|
||||
add_size = sep_a + strlen_a + sep_b + strlen_b;
|
||||
|
||||
if (!add_size) return;
|
||||
|
||||
ENSURE_SIZE(buf, buf->size + add_size);
|
||||
|
||||
/* concatenate strings */
|
||||
ptr = buf->ptr + buf->size;
|
||||
if (sep_a)
|
||||
*ptr++ = separator;
|
||||
if (strlen_a) {
|
||||
memmove(ptr, str_a, strlen_a);
|
||||
ptr += strlen_a;
|
||||
}
|
||||
if (sep_b)
|
||||
*ptr++ = separator;
|
||||
if (strlen_b) {
|
||||
memmove(ptr, str_b, strlen_b);
|
||||
ptr += strlen_b;
|
||||
}
|
||||
|
||||
/* set size based on num characters actually written */
|
||||
buf->size = ptr - buf->ptr;
|
||||
}
|
||||
|
20
src/buffer.h
20
src/buffer.h
@ -17,15 +17,31 @@ typedef struct {
|
||||
#define GIT_BUF_INIT {NULL, 0, 0}
|
||||
|
||||
int git_buf_grow(git_buf *buf, size_t target_size);
|
||||
void git_buf_free(git_buf *buf);
|
||||
void git_buf_swap(git_buf *buf_a, git_buf *buf_b);
|
||||
|
||||
/**
|
||||
* Any function that writes to a git_buf can fail due to memory allocation
|
||||
* issues. If one fails, the git_buf will be marked with an OOM error and
|
||||
* further calls to modify the buffer will fail. You just check
|
||||
* git_buf_oom() at the end of your sequence and it will be true if you ran
|
||||
* out of memory at any point with that buffer.
|
||||
*/
|
||||
int git_buf_oom(const git_buf *buf);
|
||||
|
||||
void git_buf_set(git_buf *buf, const char *data, size_t len);
|
||||
void git_buf_sets(git_buf *buf, const char *string);
|
||||
void git_buf_putc(git_buf *buf, char c);
|
||||
void git_buf_put(git_buf *buf, const char *data, size_t len);
|
||||
void git_buf_puts(git_buf *buf, const char *string);
|
||||
void git_buf_printf(git_buf *buf, const char *format, ...) GIT_FORMAT_PRINTF(2, 3);
|
||||
const char *git_buf_cstr(git_buf *buf);
|
||||
void git_buf_free(git_buf *buf);
|
||||
void git_buf_clear(git_buf *buf);
|
||||
void git_buf_consume(git_buf *buf, const char *end);
|
||||
void git_buf_join_n(git_buf *buf, char separator, int nbuf, ...);
|
||||
void git_buf_join(git_buf *buf, char separator, const char *str_a, const char *str_b);
|
||||
|
||||
const char *git_buf_cstr(git_buf *buf);
|
||||
char *git_buf_take_cstr(git_buf *buf);
|
||||
|
||||
#define git_buf_PUTS(buf, str) git_buf_put(buf, str, sizeof(str) - 1)
|
||||
|
||||
|
@ -25,4 +25,20 @@
|
||||
*/
|
||||
#define cl_git_fail(expr) cl_must_fail(expr)
|
||||
|
||||
/**
|
||||
* Wrapper for string comparison that knows about nulls.
|
||||
*/
|
||||
#define cl_assert_strequal(a,b) \
|
||||
cl_assert_strequal_internal(a,b,__FILE__,__LINE__)
|
||||
|
||||
GIT_INLINE(void) cl_assert_strequal_internal(const char *a, const char *b, const char *file, int line)
|
||||
{
|
||||
int match = (a == NULL || b == NULL) ? (a == b) : (strcmp(a, b) == 0);
|
||||
if (!match) {
|
||||
char buf[4096];
|
||||
snprintf(buf, 4096, "'%s' != '%s'", a, b);
|
||||
clay__assert(0, file, line, buf, "Strings do not match", 1);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
474
tests-clay/core/buffer.c
Normal file
474
tests-clay/core/buffer.c
Normal file
@ -0,0 +1,474 @@
|
||||
#include "clay_libgit2.h"
|
||||
#include "buffer.h"
|
||||
|
||||
#define TESTSTR "Have you seen that? Have you seeeen that??"
|
||||
const char *test_string = TESTSTR;
|
||||
const char *test_string_x2 = TESTSTR TESTSTR;
|
||||
|
||||
#define REP4(STR) STR STR STR STR
|
||||
#define REP16(STR) REP4(REP4(STR))
|
||||
#define REP1024(STR) REP16(REP16(REP4(STR)))
|
||||
#define TESTSTR_4096 REP1024("1234")
|
||||
#define TESTSTR_8192 REP1024("12341234")
|
||||
const char *test_4096 = TESTSTR_4096;
|
||||
const char *test_8192 = TESTSTR_8192;
|
||||
|
||||
/* test basic data concatenation */
|
||||
void test_core_buffer__0(void)
|
||||
{
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
cl_assert(buf.size == 0);
|
||||
|
||||
git_buf_puts(&buf, test_string);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal(test_string, git_buf_cstr(&buf));
|
||||
|
||||
git_buf_puts(&buf, test_string);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal(test_string_x2, git_buf_cstr(&buf));
|
||||
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
/* test git_buf_printf */
|
||||
void test_core_buffer__1(void)
|
||||
{
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
git_buf_printf(&buf, "%s %s %d ", "shoop", "da", 23);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal("shoop da 23 ", git_buf_cstr(&buf));
|
||||
|
||||
git_buf_printf(&buf, "%s %d", "woop", 42);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal("shoop da 23 woop 42", git_buf_cstr(&buf));
|
||||
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
/* more thorough test of concatenation options */
|
||||
void test_core_buffer__2(void)
|
||||
{
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
int i;
|
||||
|
||||
cl_assert(buf.size == 0);
|
||||
|
||||
/* this must be safe to do */
|
||||
git_buf_free(&buf);
|
||||
|
||||
cl_assert(buf.size == 0);
|
||||
cl_assert(buf.asize == 0);
|
||||
|
||||
/* empty buffer should be empty string */
|
||||
cl_assert_strequal("", git_buf_cstr(&buf));
|
||||
cl_assert(buf.size == 0);
|
||||
cl_assert(buf.asize > 0);
|
||||
|
||||
/* free should set us back to the beginning */
|
||||
git_buf_free(&buf);
|
||||
cl_assert(buf.size == 0);
|
||||
cl_assert(buf.asize == 0);
|
||||
|
||||
/* add letter */
|
||||
git_buf_putc(&buf, '+');
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal("+", git_buf_cstr(&buf));
|
||||
|
||||
/* add letter again */
|
||||
git_buf_putc(&buf, '+');
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal("++", git_buf_cstr(&buf));
|
||||
|
||||
/* let's try that a few times */
|
||||
for (i = 0; i < 16; ++i) {
|
||||
git_buf_putc(&buf, '+');
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
}
|
||||
cl_assert_strequal("++++++++++++++++++", git_buf_cstr(&buf));
|
||||
|
||||
git_buf_free(&buf);
|
||||
|
||||
/* add data */
|
||||
git_buf_put(&buf, "xo", 2);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal("xo", git_buf_cstr(&buf));
|
||||
|
||||
/* add letter again */
|
||||
git_buf_put(&buf, "xo", 2);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal("xoxo", git_buf_cstr(&buf));
|
||||
|
||||
/* let's try that a few times */
|
||||
for (i = 0; i < 16; ++i) {
|
||||
git_buf_put(&buf, "xo", 2);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
}
|
||||
cl_assert_strequal("xoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxoxo",
|
||||
git_buf_cstr(&buf));
|
||||
|
||||
git_buf_free(&buf);
|
||||
|
||||
/* set to string */
|
||||
git_buf_sets(&buf, test_string);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal(test_string, git_buf_cstr(&buf));
|
||||
|
||||
/* append string */
|
||||
git_buf_puts(&buf, test_string);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal(test_string_x2, git_buf_cstr(&buf));
|
||||
|
||||
/* set to string again (should overwrite - not append) */
|
||||
git_buf_sets(&buf, test_string);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal(test_string, git_buf_cstr(&buf));
|
||||
|
||||
/* test clear */
|
||||
git_buf_clear(&buf);
|
||||
cl_assert_strequal("", git_buf_cstr(&buf));
|
||||
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
/* let's do some tests with larger buffers to push our limits */
|
||||
void test_core_buffer__3(void)
|
||||
{
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
/* set to string */
|
||||
git_buf_set(&buf, test_4096, 4096);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal(test_4096, git_buf_cstr(&buf));
|
||||
|
||||
/* append string */
|
||||
git_buf_puts(&buf, test_4096);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal(test_8192, git_buf_cstr(&buf));
|
||||
|
||||
/* set to string again (should overwrite - not append) */
|
||||
git_buf_set(&buf, test_4096, 4096);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal(test_4096, git_buf_cstr(&buf));
|
||||
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
/* let's try some producer/consumer tests */
|
||||
void test_core_buffer__4(void)
|
||||
{
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 10; ++i) {
|
||||
git_buf_puts(&buf, "1234"); /* add 4 */
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
git_buf_consume(&buf, buf.ptr + 2); /* eat the first two */
|
||||
cl_assert(strlen(git_buf_cstr(&buf)) == (size_t)((i + 1) * 2));
|
||||
}
|
||||
/* we have appended 1234 10x and removed the first 20 letters */
|
||||
cl_assert_strequal("12341234123412341234", git_buf_cstr(&buf));
|
||||
|
||||
git_buf_consume(&buf, NULL);
|
||||
cl_assert_strequal("12341234123412341234", git_buf_cstr(&buf));
|
||||
|
||||
git_buf_consume(&buf, "invalid pointer");
|
||||
cl_assert_strequal("12341234123412341234", git_buf_cstr(&buf));
|
||||
|
||||
git_buf_consume(&buf, buf.ptr);
|
||||
cl_assert_strequal("12341234123412341234", git_buf_cstr(&buf));
|
||||
|
||||
git_buf_consume(&buf, buf.ptr + 1);
|
||||
cl_assert_strequal("2341234123412341234", git_buf_cstr(&buf));
|
||||
|
||||
git_buf_consume(&buf, buf.ptr + buf.size);
|
||||
cl_assert_strequal("", git_buf_cstr(&buf));
|
||||
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
check_buf_append(
|
||||
const char* data_a,
|
||||
const char* data_b,
|
||||
const char* expected_data,
|
||||
ssize_t expected_size,
|
||||
ssize_t expected_asize)
|
||||
{
|
||||
git_buf tgt = GIT_BUF_INIT;
|
||||
|
||||
git_buf_sets(&tgt, data_a);
|
||||
cl_assert(git_buf_oom(&tgt) == 0);
|
||||
git_buf_puts(&tgt, data_b);
|
||||
cl_assert(git_buf_oom(&tgt) == 0);
|
||||
if (expected_data == NULL)
|
||||
cl_assert(tgt.ptr == NULL);
|
||||
else
|
||||
cl_assert_strequal(expected_data, git_buf_cstr(&tgt));
|
||||
cl_assert(tgt.size == expected_size);
|
||||
if (expected_asize > 0)
|
||||
cl_assert(tgt.asize == expected_asize);
|
||||
|
||||
git_buf_free(&tgt);
|
||||
}
|
||||
|
||||
static void
|
||||
check_buf_append_abc(
|
||||
const char* buf_a,
|
||||
const char* buf_b,
|
||||
const char* buf_c,
|
||||
const char* expected_ab,
|
||||
const char* expected_abc,
|
||||
const char* expected_abca,
|
||||
const char* expected_abcab,
|
||||
const char* expected_abcabc)
|
||||
{
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
git_buf_sets(&buf, buf_a);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal(buf_a, git_buf_cstr(&buf));
|
||||
|
||||
git_buf_puts(&buf, buf_b);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal(expected_ab, git_buf_cstr(&buf));
|
||||
|
||||
git_buf_puts(&buf, buf_c);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal(expected_abc, git_buf_cstr(&buf));
|
||||
|
||||
git_buf_puts(&buf, buf_a);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal(expected_abca, git_buf_cstr(&buf));
|
||||
|
||||
git_buf_puts(&buf, buf_b);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal(expected_abcab, git_buf_cstr(&buf));
|
||||
|
||||
git_buf_puts(&buf, buf_c);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal(expected_abcabc, git_buf_cstr(&buf));
|
||||
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
/* more variations on append tests */
|
||||
void test_core_buffer__5(void)
|
||||
{
|
||||
check_buf_append("", "", "", 0, 8);
|
||||
check_buf_append("a", "", "a", 1, 8);
|
||||
check_buf_append("", "a", "a", 1, 8);
|
||||
check_buf_append("", "a", "a", 1, 8);
|
||||
check_buf_append("a", "", "a", 1, 8);
|
||||
check_buf_append("a", "b", "ab", 2, 8);
|
||||
check_buf_append("", "abcdefgh", "abcdefgh", 8, 16);
|
||||
check_buf_append("abcdefgh", "", "abcdefgh", 8, 16);
|
||||
|
||||
/* buffer with starting asize will grow to:
|
||||
* 1 -> 2, 2 -> 3, 3 -> 5, 4 -> 6, 5 -> 8, 6 -> 9,
|
||||
* 7 -> 11, 8 -> 12, 9 -> 14, 10 -> 15, 11 -> 17, 12 -> 18,
|
||||
* 13 -> 20, 14 -> 21, 15 -> 23, 16 -> 24, 17 -> 26, 18 -> 27,
|
||||
* 19 -> 29, 20 -> 30, 21 -> 32, 22 -> 33, 23 -> 35, 24 -> 36,
|
||||
* ...
|
||||
* follow sequence until value > target size,
|
||||
* then round up to nearest multiple of 8.
|
||||
*/
|
||||
|
||||
check_buf_append("abcdefgh", "/", "abcdefgh/", 9, 16);
|
||||
check_buf_append("abcdefgh", "ijklmno", "abcdefghijklmno", 15, 24);
|
||||
check_buf_append("abcdefgh", "ijklmnop", "abcdefghijklmnop", 16, 24);
|
||||
check_buf_append("0123456789", "0123456789",
|
||||
"01234567890123456789", 20, 24);
|
||||
check_buf_append(REP16("x"), REP16("o"),
|
||||
REP16("x") REP16("o"), 32, 40);
|
||||
|
||||
check_buf_append(test_4096, "", test_4096, 4096, 6144);
|
||||
check_buf_append(test_4096, test_4096, test_8192, 8192, 9216);
|
||||
|
||||
/* check sequences of appends */
|
||||
check_buf_append_abc("a", "b", "c",
|
||||
"ab", "abc", "abca", "abcab", "abcabc");
|
||||
check_buf_append_abc("a1", "b2", "c3",
|
||||
"a1b2", "a1b2c3", "a1b2c3a1",
|
||||
"a1b2c3a1b2", "a1b2c3a1b2c3");
|
||||
check_buf_append_abc("a1/", "b2/", "c3/",
|
||||
"a1/b2/", "a1/b2/c3/", "a1/b2/c3/a1/",
|
||||
"a1/b2/c3/a1/b2/", "a1/b2/c3/a1/b2/c3/");
|
||||
}
|
||||
|
||||
/* test swap */
|
||||
void test_core_buffer__6(void)
|
||||
{
|
||||
git_buf a = GIT_BUF_INIT;
|
||||
git_buf b = GIT_BUF_INIT;
|
||||
|
||||
git_buf_sets(&a, "foo");
|
||||
cl_assert(git_buf_oom(&a) == 0);
|
||||
git_buf_sets(&b, "bar");
|
||||
cl_assert(git_buf_oom(&b) == 0);
|
||||
|
||||
cl_assert_strequal("foo", git_buf_cstr(&a));
|
||||
cl_assert_strequal("bar", git_buf_cstr(&b));
|
||||
|
||||
git_buf_swap(&a, &b);
|
||||
|
||||
cl_assert_strequal("bar", git_buf_cstr(&a));
|
||||
cl_assert_strequal("foo", git_buf_cstr(&b));
|
||||
|
||||
git_buf_free(&a);
|
||||
git_buf_free(&b);
|
||||
}
|
||||
|
||||
|
||||
/* test take cstr data */
|
||||
void test_core_buffer__7(void)
|
||||
{
|
||||
git_buf a = GIT_BUF_INIT;
|
||||
char *b = NULL;
|
||||
|
||||
git_buf_sets(&a, "foo");
|
||||
cl_assert(git_buf_oom(&a) == 0);
|
||||
cl_assert_strequal("foo", git_buf_cstr(&a));
|
||||
|
||||
b = git_buf_take_cstr(&a);
|
||||
|
||||
cl_assert_strequal("foo", b);
|
||||
cl_assert_strequal(NULL, a.ptr);
|
||||
git__free(b);
|
||||
|
||||
b = git_buf_take_cstr(&a);
|
||||
|
||||
cl_assert_strequal(NULL, b);
|
||||
cl_assert_strequal(NULL, a.ptr);
|
||||
|
||||
git_buf_free(&a);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
check_joinbuf_2(
|
||||
const char *a,
|
||||
const char *b,
|
||||
const char *expected)
|
||||
{
|
||||
char sep = '/';
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
/* first validate join from nothing */
|
||||
git_buf_join(&buf, sep, a, b);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal(expected, git_buf_cstr(&buf));
|
||||
git_buf_free(&buf);
|
||||
|
||||
/* next validate join-append */
|
||||
git_buf_sets(&buf, a);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
git_buf_join(&buf, sep, NULL, b);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal(expected, git_buf_cstr(&buf));
|
||||
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
static void
|
||||
check_joinbuf_n_2(
|
||||
const char *a,
|
||||
const char *b,
|
||||
const char *expected)
|
||||
{
|
||||
char sep = '/';
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
|
||||
git_buf_sets(&buf, a);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
|
||||
git_buf_join_n(&buf, sep, 1, b);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal(expected, git_buf_cstr(&buf));
|
||||
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
static void
|
||||
check_joinbuf_n_4(
|
||||
const char *a,
|
||||
const char *b,
|
||||
const char *c,
|
||||
const char *d,
|
||||
const char *expected)
|
||||
{
|
||||
char sep = ';';
|
||||
git_buf buf = GIT_BUF_INIT;
|
||||
git_buf_join_n(&buf, sep, 4, a, b, c, d);
|
||||
cl_assert(git_buf_oom(&buf) == 0);
|
||||
cl_assert_strequal(expected, git_buf_cstr(&buf));
|
||||
git_buf_free(&buf);
|
||||
}
|
||||
|
||||
/* test join */
|
||||
void test_core_buffer__8(void)
|
||||
{
|
||||
git_buf a = GIT_BUF_INIT;
|
||||
|
||||
git_buf_join_n(&a, '/', 1, "foo");
|
||||
cl_assert(git_buf_oom(&a) == 0);
|
||||
cl_assert_strequal("foo", git_buf_cstr(&a));
|
||||
|
||||
git_buf_join_n(&a, '/', 1, "bar");
|
||||
cl_assert(git_buf_oom(&a) == 0);
|
||||
cl_assert_strequal("foo/bar", git_buf_cstr(&a));
|
||||
|
||||
git_buf_join_n(&a, '/', 1, "baz");
|
||||
cl_assert(git_buf_oom(&a) == 0);
|
||||
cl_assert_strequal("foo/bar/baz", git_buf_cstr(&a));
|
||||
|
||||
git_buf_free(&a);
|
||||
|
||||
check_joinbuf_2("", "", "");
|
||||
check_joinbuf_2("", "a", "a");
|
||||
check_joinbuf_2("", "/a", "/a");
|
||||
check_joinbuf_2("a", "", "a/");
|
||||
check_joinbuf_2("a", "/", "a/");
|
||||
check_joinbuf_2("a", "b", "a/b");
|
||||
check_joinbuf_2("/", "a", "/a");
|
||||
check_joinbuf_2("/", "", "/");
|
||||
check_joinbuf_2("/a", "/b", "/a/b");
|
||||
check_joinbuf_2("/a", "/b/", "/a/b/");
|
||||
check_joinbuf_2("/a/", "b/", "/a/b/");
|
||||
check_joinbuf_2("/a/", "/b/", "/a/b/");
|
||||
check_joinbuf_2("/a/", "//b/", "/a/b/");
|
||||
check_joinbuf_2("/abcd", "/defg", "/abcd/defg");
|
||||
check_joinbuf_2("/abcd", "/defg/", "/abcd/defg/");
|
||||
check_joinbuf_2("/abcd/", "defg/", "/abcd/defg/");
|
||||
check_joinbuf_2("/abcd/", "/defg/", "/abcd/defg/");
|
||||
|
||||
check_joinbuf_n_2("", "", "");
|
||||
check_joinbuf_n_2("", "a", "a");
|
||||
check_joinbuf_n_2("", "/a", "/a");
|
||||
check_joinbuf_n_2("a", "", "a/");
|
||||
check_joinbuf_n_2("a", "/", "a/");
|
||||
check_joinbuf_n_2("a", "b", "a/b");
|
||||
check_joinbuf_n_2("/", "a", "/a");
|
||||
check_joinbuf_n_2("/", "", "/");
|
||||
check_joinbuf_n_2("/a", "/b", "/a/b");
|
||||
check_joinbuf_n_2("/a", "/b/", "/a/b/");
|
||||
check_joinbuf_n_2("/a/", "b/", "/a/b/");
|
||||
check_joinbuf_n_2("/a/", "/b/", "/a/b/");
|
||||
check_joinbuf_n_2("/abcd", "/defg", "/abcd/defg");
|
||||
check_joinbuf_n_2("/abcd", "/defg/", "/abcd/defg/");
|
||||
check_joinbuf_n_2("/abcd/", "defg/", "/abcd/defg/");
|
||||
check_joinbuf_n_2("/abcd/", "/defg/", "/abcd/defg/");
|
||||
|
||||
check_joinbuf_n_4("", "", "", "", "");
|
||||
check_joinbuf_n_4("", "a", "", "", "a;");
|
||||
check_joinbuf_n_4("a", "", "", "", "a;");
|
||||
check_joinbuf_n_4("", "", "", "a", "a");
|
||||
check_joinbuf_n_4("a", "b", "", ";c;d;", "a;b;c;d;");
|
||||
check_joinbuf_n_4("a", "b", "", ";c;d", "a;b;c;d");
|
||||
check_joinbuf_n_4("abcd", "efgh", "ijkl", "mnop", "abcd;efgh;ijkl;mnop");
|
||||
check_joinbuf_n_4("abcd;", "efgh;", "ijkl;", "mnop;", "abcd;efgh;ijkl;mnop;");
|
||||
check_joinbuf_n_4(";abcd;", ";efgh;", ";ijkl;", ";mnop;", ";abcd;efgh;ijkl;mnop;");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user