diff options
| author | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2023-09-21 15:53:14 +0200 | 
|---|---|---|
| committer | David Oberhollenzer <david.oberhollenzer@sigma-star.at> | 2023-10-24 15:57:18 +0200 | 
| commit | 7f89eb3cfff465cf32d03a2ae6919252eae67e9b (patch) | |
| tree | ed776d71106000dfa34ad4de3402fff6fea6c56a /lib | |
| parent | c4ab32879df8b5e83b0ebd091ce2c750f53f5633 (diff) | |
libutil: add a string list helper to replace some of the adhoc ones
Signed-off-by: David Oberhollenzer <david.oberhollenzer@sigma-star.at>
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/util/Makemodule.am | 7 | ||||
| -rw-r--r-- | lib/util/src/strlist.c | 71 | ||||
| -rw-r--r-- | lib/util/test/strlist.c | 110 | 
3 files changed, 186 insertions, 2 deletions
| diff --git a/lib/util/Makemodule.am b/lib/util/Makemodule.am index 9b2065a..24fb50b 100644 --- a/lib/util/Makemodule.am +++ b/lib/util/Makemodule.am @@ -10,7 +10,7 @@ libutil_a_SOURCES = include/util/util.h include/util/str_table.h \  	lib/util/src/source_date_epoch.c lib/util/src/file_cmp.c \  	lib/util/src/hex_decode.c lib/util/src/base64_decode.c \  	lib/util/src/get_line.c lib/util/src/split_line.c \ -	lib/util/src/parse_int.c +	lib/util/src/parse_int.c lib/util/src/strlist.c include/util/strlist.h  libutil_a_CFLAGS = $(AM_CFLAGS)  libutil_a_CPPFLAGS = $(AM_CPPFLAGS) @@ -87,11 +87,14 @@ test_split_line_LDADD = libutil.a libcompat.a  test_parse_int_SOURCES = lib/util/test/parse_int.c  test_parse_int_LDADD = libutil.a libcompat.a +test_strlist_SOURCES = lib/util/test/strlist.c +test_strlist_LDADD = libutil.a libcompat.a +  LIBUTIL_TESTS = \  	test_str_table test_rbtree test_xxhash test_threadpool test_ismemzero \  	test_canonicalize_name test_filename_sane test_filename_sane_w32 \  	test_sdate_epoch test_hex_decode test_base64_decode test_get_line \ -	test_split_line test_parse_int +	test_split_line test_parse_int test_strlist  check_PROGRAMS += $(LIBUTIL_TESTS)  TESTS += $(LIBUTIL_TESTS) diff --git a/lib/util/src/strlist.c b/lib/util/src/strlist.c new file mode 100644 index 0000000..9d1fd78 --- /dev/null +++ b/lib/util/src/strlist.c @@ -0,0 +1,71 @@ +/* SPDX-License-Identifier: LGPL-3.0-or-later */ +/* + * strlist.c + * + * Copyright (C) 2023 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "util/strlist.h" +#include "util/util.h" +#include "compat.h" + +#include <stdlib.h> + +void strlist_cleanup(strlist_t *list) +{ +	for (size_t i = 0; i < list->count; ++i) +		free(list->strings[i]); + +	free(list->strings); +	memset(list, 0, sizeof(*list)); +} + +int strlist_init_copy(strlist_t *dst, const strlist_t *src) +{ +	memset(dst, 0, sizeof(*dst)); + +	dst->strings = alloc_array(sizeof(char *), src->capacity); +	if (dst->strings == NULL) +		return -1; + +	dst->count = src->count; +	dst->capacity = src->capacity; + +	for (size_t i = 0; i < src->count; ++i) { +		dst->strings[i] = strdup(src->strings[i]); + +		if (dst->strings[i] == NULL) { +			dst->count = i; +			strlist_cleanup(dst); +			return -1; +		} +	} + +	return 0; +} + +int strlist_append(strlist_t *list, const char *str) +{ +	if (list->count == list->capacity) { +		size_t new_cap = list->capacity ? (list->capacity * 2) : 128; +		size_t new_sz; +		char **new; + +		if (SZ_MUL_OV(new_cap, sizeof(char *), &new_sz)) +			return -1; + +		new = realloc(list->strings, new_sz); +		if (new == NULL) +			return -1; + +		list->capacity = new_cap; +		list->strings = new; +	} + +	list->strings[list->count] = strdup(str); +	if (list->strings[list->count] == NULL) +		return -1; + +	list->count += 1; +	return 0; +} diff --git a/lib/util/test/strlist.c b/lib/util/test/strlist.c new file mode 100644 index 0000000..23587b3 --- /dev/null +++ b/lib/util/test/strlist.c @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * strlist.c + * + * Copyright (C) 2023 David Oberhollenzer <goliath@infraroot.at> + */ +#include "config.h" +#include "util/util.h" +#include "util/test.h" +#include "util/strlist.h" + +int main(int argc, char **argv) +{ +	const char *str0, *str1, *str2; +	strlist_t a, b; +	int ret; +	(void)argc; (void)argv; + +	str0 = "foo"; +	str1 = "bar"; +	str2 = "baz"; + +	/* init */ +	strlist_init(&a); +	TEST_NULL(a.strings); +	TEST_EQUAL_UI(a.count, 0); +	TEST_EQUAL_UI(a.capacity, 0); + +	/* append a string */ +	ret = strlist_append(&a, str0); +	TEST_EQUAL_I(ret, 0); + +	TEST_EQUAL_UI(a.count, 1); +	TEST_ASSERT(a.capacity >= a.count); + +	TEST_NOT_NULL(a.strings); +	TEST_NOT_NULL(a.strings[0]); + +	TEST_STR_EQUAL(a.strings[0], str0); +	TEST_ASSERT(a.strings[0] != str0); + +	/* append another */ +	ret = strlist_append(&a, str1); +	TEST_EQUAL_I(ret, 0); + +	TEST_EQUAL_UI(a.count, 2); +	TEST_ASSERT(a.capacity >= a.count); + +	TEST_NOT_NULL(a.strings); +	TEST_NOT_NULL(a.strings[0]); +	TEST_NOT_NULL(a.strings[1]); + +	TEST_ASSERT(a.strings[0] != str0); +	TEST_ASSERT(a.strings[1] != str1); +	TEST_STR_EQUAL(a.strings[0], str0); +	TEST_STR_EQUAL(a.strings[1], str1); + +	/* and one more */ +	ret = strlist_append(&a, str2); +	TEST_EQUAL_I(ret, 0); + +	TEST_EQUAL_UI(a.count, 3); +	TEST_ASSERT(a.capacity >= a.count); + +	TEST_NOT_NULL(a.strings); +	TEST_NOT_NULL(a.strings[0]); +	TEST_NOT_NULL(a.strings[1]); +	TEST_NOT_NULL(a.strings[2]); + +	TEST_ASSERT(a.strings[0] != str0); +	TEST_ASSERT(a.strings[1] != str1); +	TEST_ASSERT(a.strings[2] != str2); +	TEST_STR_EQUAL(a.strings[0], str0); +	TEST_STR_EQUAL(a.strings[1], str1); +	TEST_STR_EQUAL(a.strings[2], str2); + +	/* copy */ +	strlist_init_copy(&b, &a); +	TEST_NOT_NULL(b.strings); +	TEST_EQUAL_UI(b.count, a.count); +	TEST_EQUAL_UI(b.capacity, a.capacity); + +	TEST_ASSERT(b.strings != a.strings); + +	TEST_NOT_NULL(b.strings[0]); +	TEST_NOT_NULL(b.strings[1]); +	TEST_NOT_NULL(b.strings[2]); + +	TEST_ASSERT(b.strings[0] != a.strings[0]); +	TEST_ASSERT(b.strings[1] != a.strings[1]); +	TEST_ASSERT(b.strings[2] != a.strings[2]); + +	TEST_STR_EQUAL(b.strings[0], str0); +	TEST_STR_EQUAL(b.strings[1], str1); +	TEST_STR_EQUAL(b.strings[2], str2); + +	/* cleanup */ +	strlist_cleanup(&a); +	strlist_cleanup(&b); + +	TEST_NULL(a.strings); +	TEST_NULL(b.strings); + +	TEST_EQUAL_UI(a.count, 0); +	TEST_EQUAL_UI(b.count, 0); + +	TEST_EQUAL_UI(a.capacity, 0); +	TEST_EQUAL_UI(b.capacity, 0); +	return EXIT_SUCCESS; +} | 
