/*******************************************************************************
* continuous enum
*/
-enum {
+enum test_enum_cont {
CONT1,
CONT2,
CONT3,
CONT4,
CONT5,
-} test_enum_cont;
+};
ENUM_BEGIN(test_enum_cont_names, CONT1, CONT5,
"CONT1", "CONT2", "CONT3", "CONT4", "CONT5");
/*******************************************************************************
* split enum
*/
-enum {
+enum test_enum_split {
SPLIT1 = 1,
SPLIT2,
SPLIT3 = 5,
SPLIT4,
SPLIT5 = 255,
-} test_enum_split;
+};
ENUM_BEGIN(test_enum_split_names, SPLIT1, SPLIT2,
"SPLIT1", "SPLIT2");
/*******************************************************************************
* enum flags
*/
-enum {
+enum test_enum_flags {
FLAG1 = (1 << 0),
FLAG2 = (1 << 1),
FLAG3 = (1 << 2),
FLAG10 = (1 << 9),
FLAG11 = (1 << 10),
FLAG12 = (1 << 11),
-} test_enum_flags;
+};
ENUM_FLAGS(test_enum_flags_names, FLAG1, FLAG5,
"(unset)", "FLAG1", "FLAG2", "FLAG3", "FLAG4", "FLAG5");
}, enum_flags_to_string_tests[] = {
{-1, NULL},
{6435, NULL},
+}, enum_flags_from_string_tests[] = {
+ {0, NULL},
+ {0, ""},
+ {0, "(unset)"},
+ {FLAG1, "FLAG1"},
+ {FLAG2, "flag2"},
+ {FLAG3, "fLaG3"},
+ {FLAG4, "FLAG4"},
+ {FLAG5, "FLAG5"},
+ {FLAG1 | FLAG3, "FLAG1 | FLAG3"},
+ {FLAG1 | FLAG3, "flag3|flag1"},
+ {FLAG1 | FLAG3, "flag1|flag3 | (unset)"},
+ {FLAG1 | FLAG2 | FLAG3 | FLAG4 | FLAG5, "flag1|flag2|flag3|flag4|flag5"},
+ {FLAG1 | FLAG2 | FLAG3 | FLAG4 | FLAG5, "flag3|flag4|flag5|flag2|flag1"},
+ {FLAG5, "(unset)|flag5"},
+ {FLAG1, "FLAG1 | flag1 | flAg1"},
+ {-1, "FLAG6"},
+ {-1, "flag1 | asdf"},
+}, enum_flags_from_string_noflagenum_tests[] = {
+ {0, NULL},
+ {0, ""},
+ {CONT2, "CONT2"},
+ {CONT5, "CONT5"},
+ {-1, "asdf"},
};
START_TEST(test_enum_printf_hook_cont)
}
END_TEST
+START_TEST(test_enum_flags_from_string)
+{
+ enum test_enum_flags val;
+
+ if (enum_flags_from_string(test_enum_flags_names,
+ enum_flags_from_string_tests[_i].str, &val))
+ {
+ ck_assert_int_eq(enum_flags_from_string_tests[_i].val, val);
+ }
+ else
+ {
+ ck_assert_int_eq(enum_flags_from_string_tests[_i].val, -1);
+ }
+}
+END_TEST
+
+START_TEST(test_enum_flags_from_string_noflagenum)
+{
+ enum test_enum_cont val;
+
+ if (enum_flags_from_string(test_enum_cont_names,
+ enum_flags_from_string_noflagenum_tests[_i].str, &val))
+ {
+ ck_assert_int_eq(enum_flags_from_string_noflagenum_tests[_i].val, val);
+ }
+ else
+ {
+ ck_assert_int_eq(enum_flags_from_string_noflagenum_tests[_i].val, -1);
+ }
+}
+END_TEST
+
START_TEST(test_enum_printf_hook_width)
{
char buf[128];
tcase_add_loop_test(tc, test_enum_flags_to_string_noflagenum, 0, countof(printf_tests_flags_noflagenum));
suite_add_tcase(s, tc);
+ tc = tcase_create("enum_flags_from_string");
+ tcase_add_loop_test(tc, test_enum_flags_from_string, 0, countof(enum_flags_from_string_tests));
+ tcase_add_loop_test(tc, test_enum_flags_from_string_noflagenum, 0, countof(enum_flags_from_string_noflagenum_tests));
+ suite_add_tcase(s, tc);
+
tc = tcase_create("enum_printf_hook");
tcase_add_loop_test(tc, test_enum_printf_hook_cont, 0, countof(printf_tests_cont));
tcase_add_loop_test(tc, test_enum_printf_hook_split, 0, countof(printf_tests_split));
#include <stdio.h>
#include <library.h>
+#include <collections/enumerator.h>
#include <utils/utils.h>
#include "enum.h"
return buf;
}
+/*
+ * Described in header
+ */
+bool enum_flags_from_string_as_int(enum_name_t *e, const char *str, u_int *val)
+{
+ enumerator_t *enumerator;
+ char *name;
+
+ *val = 0;
+
+ if (!str || !*str)
+ {
+ return TRUE;
+ }
+ else if (e->next != ENUM_FLAG_MAGIC)
+ {
+ return enum_from_name_as_int(e, str, val);
+ }
+
+ enumerator = enumerator_create_token(str, "|", " ");
+ while (enumerator->enumerate(enumerator, &name))
+ {
+ u_int flag, i;
+ bool found = FALSE;
+
+ if (strcaseeq(name, e->names[0]))
+ { /* accept name used if no flags are set */
+ continue;
+ }
+ for (i = 1, flag = e->first; flag <= e->last; i++, flag <<= 1)
+ {
+ if (e->names[i] && strcaseeq(name, e->names[i]))
+ {
+ *val |= flag;
+ found = TRUE;
+ break;
+ }
+ }
+ if (!found)
+ {
+ enumerator->destroy(enumerator);
+ return FALSE;
+ }
+ }
+ enumerator->destroy(enumerator);
+ return TRUE;
+}
+
/**
* See header.
*/
*/
#define enum_from_name(e, name, valp) ({ \
int _val; \
- int _found = enum_from_name_as_int(e, name, &_val); \
+ bool _found = enum_from_name_as_int(e, name, &_val); \
if (_found) \
{ \
*(valp) = _val; \
/**
* Convert a enum string back to its enum value, integer pointer variant.
*
- * This variant takes integer pointer only, use enum_from_name() to pass
+ * This variant takes an integer pointer, use enum_from_name() to pass
* enum type pointers for the result.
*
* @param e enum names for this enum value
* @param name name to get enum value for
* @param val integer pointer receiving value
- * @return TRUE if enum name found, FALSE otherwise
+ * @return TRUE if all names found, FALSE otherwise
*/
bool enum_from_name_as_int(enum_name_t *e, const char *name, int *val);
*/
char *enum_flags_to_string(enum_name_t *e, u_int val, char *buf, size_t len);
+/**
+ * Convert a string of flags separated by | to their combined value
+ *
+ * @param e enum names for this enum value
+ * @param str string to get enum value for
+ * @param valp variable sized pointer receiving value
+ * @return TRUE if all names found, FALSE otherwise
+ */
+#define enum_flags_from_string(e, str, valp) ({ \
+ u_int _val; \
+ bool _found = enum_flags_from_string_as_int(e, str, &_val); \
+ if (_found) \
+ { \
+ *(valp) = _val; \
+ } \
+ _found; })
+
+/**
+ * Convert a string of flags separated by | to their combined value.
+ *
+ * This variant takes an unsigned integer pointer, use enum_flags_from_names()
+ * to pass enum type pointers for the result.
+ *
+ * @param e enum names for this enum value
+ * @param str string to get enum value for
+ * @param val integer pointer receiving value
+ * @return TRUE if enum name found, FALSE otherwise
+ */
+bool enum_flags_from_string_as_int(enum_name_t *e, const char *str, u_int *val);
+
/**
* printf hook function for enum_names_t.
*