diff options
-rw-r--r-- | configs/config_test.conf.sample | 6 | ||||
-rw-r--r-- | include/asterisk/config_options.h | 20 | ||||
-rw-r--r-- | main/config_options.c | 19 | ||||
-rw-r--r-- | tests/test_config.c | 23 |
4 files changed, 67 insertions, 1 deletions
diff --git a/configs/config_test.conf.sample b/configs/config_test.conf.sample index f03291cde..425b34e03 100644 --- a/configs/config_test.conf.sample +++ b/configs/config_test.conf.sample @@ -9,6 +9,9 @@ uintopt=1 doubleopt=0.1 sockaddropt=1.2.3.4:1234 boolopt=true +boolflag1=true +boolflag2=false +boolflag3=true acldenyopt=0.0.0.0/0 aclpermitopt=1.2.3.4/32 codecopt=!all,ulaw,g729 @@ -23,6 +26,9 @@ uintopt=1 doubleopt=0.1 sockaddropt=1.2.3.4:1234 boolopt=true +boolflag1=true +boolflag2=false +boolflag3=true acldenyopt=0.0.0.0/0 aclpermitopt=1.2.3.4/32 codecopt=!all,ulaw,g729 diff --git a/include/asterisk/config_options.h b/include/asterisk/config_options.h index 1bbf27025..c65e5d07a 100644 --- a/include/asterisk/config_options.h +++ b/include/asterisk/config_options.h @@ -261,6 +261,26 @@ enum aco_option_type { */ OPT_BOOL_T, + /*! \brief Type for default option handler for bools (ast_true/ast_false) that are stored in a flag + * \note aco_option_register flags: + * non-zero : process via ast_true + * 0 : process via ast_false + * aco_option_register varargs: + * FLDSET macro with the field of type of unsigned int. + * The flag to set + * + * Example: + * {code} + * #define MY_TYPE_ISQUIET 1 << 4 + * struct test_item { + * unsigned int flags; + * }; + aco_option_register(&cfg_info, "quiet", ACO_EXACT, my_types, "no", OPT_BOOLFLAG_T, 1, FLDSET(struct test_item, flags), MY_TYPE_ISQUIET); + * {endcode} + */ + + OPT_BOOLFLAG_T, + /*! \brief Type for default option handler for codec preferences/capabilities * \note aco_option_register flags: * non-zero : This is an "allow" style option diff --git a/main/config_options.c b/main/config_options.c index eedce2879..efba8de3a 100644 --- a/main/config_options.c +++ b/main/config_options.c @@ -92,6 +92,7 @@ static int double_handler_fn(const struct aco_option *opt, struct ast_variable * static int sockaddr_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj); static int stringfield_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj); static int bool_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj); +static int boolflag_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj); static int acl_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj); static int codec_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj); @@ -100,6 +101,7 @@ static aco_option_handler ast_config_option_default_handler(enum aco_option_type switch(type) { case OPT_ACL_T: return acl_handler_fn; case OPT_BOOL_T: return bool_handler_fn; + case OPT_BOOLFLAG_T: return boolflag_handler_fn; case OPT_CODEC_T: return codec_handler_fn; case OPT_DOUBLE_T: return double_handler_fn; case OPT_INT_T: return int_handler_fn; @@ -741,6 +743,23 @@ static int bool_handler_fn(const struct aco_option *opt, struct ast_variable *va return 0; } +/*! \brief Default option handler for bools (ast_true/ast_false) that are stored as flags + * \note For a description of the opt->flags and opt->args values, see the documentation for + * enum aco_option_type in config_options.h + */ +static int boolflag_handler_fn(const struct aco_option *opt, struct ast_variable *var, void *obj) +{ + unsigned int *flags_field = (unsigned int *)(obj + opt->args[0]); + unsigned int val = opt->flags ? ast_true(var->value) : ast_false(var->value); + unsigned int flag = opt->args[1]; + if (val) { + *flags_field |= flag; + } else { + *flags_field &= ~flag; + } + return 0; +} + /*! \brief Default handler for ast_sockaddrs * \note For a description of the opt->flags and opt->args values, see the documentation for * enum aco_option_type in config_options.h diff --git a/tests/test_config.c b/tests/test_config.c index 4d92c7913..0c2816579 100644 --- a/tests/test_config.c +++ b/tests/test_config.c @@ -622,6 +622,7 @@ struct test_item { ); int32_t intopt; uint32_t uintopt; + unsigned int flags; double doubleopt; struct ast_sockaddr sockaddropt; int boolopt; @@ -784,6 +785,12 @@ AST_TEST_DEFINE(config_options_test) #define SOCKADDR_CONFIG "1.2.3.4:1234" #define BOOL_DEFAULT "false" #define BOOL_CONFIG "true" +#define BOOLFLAG1_DEFAULT "false" +#define BOOLFLAG1_CONFIG "true" +#define BOOLFLAG2_DEFAULT "false" +#define BOOLFLAG2_CONFIG "false" +#define BOOLFLAG3_DEFAULT "false" +#define BOOLFLAG3_CONFIG "true" #define ACL_DEFAULT NULL #define ACL_CONFIG_PERMIT "1.2.3.4/32" #define ACL_CONFIG_DENY "0.0.0.0/0" @@ -794,6 +801,10 @@ AST_TEST_DEFINE(config_options_test) #define CUSTOM_DEFAULT "no" #define CUSTOM_CONFIG "yes" +#define BOOLFLAG1 1 << 0 +#define BOOLFLAG2 1 << 1 +#define BOOLFLAG3 1 << 2 + if (aco_info_init(&cfg_info)) { ast_test_status_update(test, "Could not init cfg info\n"); return AST_TEST_FAIL; @@ -805,6 +816,9 @@ AST_TEST_DEFINE(config_options_test) aco_option_register(&cfg_info, "doubleopt", ACO_EXACT, config_test_conf.types, DOUBLE_DEFAULT, OPT_DOUBLE_T, 0, FLDSET(struct test_item, doubleopt)); aco_option_register(&cfg_info, "sockaddropt", ACO_EXACT, config_test_conf.types, SOCKADDR_DEFAULT, OPT_SOCKADDR_T, 0, FLDSET(struct test_item, sockaddropt)); aco_option_register(&cfg_info, "boolopt", ACO_EXACT, config_test_conf.types, BOOL_DEFAULT, OPT_BOOL_T, 1, FLDSET(struct test_item, boolopt)); + aco_option_register(&cfg_info, "boolflag1", ACO_EXACT, config_test_conf.types, BOOLFLAG1_DEFAULT, OPT_BOOLFLAG_T, 1, FLDSET(struct test_item, flags), BOOLFLAG1); + aco_option_register(&cfg_info, "boolflag2", ACO_EXACT, config_test_conf.types, BOOLFLAG2_DEFAULT, OPT_BOOLFLAG_T, 1, FLDSET(struct test_item, flags), BOOLFLAG2); + aco_option_register(&cfg_info, "boolflag3", ACO_EXACT, config_test_conf.types, BOOLFLAG3_DEFAULT, OPT_BOOLFLAG_T, 1, FLDSET(struct test_item, flags), BOOLFLAG3); aco_option_register(&cfg_info, "aclpermitopt", ACO_EXACT, config_test_conf.types, ACL_DEFAULT, OPT_ACL_T, 1, FLDSET(struct test_item, aclopt)); aco_option_register(&cfg_info, "acldenyopt", ACO_EXACT, config_test_conf.types, ACL_DEFAULT, OPT_ACL_T, 0, FLDSET(struct test_item, aclopt)); aco_option_register(&cfg_info, "codecopt", ACO_EXACT, config_test_conf.types, CODEC_DEFAULT, OPT_CODEC_T, 1, FLDSET(struct test_item, codecprefopt, codeccapopt)); @@ -826,6 +840,12 @@ AST_TEST_DEFINE(config_options_test) ast_parse_arg(SOCKADDR_CONFIG, PARSE_ADDR, &configs.sockaddropt); defaults.boolopt = ast_true(BOOL_DEFAULT); configs.boolopt = ast_true(BOOL_CONFIG); + ast_set2_flag(&defaults, ast_true(BOOLFLAG1_DEFAULT), BOOLFLAG1); + ast_set2_flag(&defaults, ast_true(BOOLFLAG2_DEFAULT), BOOLFLAG2); + ast_set2_flag(&defaults, ast_true(BOOLFLAG3_DEFAULT), BOOLFLAG3); + ast_set2_flag(&configs, ast_true(BOOLFLAG1_CONFIG), BOOLFLAG1); + ast_set2_flag(&configs, ast_true(BOOLFLAG2_CONFIG), BOOLFLAG2); + ast_set2_flag(&configs, ast_true(BOOLFLAG3_CONFIG), BOOLFLAG3); defaults.aclopt = NULL; configs.aclopt = ast_append_ha("deny", ACL_CONFIG_DENY, configs.aclopt, &error); @@ -865,7 +885,7 @@ AST_TEST_DEFINE(config_options_test) #define NOT_EQUAL_FAIL(field) \ if (arr[x]->field != control->field) { \ - ast_test_status_update(test, "%s di not match: %d != %d with x = %d\n", #field, arr[x]->field, control->field, x); \ + ast_test_status_update(test, "%s did not match: %d != %d with x = %d\n", #field, arr[x]->field, control->field, x); \ res = AST_TEST_FAIL; \ } for (x = 0; x < 4; x++) { @@ -874,6 +894,7 @@ AST_TEST_DEFINE(config_options_test) NOT_EQUAL_FAIL(intopt); NOT_EQUAL_FAIL(uintopt); NOT_EQUAL_FAIL(boolopt); + NOT_EQUAL_FAIL(flags); NOT_EQUAL_FAIL(customopt); if (fabs(arr[x]->doubleopt - control->doubleopt) > 0.001) { ast_test_status_update(test, "doubleopt did not match: %f vs %f on loop %d\n", arr[x]->doubleopt, control->doubleopt, x); |