core: Config and XML tweaks needed for geolocation

Added:

Replace a variable in a list:
int ast_variable_list_replace_variable(struct ast_variable **head,
    struct ast_variable *old, struct ast_variable *new);
Added test as well.

Create a "name=value" string from a variable list:
'name1="val1",name2="val2"', etc.
struct ast_str *ast_variable_list_join(
    const struct ast_variable *head, const char *item_separator,
    const char *name_value_separator, const char *quote_char,
    struct ast_str **str);
Added test as well.

Allow the name of an XML element to be changed.
void ast_xml_set_name(struct ast_xml_node *node, const char *name);

Change-Id: I330a5f63dc0c218e0d8dfc0745948d2812141ccb
This commit is contained in:
George Joseph 2022-02-20 13:16:22 -07:00 committed by Friendly Automation
parent 466a361626
commit 83372e7ab5
5 changed files with 149 additions and 0 deletions

View File

@ -967,6 +967,44 @@ struct ast_variable *ast_variable_list_append_hint(struct ast_variable **head, s
*/
int ast_variable_list_replace(struct ast_variable **head, struct ast_variable *replacement);
/*!
* \brief Replace a variable in the given list with a new variable
*
* \param head A pointer to the current variable list head. Since the variable to be
* replaced, this pointer may be updated with the new head.
* \param old A pointer to the existing variable to be replaced.
* \param new A pointer to the new variable that will replace the old one.
*
* \retval 0 if a variable was replaced in the list
* \retval -1 if no replacement occured
*
* \note The search for the old variable is done simply on the pointer.
* \note If a variable is replaced, its memory is freed.
*/
int ast_variable_list_replace_variable(struct ast_variable **head, struct ast_variable *old,
struct ast_variable *new);
/*!
* \brief Join an ast_variable list with specified separators and quoted values
*
* \param head A pointer to an ast_variable list head.
* \param item_separator The string to use to separate the list items.
* If NULL, "," will be used.
* \param name_value_separator The string to use to separate each item's name and value.
* If NULL, "=" will be used.
* \param str A pointer to a pre-allocated ast_str in which to put the results.
* If NULL, one will be allocated and returned.
* \param quote_char The quote char to use for the values.
* May be NULL or empty for no quoting.
*
* \retval A pointer to the result ast_str. This may NOT be the same as the pointer
* passed in if the original ast_str wasn't large enough to hold the result.
* Regardless, the pointer MUST be freed after use.
* \retval NULL if there was an error.
*/
struct ast_str *ast_variable_list_join(const struct ast_variable *head, const char *item_separator,
const char *name_value_separator, const char *quote_char, struct ast_str **str);
/*!
* \brief Update variable value within a config
*

View File

@ -201,6 +201,13 @@ const char *ast_xml_get_text(struct ast_xml_node *node);
*/
void ast_xml_set_text(struct ast_xml_node *node, const char *content);
/*!
* \brief Set or reset an element's name.
* \param node Node whose name is to be set.
* \param name New name.
*/
void ast_xml_set_name(struct ast_xml_node *node, const char *name);
/*!
* \brief Get the name of a node. */
const char *ast_xml_node_get_name(struct ast_xml_node *node);

View File

@ -679,6 +679,49 @@ int ast_variable_list_replace(struct ast_variable **head, struct ast_variable *r
return -1;
}
int ast_variable_list_replace_variable(struct ast_variable **head, struct ast_variable *old,
struct ast_variable *new)
{
struct ast_variable *v, **prev = head;
for (v = *head; v; prev = &v->next, v = v->next) {
if (v == old) {
new->next = v->next;
*prev = new;
ast_free(v);
return 0;
}
}
return -1;
}
struct ast_str *ast_variable_list_join(const struct ast_variable *head, const char *item_separator,
const char *name_value_separator, const char *quote_char, struct ast_str **str)
{
struct ast_variable *var = (struct ast_variable *)head;
struct ast_str *local_str = NULL;
if (str == NULL || *str == NULL) {
local_str = ast_str_create(AST_MAX_USER_FIELD);
if (!local_str) {
return NULL;
}
} else {
local_str = *str;
}
for (; var; var = var->next) {
ast_str_append(&local_str, 0, "%s%s%s%s%s%s", var->name, name_value_separator, S_OR(quote_char, ""),
var->value, S_OR(quote_char, ""), var->next ? item_separator : "");
}
if (str != NULL) {
*str = local_str;
}
return local_str;
}
const char *ast_config_option(struct ast_config *cfg, const char *cat, const char *var)
{
const char *tmp;

View File

@ -332,6 +332,15 @@ void ast_xml_set_text(struct ast_xml_node *node, const char *content)
xmlNodeSetContent((xmlNode *) node, (const xmlChar *) content);
}
void ast_xml_set_name(struct ast_xml_node *node, const char *name)
{
if (!node || !name) {
return;
}
xmlNodeSetName((xmlNode *) node, (const xmlChar *) name);
}
int ast_xml_doc_dump_file(FILE *output, struct ast_xml_doc *doc)
{
return xmlDocDump(output, (xmlDocPtr)doc);

View File

@ -1893,6 +1893,56 @@ AST_TEST_DEFINE(variable_lists_match)
return AST_TEST_PASS;
}
AST_TEST_DEFINE(variable_list_join_replace)
{
RAII_VAR(struct ast_variable *, list, NULL, ast_variables_destroy);
RAII_VAR(struct ast_str *, str, NULL, ast_free);
struct ast_variable *bbb;
int rc;
switch (cmd) {
case TEST_INIT:
info->name = "variable_list_join_replace";
info->category = "/main/config/";
info->summary = "Test joining a variable list";
info->description = info->summary;
return AST_TEST_NOT_RUN;
case TEST_EXECUTE:
break;
}
list = ast_variable_new("aaa", "111", "");
bbb = ast_variable_new("bbb", "222", "");
ast_variable_list_append(&list, bbb);
ast_variable_list_append(&list, ast_variable_new("ccc", "33 33", ""));
str = ast_variable_list_join(list, ", ", " = ", "\"", &str);
ast_test_validate(test, strcmp(ast_str_buffer(str), "aaa = \"111\", bbb = \"222\", ccc = \"33 33\"") == 0);
ast_free(str);
str = ast_str_create(AST_MAX_USER_FIELD);
str = ast_variable_list_join(list, ", ", " = ", "\"", &str);
ast_test_validate(test, strcmp(ast_str_buffer(str), "aaa = \"111\", bbb = \"222\", ccc = \"33 33\"") == 0);
ast_free(str);
str = ast_variable_list_join(list, ", ", " = ", "\"", NULL);
ast_test_validate(test, strcmp(ast_str_buffer(str), "aaa = \"111\", bbb = \"222\", ccc = \"33 33\"") == 0);
ast_free(str);
/* Replace the head item in the list */
rc = ast_variable_list_replace_variable(&list, list, ast_variable_new("ddd", "444", ""));
ast_test_validate(test, rc == 0);
str = ast_variable_list_join(list, ", ", " = ", "\"", NULL);
ast_test_validate(test, strcmp(ast_str_buffer(str), "ddd = \"444\", bbb = \"222\", ccc = \"33 33\"") == 0);
ast_free(str);
rc = ast_variable_list_replace_variable(&list, bbb, ast_variable_new("eee", "555", ""));
ast_test_validate(test, rc == 0);
str = ast_variable_list_join(list, ", ", " = ", "\"", NULL);
ast_test_validate(test, strcmp(ast_str_buffer(str), "ddd = \"444\", eee = \"555\", ccc = \"33 33\"") == 0);
return AST_TEST_PASS;
}
static int unload_module(void)
{
AST_TEST_UNREGISTER(config_save);
@ -1905,6 +1955,7 @@ static int unload_module(void)
AST_TEST_UNREGISTER(config_options_test);
AST_TEST_UNREGISTER(config_dialplan_function);
AST_TEST_UNREGISTER(variable_lists_match);
AST_TEST_UNREGISTER(variable_list_join_replace);
return 0;
}
@ -1920,6 +1971,7 @@ static int load_module(void)
AST_TEST_REGISTER(config_options_test);
AST_TEST_REGISTER(config_dialplan_function);
AST_TEST_REGISTER(variable_lists_match);
AST_TEST_REGISTER(variable_list_join_replace);
return AST_MODULE_LOAD_SUCCESS;
}