From 032d0980dfe5a27a5954f44f9d519e03fc7d1ced Mon Sep 17 00:00:00 2001 From: Sumit Bose Date: Nov 14 2012 09:42:34 +0000 Subject: Add string_in_list() and add_string_to_list() with tests string_in_list() and add_string_to_list() are two utilities for NULL terminated strings arrays. add_string_to_list() adds a new string to an existing list or creates a new one with the strings as only item if there is not list. string_in_list() checks if a given string is in the list. It can be used case sensitive or in-sensitive. --- diff --git a/src/tests/util-tests.c b/src/tests/util-tests.c index 80c03c7..ff809a5 100644 --- a/src/tests/util-tests.c +++ b/src/tests/util-tests.c @@ -37,6 +37,84 @@ char *filename; int atio_fd; +START_TEST(test_add_string_to_list) +{ + int ret; + + char **list = NULL; + + ret = add_string_to_list(NULL, NULL, NULL); + fail_unless(ret == EINVAL, "NULL input accepted"); + + ret = add_string_to_list(global_talloc_context, "ABC", &list); + fail_unless(ret == EOK, "Adding string to non-existing list failed."); + fail_unless(list != NULL, "No new list created."); + fail_unless(list[0] != NULL, "String not added to new list."); + fail_unless(strcmp(list[0], "ABC") == 0, + "Wrong string added to newly created list."); + fail_unless(list[1] == NULL, + "Missing terminating NULL in newly created list."); + + ret = add_string_to_list(global_talloc_context, "DEF", &list); + fail_unless(ret == EOK, "Adding string to list failed."); + fail_unless(list != NULL, "No list returned."); + fail_unless(strcmp(list[0], "ABC") == 0, "Wrong first string in new list."); + fail_unless(strcmp(list[1], "DEF") == 0, "Wrong string added to list."); + fail_unless(list[2] == NULL, "Missing terminating NULL."); + + list[0] = NULL; + ret = add_string_to_list(global_talloc_context, "ABC", &list); + fail_unless(ret == EOK, "Adding string to empty list failed."); + fail_unless(list != NULL, "No list returned."); + fail_unless(list[0] != NULL, "String not added to empty list."); + fail_unless(strcmp(list[0], "ABC") == 0, + "Wrong string added to empty list."); + fail_unless(list[1] == NULL, + "Missing terminating NULL in newly created list."); + + talloc_free(list); +} +END_TEST + +START_TEST(test_string_in_list) +{ + bool is_in; + char *empty_list[] = {NULL}; + char *list[] = {discard_const("ABC"), + discard_const("DEF"), + discard_const("GHI"), + NULL}; + + is_in = string_in_list(NULL, NULL, false); + fail_unless(!is_in, "NULL string is in NULL list."); + + is_in = string_in_list(NULL, empty_list, false); + fail_unless(!is_in, "NULL string is in empty list."); + + is_in = string_in_list(NULL, list, false); + fail_unless(!is_in, "NULL string is in list."); + + is_in = string_in_list("ABC", NULL, false); + fail_unless(!is_in, "String is in NULL list."); + + is_in = string_in_list("ABC", empty_list, false); + fail_unless(!is_in, "String is in empty list."); + + is_in = string_in_list("ABC", list, false); + fail_unless(is_in, "String is not list."); + + is_in = string_in_list("abc", list, false); + fail_unless(is_in, "String is not case in-sensitive list."); + + is_in = string_in_list("abc", list, true); + fail_unless(!is_in, "Wrong string found in case sensitive list."); + + is_in = string_in_list("123", list, false); + fail_unless(!is_in, "Wrong string found in list."); + +} +END_TEST + START_TEST(test_parse_args) { struct pa_testcase { @@ -646,10 +724,15 @@ Suite *util_suite(void) TCase *tc_util = tcase_create("util"); + tcase_add_checked_fixture(tc_util, + leak_check_setup, + leak_check_teardown); tcase_add_test (tc_util, test_diff_string_lists); tcase_add_test (tc_util, test_sss_filter_sanitize); tcase_add_test (tc_util, test_size_t_overflow); tcase_add_test (tc_util, test_parse_args); + tcase_add_test (tc_util, test_add_string_to_list); + tcase_add_test (tc_util, test_string_in_list); tcase_set_timeout(tc_util, 60); TCase *tc_utf8 = tcase_create("utf8"); diff --git a/src/util/util.c b/src/util/util.c index b812ef1..18df0e8 100644 --- a/src/util/util.c +++ b/src/util/util.c @@ -634,3 +634,66 @@ remove_ipv6_brackets(char *ipv6addr) return EOK; } + +errno_t add_string_to_list(TALLOC_CTX *mem_ctx, const char *string, + char ***list_p) +{ + size_t c; + char **old_list = NULL; + char **new_list = NULL; + + if (string == NULL || list_p == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("Missing string or list.\n")); + return EINVAL; + } + + old_list = *list_p; + + if (old_list == NULL) { + /* If the input is a NULL list a new one is created with the new + * string and the terminating NULL element. */ + c = 0; + new_list = talloc_array(mem_ctx, char *, 2); + } else { + for (c = 0; old_list[c] != NULL; c++); + new_list = talloc_realloc(mem_ctx, old_list, char *, c + 1); + } + + if (new_list == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("talloc_array/talloc_realloc failed.\n")); + return ENOMEM; + } + + new_list[c] = talloc_strdup(new_list, string); + if (new_list[c] == NULL) { + DEBUG(SSSDBG_OP_FAILURE, ("talloc_strdup failed.\n")); + talloc_free(new_list); + return ENOMEM; + } + + new_list[c + 1] = NULL; + + *list_p = new_list; + + return EOK; +} + +bool string_in_list(const char *string, char **list, bool case_sensitive) +{ + size_t c; + int(*compare)(const char *s1, const char *s2); + + if (string == NULL || list == NULL || *list == NULL) { + return false; + } + + compare = case_sensitive ? strcmp : strcasecmp; + + for (c = 0; list[c] != NULL; c++) { + if (compare(string, list[c]) == 0) { + return true; + } + } + + return false; +} diff --git a/src/util/util.h b/src/util/util.h index b6ecfc2..56e7e0b 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -535,6 +535,12 @@ sss_escape_ip_address(TALLOC_CTX *mem_ctx, int family, const char *addr); errno_t remove_ipv6_brackets(char *ipv6addr); + +errno_t add_string_to_list(TALLOC_CTX *mem_ctx, const char *string, + char ***list_p); + +bool string_in_list(const char *string, char **list, bool case_sensitive); + /* from sss_tc_utf8.c */ char * sss_tc_utf8_str_tolower(TALLOC_CTX *mem_ctx, const char *s);