Commit 798dd36c by Vicent Martí

Merge pull request #499 from arrbee/extend-git-buf

Extend git_buf with new utility functions and unit tests.
parents 89886d0b 679b69c4
......@@ -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;
}
......@@ -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
#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;");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment