From dfe219b64913c7b49d0e319aaf9c2e6c702b266d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nils=20O=2E=20Sel=C3=A5sdal?= Date: Tue, 4 Feb 2014 01:37:27 +0100 Subject: [PATCH] Add an unsigned int/string pair type, modelled on the value string of wireshark --- include/ucore/val_str.h | 37 +++++++++++++++++++++ src/val_str.c | 47 +++++++++++++++++++++++++++ test/test_runner.c | 4 ++- test/test_val_str.c | 72 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 159 insertions(+), 1 deletion(-) create mode 100644 include/ucore/val_str.h create mode 100644 src/val_str.c create mode 100644 test/test_val_str.c diff --git a/include/ucore/val_str.h b/include/ucore/val_str.h new file mode 100644 index 0000000..834f7cb --- /dev/null +++ b/include/ucore/val_str.h @@ -0,0 +1,37 @@ +#ifndef UC_VAL_STR_H_ +#define UC_VAL_STR_H_ + +#include + +struct UCValStr { + unsigned int val; + const char *str; +}; + +#define UC_VS_ENTRY(constant) {constant, #constant} +#define UC_VS_TERMINATOR {-1, NULL} + +/** Find @val in @array. + * The last .str in @array must be a NULL pointer. + * (does a linear search) + * + * @param val value to find + * @param array array to search + * @return the string associated with @val or NULL + */ +const char *uc_vs_search(unsigned int val, const struct UCValStr *array); + +/** Find @val in @array. + * @array must be sorted on val and must not be empty + * (does a binary search) + * + * @param val value to find + * @param array array to search + * @return the string associated with @val or NULL + */ +const char *uc_vs_bsearch(unsigned int val, + const struct UCValStr *array, + size_t array_len); + + +#endif diff --git a/src/val_str.c b/src/val_str.c new file mode 100644 index 0000000..40e0cd7 --- /dev/null +++ b/src/val_str.c @@ -0,0 +1,47 @@ +#include +#include +#include "ucore/val_str.h" +#include "ucore/saturating_math.h" + + +const char *uc_vs_search(unsigned int val, const struct UCValStr *array) +{ + const char *found = NULL; + + while (array->str) { + if (array->val == val) { + found = array->str; + break; + } + array++; + } + + return found; +} + +const char *uc_vs_bsearch(unsigned int val, + const struct UCValStr *array, + size_t array_len) +{ + size_t i = array_len; + const struct UCValStr *start = array; + + while (i != 0) { + const struct UCValStr *curr; + curr = start + i / 2; + + if (curr->val == val) { + return curr->str; + } + + if (curr->val < val) { + start = curr + 1; + i--; + } + + i = i / 2; + } + + return NULL; +} + diff --git a/test/test_runner.c b/test/test_runner.c index 92c0eb0..fab9686 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -29,6 +29,7 @@ extern Suite *ratelimit_suite(void); extern Suite *htable_suite(void); extern Suite *heapsort_suite(void); extern Suite *dstr_suite(void); +extern Suite *val_str_suite(void); static suite_func suites[] = { bitvec_suite, @@ -52,7 +53,8 @@ static suite_func suites[] = { clock_suite, threadqueue_suite, heapsort_suite, - dstr_suite + dstr_suite, + val_str_suite }; int diff --git a/test/test_val_str.c b/test/test_val_str.c new file mode 100644 index 0000000..96006cf --- /dev/null +++ b/test/test_val_str.c @@ -0,0 +1,72 @@ +#include +#include + + +START_TEST (test_val_str_search) + struct UCValStr vals[] = { + UC_VS_ENTRY(1), + UC_VS_ENTRY(5), + UC_VS_ENTRY(0), + UC_VS_TERMINATOR + }; + ck_assert_str_eq(uc_vs_search(0 , vals) , "0"); + ck_assert_str_eq(uc_vs_search(1 , vals) , "1"); + ck_assert_str_eq(uc_vs_search(5 , vals) , "5"); + + fail_if(uc_vs_search(10, vals) != NULL); +END_TEST + +START_TEST (test_val_str_bsearch_odd) + struct UCValStr vals[] = { + UC_VS_ENTRY(1), + UC_VS_ENTRY(2), + UC_VS_ENTRY(10), + UC_VS_ENTRY(100), + UC_VS_ENTRY(101), + }; + const size_t len = sizeof vals/sizeof vals[0]; + + ck_assert_str_eq(uc_vs_bsearch(1 , vals , len) , "1"); + ck_assert_str_eq(uc_vs_bsearch(2 , vals , len) , "2"); + ck_assert_str_eq(uc_vs_bsearch(10 , vals , len) , "10"); + ck_assert_str_eq(uc_vs_bsearch(100 , vals , len) , "100"); + ck_assert_str_eq(uc_vs_bsearch(101 , vals , len) , "101"); + + fail_if(uc_vs_bsearch(0 , vals , len) != NULL); + fail_if(uc_vs_bsearch(55 , vals , len) != NULL); + fail_if(uc_vs_bsearch(999 , vals , len) != NULL); +END_TEST + +START_TEST (test_val_str_bsearch_even) + struct UCValStr vals[] = { + UC_VS_ENTRY(1), + UC_VS_ENTRY(2), + UC_VS_ENTRY(10), + UC_VS_ENTRY(101), + }; + const size_t len = sizeof vals/sizeof vals[0]; + + ck_assert_str_eq(uc_vs_bsearch(1 , vals , len) , "1"); + ck_assert_str_eq(uc_vs_bsearch(2 , vals , len) , "2"); + ck_assert_str_eq(uc_vs_bsearch(10 , vals , len) , "10"); + ck_assert_str_eq(uc_vs_bsearch(101 , vals , len) , "101"); + + fail_if(uc_vs_bsearch(0 , vals , len) != NULL); + fail_if(uc_vs_bsearch(55 , vals , len) != NULL); + fail_if(uc_vs_bsearch(999 , vals , len) != NULL); +END_TEST + + +Suite *val_str_suite(void) +{ + Suite *s = suite_create("valstr"); + TCase *tc = tcase_create("valstr tests"); + tcase_add_test(tc, test_val_str_search); + tcase_add_test(tc, test_val_str_bsearch_odd); + tcase_add_test(tc, test_val_str_bsearch_even); + + suite_add_tcase(s, tc); + + return s; +} +