From: Tobias Brunner Date: Thu, 16 Feb 2023 16:04:40 +0000 (+0100) Subject: enum: Add functions to add and remove mappings from enum names X-Git-Tag: android-2.4.1~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=0de42047a98f831e8963cc352265db6a78bccc1b;p=thirdparty%2Fstrongswan.git enum: Add functions to add and remove mappings from enum names Co-authored-by: Thomas Egerer --- diff --git a/src/libstrongswan/tests/suites/test_enum.c b/src/libstrongswan/tests/suites/test_enum.c index c2329bdba4..fdb37a8d14 100644 --- a/src/libstrongswan/tests/suites/test_enum.c +++ b/src/libstrongswan/tests/suites/test_enum.c @@ -85,6 +85,13 @@ ENUM_FLAGS(test_enum_flags_overflow_names, FLAG1, FLAG12, "(unset)", "OVERFLOWFLAGLONGNAME7", "OVERFLOWFLAGLONGNAME8", "OVERFLOWFLAGLONGNAME9", "OVERFLOWFLAGLONGNAME10", "OVERFLOWFLAGLONGNAME11", "OVERFLOWFLAGLONGNAME12"); +/******************************************************************************* + * add_enum_names + */ + +ENUM_EXT(e1, 65000, 65001, "CONT65000", "CONT65001"); +ENUM_EXT(e2, 62000, 62001, "CONT62000", "CONT62001"); + /******************************************************************************* * enum_to_name */ @@ -172,6 +179,15 @@ static struct { {FALSE, 0, "asdf"}, {FALSE, 0, ""}, {FALSE, 0, NULL}, +}, enum_tests_ext[] = { + {TRUE, CONT1, "CONT1"}, + {TRUE, 62000, "CONT62000"}, + {TRUE, 62001, "CONT62001"}, + {TRUE, 65000, "CONT65000"}, + {TRUE, 65001, "CONT65001"}, + {FALSE, 0, "CONT64000"}, + {FALSE, 0, ""}, + {FALSE, 0, NULL}, }; START_TEST(test_enum_from_name_cont) @@ -196,6 +212,23 @@ START_TEST(test_enum_from_name_split) } END_TEST +START_TEST(test_enum_from_name_ext) +{ + int val = 0; + bool found; + + enum_add_enum_names(test_enum_cont_names, e1); + enum_add_enum_names(test_enum_cont_names, e2); + + found = enum_from_name(test_enum_cont_names, enum_tests_ext[_i].str, &val); + ck_assert(enum_tests_ext[_i].found == found); + ck_assert_int_eq(val, enum_tests_ext[_i].val); + + enum_remove_enum_names(test_enum_cont_names, e1); + enum_remove_enum_names(test_enum_cont_names, e2); +} +END_TEST + /******************************************************************************* * enum_printf_hook */ @@ -441,6 +474,51 @@ START_TEST(test_enum_printf_hook_width) } END_TEST +START_TEST(test_enum_printf_hook_add_enum_names) +{ + char buf[128]; + + enum_add_enum_names(test_enum_cont_names, e1); + snprintf(buf, sizeof(buf), "%N", test_enum_cont_names, 65001); + ck_assert_str_eq("CONT65001", buf); + + enum_add_enum_names(test_enum_cont_names, e2); + snprintf(buf, sizeof(buf), "%N", test_enum_cont_names, 62001); + ck_assert_str_eq("CONT62001", buf); + + /* adding the same list repeatedly should not result in an infinite loop */ + enum_add_enum_names(test_enum_cont_names, e2); + snprintf(buf, sizeof(buf), "%N", test_enum_cont_names, 62001); + ck_assert_str_eq("CONT62001", buf); + + /* can also be defined inside a function as long as the same function is + * adding and removing it */ + ENUM_EXT(e3, 64000, 64001, "CONT64000", "CONT64001"); + enum_add_enum_names(test_enum_cont_names, e3); + snprintf(buf, sizeof(buf), "%N", test_enum_cont_names, 64000); + ck_assert_str_eq("CONT64000", buf); + + snprintf(buf, sizeof(buf), "%N, %N, %N", test_enum_cont_names, 62001, + test_enum_cont_names, 65000, test_enum_cont_names, 64000); + ck_assert_str_eq("CONT62001, CONT65000, CONT64000", buf); + + enum_remove_enum_names(test_enum_cont_names, e2); + snprintf(buf, sizeof(buf), "%N, %N, %N", test_enum_cont_names, 62001, + test_enum_cont_names, 65000, test_enum_cont_names, 64000); + ck_assert_str_eq("(62001), CONT65000, CONT64000", buf); + + enum_remove_enum_names(test_enum_cont_names, e3); + snprintf(buf, sizeof(buf), "%N, %N, %N", test_enum_cont_names, 62001, + test_enum_cont_names, 65000, test_enum_cont_names, 64000); + ck_assert_str_eq("(62001), CONT65000, (64000)", buf); + + enum_remove_enum_names(test_enum_cont_names, e1); + snprintf(buf, sizeof(buf), "%N, %N, %N", test_enum_cont_names, 62001, + test_enum_cont_names, 65000, test_enum_cont_names, 64000); + ck_assert_str_eq("(62001), (65000), (64000)", buf); +} +END_TEST + Suite *enum_suite_create() { Suite *s; @@ -456,6 +534,7 @@ Suite *enum_suite_create() tc = tcase_create("enum_from_name"); tcase_add_loop_test(tc, test_enum_from_name_cont, 0, countof(enum_tests_cont)); tcase_add_loop_test(tc, test_enum_from_name_split, 0, countof(enum_tests_split)); + tcase_add_loop_test(tc, test_enum_from_name_ext, 0, countof(enum_tests_ext)); suite_add_tcase(s, tc); tc = tcase_create("enum_flags_to_string"); @@ -478,6 +557,7 @@ Suite *enum_suite_create() tcase_add_loop_test(tc, test_enum_printf_hook_flags_overflow, 0, countof(printf_tests_flags_overflow)); tcase_add_loop_test(tc, test_enum_printf_hook_flags_noflagenum, 0, countof(printf_tests_flags_noflagenum)); tcase_add_test(tc, test_enum_printf_hook_width); + tcase_add_test(tc, test_enum_printf_hook_add_enum_names); suite_add_tcase(s, tc); return s; diff --git a/src/libstrongswan/utils/enum.c b/src/libstrongswan/utils/enum.c index 4f93e8c6d2..b6f65f2e8f 100644 --- a/src/libstrongswan/utils/enum.c +++ b/src/libstrongswan/utils/enum.c @@ -1,4 +1,5 @@ /* + * Copyright (C) 2023 Tobias Brunner * Copyright (C) 2006 Martin Willi * * Copyright (C) secunet Security Networks AG @@ -23,6 +24,49 @@ #include "enum.h" +/* + * Described in header + */ +void enum_add_enum_names(enum_name_t *e, enum_name_t *names) +{ + if (e) + { + do + { + if (!e->next) + { + e->next = names; + break; + } + else if (e->next == names) + { + break; + } + } + while ((e = e->next)); + } +} + +/* + * Described in header + */ +void enum_remove_enum_names(enum_name_t *e, enum_name_t *names) +{ + if (e) + { + do + { + if (e->next == names) + { + e->next = names->next; + names->next = NULL; + break; + } + } + while ((e = e->next)); + } +} + /** * See header. */ diff --git a/src/libstrongswan/utils/enum.h b/src/libstrongswan/utils/enum.h index 45649224ea..5b3957b268 100644 --- a/src/libstrongswan/utils/enum.h +++ b/src/libstrongswan/utils/enum.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2019 Tobias Brunner + * Copyright (C) 2009-2023 Tobias Brunner * Copyright (C) 2006-2008 Martin Willi * * Copyright (C) secunet Security Networks AG @@ -140,6 +140,41 @@ struct enum_name_t { countof(((char*[]){__VA_ARGS__}))), \ ENUM_FLAG_MAGIC, { unset, __VA_ARGS__ }}; ENUM_END(name, last) +/** + * Define a static enum name that can be added and removed to an existing list + * via enum_add_enum_names() and enum_remove_enum_names(), respectively. + * + * @param name name of the static enum_name element + * @param first enum value of the first enum string + * @param last enum value of the last enum string + * @param ... a list of strings + */ +#define ENUM_EXT(name, first, last, ...) \ + ENUM_BEGIN(name, first, last, __VA_ARGS__); static ENUM_END(name, last) + +/** + * Register enum names for additional enum values with an existing enum name. + * + * @note Must be called while running single-threaded, e.g. when plugins and + * their features are loaded. Use enum_remove_enum_names() to remove the names + * during deinitialization. + * + * @param e enum names to add new names to + * @param names additional enum names + */ +void enum_add_enum_names(enum_name_t *e, enum_name_t *names); + +/** + * Remove previously registered enum names. + * + * @note Must be called while running single-threaded, e.g. when plugins and + * their features are unloaded. + * + * @param e enum names to remove previously added names from + * @param names additional enum names to remove + */ +void enum_remove_enum_names(enum_name_t *e, enum_name_t *names); + /** * Convert a enum value to its string representation. *