diff options
author | Lars Wirzenius <liw@liw.fi> | 2010-10-22 14:34:03 +0100 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2010-10-22 14:34:03 +0100 |
commit | 2a9a7e36ac4f1851eaeb893f61b1919d706096d5 (patch) | |
tree | 91d58b26f991d26394253772a68008ddee4c7b55 | |
parent | 8dda24d8c82332f03cd280d8a8df5f16c48ad63c (diff) | |
download | dynstr-2a9a7e36ac4f1851eaeb893f61b1919d706096d5.tar.gz |
Implement dynstr_cat.
-rw-r--r-- | dynstr.c | 37 | ||||
-rw-r--r-- | dynstr.h | 1 | ||||
-rw-r--r-- | unittests.c | 52 |
3 files changed, 89 insertions, 1 deletions
@@ -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; +} @@ -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]); |