summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2010-10-22 14:34:03 +0100
committerLars Wirzenius <liw@liw.fi>2010-10-22 14:34:03 +0100
commit2a9a7e36ac4f1851eaeb893f61b1919d706096d5 (patch)
tree91d58b26f991d26394253772a68008ddee4c7b55
parent8dda24d8c82332f03cd280d8a8df5f16c48ad63c (diff)
downloaddynstr-2a9a7e36ac4f1851eaeb893f61b1919d706096d5.tar.gz
Implement dynstr_cat.
-rw-r--r--dynstr.c37
-rw-r--r--dynstr.h1
-rw-r--r--unittests.c52
3 files changed, 89 insertions, 1 deletions
diff --git a/dynstr.c b/dynstr.c
index 1d15a1c..8110665 100644
--- a/dynstr.c
+++ b/dynstr.c
@@ -152,4 +152,41 @@ Dynstr *dynstr_substr(Dynstr *dynstr, size_t offset, size_t size)
return new(dynstr->mem + offset, size, true);
}
+Dynstr *dynstr_cat(Dynstr *dynstr, ...)
+{
+ va_list args;
+ Dynstr *result;
+ size_t size;
+ void *mem;
+ size_t offset;
+
+ va_start(args, dynstr);
+ size = 0;
+ for (Dynstr *p = dynstr; p != NULL; p = va_arg(args, Dynstr *))
+ size += p->size;
+ va_end(args);
+
+ mem = alloc(size);
+ if (mem == NULL)
+ return NULL;
+
+ va_start(args, dynstr);
+ offset = 0;
+ for (Dynstr *p = dynstr; p != NULL; p = va_arg(args, Dynstr *)) {
+ memcpy(mem + offset, p->mem, p->size);
+ offset += p->size;
+ }
+ va_end(args);
+
+ result = dynstr_new_empty();
+ if (result == NULL) {
+ free(mem);
+ return NULL;
+ }
+ result->size = size;
+ result->mem = mem;
+ result->dynamic = true;
+
+ return result;
+}
diff --git a/dynstr.h b/dynstr.h
index 0dbf13e..f7ff523 100644
--- a/dynstr.h
+++ b/dynstr.h
@@ -107,7 +107,6 @@ Dynstr *dynstr_substr(Dynstr *dynstr, size_t offset, size_t size);
* argument list has zero or more pointers to dynamic strings, and
* then a NULL pointer. */
Dynstr *dynstr_cat(Dynstr *dynstr, ...);
-Dynstr *dynstr_vcat(Dynstr *, va_list);
/* Return value of byte at a given offset. The value is non-negative. If
* the offset is past the end of the string, -1 is returned. */
diff --git a/unittests.c b/unittests.c
index a17686c..d9be8b8 100644
--- a/unittests.c
+++ b/unittests.c
@@ -435,6 +435,55 @@ static int test_copies_partial_substring_when_length_too_big(void)
}
+static int test_cats_ok(void)
+{
+ Dynstr *a;
+ Dynstr *b;
+ Dynstr *c;
+ char buf[1024];
+ size_t size;
+
+ a = dynstr_new_from_cstring("abc");
+ b = dynstr_new_from_cstring("def");
+ c = dynstr_cat(a, b, NULL);
+ size = dynstr_memcpy(buf, c, 0, dynstr_len(c));
+ FAIL_UNLESS_EQUAL(size, 6);
+ FAIL_UNLESS_EQUAL(memcmp(buf, "abcdef", 6), 0);
+ return true;
+}
+
+
+static int test_cat_returns_NULL_for_first_malloc_failure(void)
+{
+ Dynstr *a;
+ Dynstr *b;
+ Dynstr *c;
+
+ a = dynstr_new_from_cstring("abc");
+ b = dynstr_new_from_cstring("def");
+ dynstr_set_malloc(fail_malloc);
+ c = dynstr_cat(a, b, NULL);
+ FAIL_UNLESS_EQUAL(c, NULL);
+ return true;
+}
+
+
+static int test_cat_returns_NULL_for_second_malloc_failure(void)
+{
+ Dynstr *a;
+ Dynstr *b;
+ Dynstr *c;
+
+ a = dynstr_new_from_cstring("abc");
+ b = dynstr_new_from_cstring("def");
+ dynstr_set_malloc(fail_malloc);
+ fail_malloc_after = 1;
+ c = dynstr_cat(a, b, NULL);
+ FAIL_UNLESS_EQUAL(c, NULL);
+ return true;
+}
+
+
static void setup(void)
{
dynstr_init();
@@ -484,6 +533,9 @@ static const struct test tests[] = {
TEST(test_copies_final_substring_ok),
TEST(test_copies_empty_substring_when_offset_too_big),
TEST(test_copies_partial_substring_when_length_too_big),
+ TEST(test_cats_ok),
+ TEST(test_cat_returns_NULL_for_first_malloc_failure),
+ TEST(test_cat_returns_NULL_for_second_malloc_failure),
};
static const int num_tests = sizeof(tests) / sizeof(tests[0]);