enum: Add helper to parse enum flags from strings
Individual flag names are separated by |.
This commit is contained in:
@@ -20,13 +20,13 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* continuous enum
|
* continuous enum
|
||||||
*/
|
*/
|
||||||
enum {
|
enum test_enum_cont {
|
||||||
CONT1,
|
CONT1,
|
||||||
CONT2,
|
CONT2,
|
||||||
CONT3,
|
CONT3,
|
||||||
CONT4,
|
CONT4,
|
||||||
CONT5,
|
CONT5,
|
||||||
} test_enum_cont;
|
};
|
||||||
|
|
||||||
ENUM_BEGIN(test_enum_cont_names, CONT1, CONT5,
|
ENUM_BEGIN(test_enum_cont_names, CONT1, CONT5,
|
||||||
"CONT1", "CONT2", "CONT3", "CONT4", "CONT5");
|
"CONT1", "CONT2", "CONT3", "CONT4", "CONT5");
|
||||||
@@ -35,13 +35,13 @@ ENUM_END(test_enum_cont_names, CONT5);
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* split enum
|
* split enum
|
||||||
*/
|
*/
|
||||||
enum {
|
enum test_enum_split {
|
||||||
SPLIT1 = 1,
|
SPLIT1 = 1,
|
||||||
SPLIT2,
|
SPLIT2,
|
||||||
SPLIT3 = 5,
|
SPLIT3 = 5,
|
||||||
SPLIT4,
|
SPLIT4,
|
||||||
SPLIT5 = 255,
|
SPLIT5 = 255,
|
||||||
} test_enum_split;
|
};
|
||||||
|
|
||||||
ENUM_BEGIN(test_enum_split_names, SPLIT1, SPLIT2,
|
ENUM_BEGIN(test_enum_split_names, SPLIT1, SPLIT2,
|
||||||
"SPLIT1", "SPLIT2");
|
"SPLIT1", "SPLIT2");
|
||||||
@@ -54,7 +54,7 @@ ENUM_END(test_enum_split_names, SPLIT5);
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* enum flags
|
* enum flags
|
||||||
*/
|
*/
|
||||||
enum {
|
enum test_enum_flags {
|
||||||
FLAG1 = (1 << 0),
|
FLAG1 = (1 << 0),
|
||||||
FLAG2 = (1 << 1),
|
FLAG2 = (1 << 1),
|
||||||
FLAG3 = (1 << 2),
|
FLAG3 = (1 << 2),
|
||||||
@@ -67,7 +67,7 @@ enum {
|
|||||||
FLAG10 = (1 << 9),
|
FLAG10 = (1 << 9),
|
||||||
FLAG11 = (1 << 10),
|
FLAG11 = (1 << 10),
|
||||||
FLAG12 = (1 << 11),
|
FLAG12 = (1 << 11),
|
||||||
} test_enum_flags;
|
};
|
||||||
|
|
||||||
ENUM_FLAGS(test_enum_flags_names, FLAG1, FLAG5,
|
ENUM_FLAGS(test_enum_flags_names, FLAG1, FLAG5,
|
||||||
"(unset)", "FLAG1", "FLAG2", "FLAG3", "FLAG4", "FLAG5");
|
"(unset)", "FLAG1", "FLAG2", "FLAG3", "FLAG4", "FLAG5");
|
||||||
@@ -263,6 +263,30 @@ static struct {
|
|||||||
}, enum_flags_to_string_tests[] = {
|
}, enum_flags_to_string_tests[] = {
|
||||||
{-1, NULL},
|
{-1, NULL},
|
||||||
{6435, 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)
|
START_TEST(test_enum_printf_hook_cont)
|
||||||
@@ -371,6 +395,38 @@ START_TEST(test_enum_flags_to_string_noflagenum)
|
|||||||
}
|
}
|
||||||
END_TEST
|
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)
|
START_TEST(test_enum_printf_hook_width)
|
||||||
{
|
{
|
||||||
char buf[128];
|
char buf[128];
|
||||||
@@ -406,6 +462,11 @@ Suite *enum_suite_create()
|
|||||||
tcase_add_loop_test(tc, test_enum_flags_to_string_noflagenum, 0, countof(printf_tests_flags_noflagenum));
|
tcase_add_loop_test(tc, test_enum_flags_to_string_noflagenum, 0, countof(printf_tests_flags_noflagenum));
|
||||||
suite_add_tcase(s, tc);
|
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");
|
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_cont, 0, countof(printf_tests_cont));
|
||||||
tcase_add_loop_test(tc, test_enum_printf_hook_split, 0, countof(printf_tests_split));
|
tcase_add_loop_test(tc, test_enum_printf_hook_split, 0, countof(printf_tests_split));
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <library.h>
|
#include <library.h>
|
||||||
|
#include <collections/enumerator.h>
|
||||||
#include <utils/utils.h>
|
#include <utils/utils.h>
|
||||||
|
|
||||||
#include "enum.h"
|
#include "enum.h"
|
||||||
@@ -135,6 +136,54 @@ char *enum_flags_to_string(enum_name_t *e, u_int val, char *buf, size_t len)
|
|||||||
return buf;
|
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.
|
* See header.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ char *enum_to_name(enum_name_t *e, int val);
|
|||||||
*/
|
*/
|
||||||
#define enum_from_name(e, name, valp) ({ \
|
#define enum_from_name(e, name, valp) ({ \
|
||||||
int _val; \
|
int _val; \
|
||||||
int _found = enum_from_name_as_int(e, name, &_val); \
|
bool _found = enum_from_name_as_int(e, name, &_val); \
|
||||||
if (_found) \
|
if (_found) \
|
||||||
{ \
|
{ \
|
||||||
*(valp) = _val; \
|
*(valp) = _val; \
|
||||||
@@ -168,13 +168,13 @@ char *enum_to_name(enum_name_t *e, int val);
|
|||||||
/**
|
/**
|
||||||
* Convert a enum string back to its enum value, integer pointer variant.
|
* 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.
|
* enum type pointers for the result.
|
||||||
*
|
*
|
||||||
* @param e enum names for this enum value
|
* @param e enum names for this enum value
|
||||||
* @param name name to get enum value for
|
* @param name name to get enum value for
|
||||||
* @param val integer pointer receiving value
|
* @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);
|
bool enum_from_name_as_int(enum_name_t *e, const char *name, int *val);
|
||||||
|
|
||||||
@@ -189,6 +189,36 @@ 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);
|
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.
|
* printf hook function for enum_names_t.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user