"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
*/
{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)
}
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
*/
}
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;
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");
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;
/*
- * Copyright (C) 2009-2019 Tobias Brunner
+ * Copyright (C) 2009-2023 Tobias Brunner
* Copyright (C) 2006-2008 Martin Willi
*
* Copyright (C) secunet Security Networks AG
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.
*