[svn-commits] gtjoseph: trunk r430316 - in /trunk: ./ funcs/func_config.c tests/test_config.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Jan 7 11:54:19 CST 2015


Author: gtjoseph
Date: Wed Jan  7 11:54:13 2015
New Revision: 430316

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=430316
Log:
func_config: Add ability to retrieve specific occurrence of a variable

I guess nobody uses templates with AST_CONFIG because today if you have a
context that inherits from a template and you call AST_CONFIG on the context,
you'll get the value from the template even if you've overridden it in the
context.  This is because AST_CONFIG only gets the first occurrence which is
always from the template.

This patch adds an optional 'index' parameter to AST_CONFIG which lets you
specify the exact occurrence to retrieve, or '-1' to retrieve the last.
The default behavior is the current behavior.

Tested-by: George Joseph

Review: https://reviewboard.asterisk.org/r/4313/
........

Merged revisions 430315 from http://svn.asterisk.org/svn/asterisk/branches/13

Modified:
    trunk/   (props changed)
    trunk/funcs/func_config.c
    trunk/tests/test_config.c

Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-13-merged' - no diff available.

Modified: trunk/funcs/func_config.c
URL: http://svnview.digium.com/svn/asterisk/trunk/funcs/func_config.c?view=diff&rev=430316&r1=430315&r2=430316
==============================================================================
--- trunk/funcs/func_config.c (original)
+++ trunk/funcs/func_config.c Wed Jan  7 11:54:13 2015
@@ -49,6 +49,13 @@
 			<parameter name="config_file" required="true" />
 			<parameter name="category" required="true" />
 			<parameter name="variable_name" required="true" />
+			<parameter name="index" required="false">
+				<para>If there are multiple variables with the same name, you can specify
+				<literal>0</literal> for the first item (default), <literal>-1</literal> for the last
+				item, or any other number for that specific item.  <literal>-1</literal> is useful
+				when the variable is derived from a template and you want the effective value (the last
+				occurrence), not the value from the template (the first occurrence).</para>
+			</parameter>
 		</syntax>
 		<description>
 			<para>This function reads a variable from an Asterisk configuration file.</para>
@@ -65,14 +72,17 @@
 
 static AST_RWLIST_HEAD_STATIC(configs, config_item);
 
-static int config_function_read(struct ast_channel *chan, const char *cmd, char *data, 
-	char *buf, size_t len) 
+static int config_function_read(struct ast_channel *chan, const char *cmd, char *data,
+	char *buf, size_t len)
 {
 	struct ast_config *cfg;
 	struct ast_flags cfg_flags = { CONFIG_FLAG_FILEUNCHANGED };
-	const char *val;
 	char *parse;
 	struct config_item *cur;
+	int index = 0;
+	struct ast_variable *var;
+	struct ast_variable *found = NULL;
+	int ix = 0;
 	AST_DECLARE_APP_ARGS(args,
 		AST_APP_ARG(filename);
 		AST_APP_ARG(category);
@@ -101,6 +111,13 @@
 	if (ast_strlen_zero(args.variable)) {
 		ast_log(LOG_ERROR, "AST_CONFIG() requires a variable\n");
 		return -1;
+	}
+
+	if (!ast_strlen_zero(args.index)) {
+		if (!sscanf(args.index, "%d", &index)) {
+			ast_log(LOG_ERROR, "AST_CONFIG() index must be an integer\n");
+			return -1;
+		}
 	}
 
 	if (!(cfg = ast_config_load(args.filename, cfg_flags)) || cfg == CONFIG_STATUS_FILEINVALID) {
@@ -164,14 +181,29 @@
 		}
 	}
 
-	if (!(val = ast_variable_retrieve(cfg, args.category, args.variable))) {
-		ast_debug(1, "'%s' not found in [%s] of '%s'\n", args.variable,
-			args.category, args.filename);
+	for (var = ast_category_root(cfg, args.category); var; var = var->next) {
+		if (strcasecmp(args.variable, var->name)) {
+			continue;
+		}
+		found = var;
+		if (index == -1) {
+			continue;
+		}
+		if (ix == index) {
+			break;
+		}
+		found = NULL;
+		ix++;
+	}
+
+	if (!found) {
+		ast_debug(1, "'%s' not found at index %d in [%s] of '%s'.  Maximum index found: %d\n",
+			args.variable, index, args.category, args.filename, ix);
 		AST_RWLIST_UNLOCK(&configs);
 		return -1;
 	}
 
-	ast_copy_string(buf, val, len);
+	ast_copy_string(buf, found->value, len);
 
 	/* Unlock down here, so there's no chance the struct goes away while we're using it. */
 	AST_RWLIST_UNLOCK(&configs);

Modified: trunk/tests/test_config.c
URL: http://svnview.digium.com/svn/asterisk/trunk/tests/test_config.c?view=diff&rev=430316&r1=430315&r2=430316
==============================================================================
--- trunk/tests/test_config.c (original)
+++ trunk/tests/test_config.c Wed Jan  7 11:54:13 2015
@@ -42,6 +42,7 @@
 #include "asterisk/config_options.h"
 #include "asterisk/netsock2.h"
 #include "asterisk/acl.h"
+#include "asterisk/pbx.h"
 #include "asterisk/frame.h"
 #include "asterisk/utils.h"
 #include "asterisk/logger.h"
@@ -1504,6 +1505,156 @@
 	return res;
 }
 
+AST_TEST_DEFINE(config_dialplan_function)
+{
+	enum ast_test_result_state res = AST_TEST_PASS;
+	FILE *config_file;
+	char filename[PATH_MAX];
+	struct ast_str *buf;
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "config_dialplan_function";
+		info->category = "/main/config/";
+		info->summary = "Test AST_CONFIG dialplan function";
+		info->description = "Test AST_CONFIG dialplan function";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	snprintf(filename, sizeof(filename), "%s/%s",
+			ast_config_AST_CONFIG_DIR, CONFIG_FILE);
+	config_file = fopen(filename, "w");
+
+	if (!config_file) {
+		return AST_TEST_FAIL;
+	}
+
+	fputs(
+		"[c1t](!)\n"
+		"var1=val1\n"
+		"var1=val2\n"
+		"var2=val21\n"
+		"\n"
+		"[c1](c1t)\n"
+		"var1=val3\n"
+		"var1=val4\n"
+		, config_file);
+
+	fclose(config_file);
+
+	if (!(buf = ast_str_create(32))) {
+		ast_test_status_update(test, "Failed to allocate return buffer\n");
+		res = AST_TEST_FAIL;
+		goto out;
+	}
+
+	if (ast_func_read2(NULL, "AST_CONFIG("CONFIG_FILE",c1,var1)", &buf, 32)) {
+		ast_test_status_update(test, "Failed to retrieve field 'var1'\n");
+		res = AST_TEST_FAIL;
+		goto out;
+	}
+	if (strcmp(ast_str_buffer(buf), "val1")) {
+		ast_test_status_update(test, "Got '%s', should be '%s'\n",
+			ast_str_buffer(buf), "val1");
+		res = AST_TEST_FAIL;
+		goto out;
+	}
+
+	ast_str_reset(buf);
+	if (ast_func_read2(NULL, "AST_CONFIG("CONFIG_FILE",c1,var1,0)", &buf, 32)) {
+		ast_test_status_update(test, "Failed to retrieve field 'var1'\n");
+		res = AST_TEST_FAIL;
+		goto out;
+	}
+	if (strcmp(ast_str_buffer(buf), "val1")) {
+		ast_test_status_update(test, "Got '%s', should be '%s'\n",
+			ast_str_buffer(buf), "val1");
+		res = AST_TEST_FAIL;
+		goto out;
+	}
+
+	ast_str_reset(buf);
+	if (ast_func_read2(NULL, "AST_CONFIG("CONFIG_FILE",c1,var1,1)", &buf, 32)) {
+		ast_test_status_update(test, "Failed to retrieve field 'var1'\n");
+		res = AST_TEST_FAIL;
+		goto out;
+	}
+	if (strcmp(ast_str_buffer(buf), "val2")) {
+		ast_test_status_update(test, "Got '%s', should be '%s'\n",
+			ast_str_buffer(buf), "val2");
+		res = AST_TEST_FAIL;
+		goto out;
+	}
+
+	ast_str_reset(buf);
+	if (ast_func_read2(NULL, "AST_CONFIG("CONFIG_FILE",c1,var1,2)", &buf, 32)) {
+		ast_test_status_update(test, "Failed to retrieve field 'var1'\n");
+		res = AST_TEST_FAIL;
+		goto out;
+	}
+	if (strcmp(ast_str_buffer(buf), "val3")) {
+		ast_test_status_update(test, "Got '%s', should be '%s'\n",
+			ast_str_buffer(buf), "val3");
+		res = AST_TEST_FAIL;
+		goto out;
+	}
+
+	ast_str_reset(buf);
+	if (ast_func_read2(NULL, "AST_CONFIG("CONFIG_FILE",c1,var1,3)", &buf, 32)) {
+		ast_test_status_update(test, "Failed to retrieve field 'var1'\n");
+		res = AST_TEST_FAIL;
+		goto out;
+	}
+	if (strcmp(ast_str_buffer(buf), "val4")) {
+		ast_test_status_update(test, "Got '%s', should be '%s'\n",
+			ast_str_buffer(buf), "val4");
+		res = AST_TEST_FAIL;
+		goto out;
+	}
+
+	ast_str_reset(buf);
+	if (ast_func_read2(NULL, "AST_CONFIG("CONFIG_FILE",c1,var1,-1)", &buf, 32)) {
+		ast_test_status_update(test, "Failed to retrieve field 'var1'\n");
+		res = AST_TEST_FAIL;
+		goto out;
+	}
+	if (strcmp(ast_str_buffer(buf), "val4")) {
+		ast_test_status_update(test, "Got '%s', should be '%s'\n",
+			ast_str_buffer(buf), "val4");
+		res = AST_TEST_FAIL;
+		goto out;
+	}
+
+	ast_str_reset(buf);
+	if (ast_func_read2(NULL, "AST_CONFIG("CONFIG_FILE",c1,var2,-1)", &buf, 32)) {
+		ast_test_status_update(test, "Failed to retrieve field 'var2'\n");
+		res = AST_TEST_FAIL;
+		goto out;
+	}
+	if (strcmp(ast_str_buffer(buf), "val21")) {
+		ast_test_status_update(test, "Got '%s', should be '%s'\n",
+			ast_str_buffer(buf), "val21");
+		res = AST_TEST_FAIL;
+		goto out;
+	}
+
+	ast_str_reset(buf);
+	if (!ast_func_read2(NULL, "AST_CONFIG("CONFIG_FILE",c1,var1,5)", &buf, 32)) {
+		ast_test_status_update(test, "Should not have retrieved a value\n");
+		res = AST_TEST_FAIL;
+		goto out;
+	}
+
+out:
+	if (buf) {
+		ast_free(buf);
+	}
+	delete_config_file();
+	return res;
+}
+
 static int unload_module(void)
 {
 	AST_TEST_UNREGISTER(config_basic_ops);
@@ -1513,6 +1664,7 @@
 	AST_TEST_UNREGISTER(config_hook);
 	AST_TEST_UNREGISTER(ast_parse_arg_test);
 	AST_TEST_UNREGISTER(config_options_test);
+	AST_TEST_UNREGISTER(config_dialplan_function);
 	return 0;
 }
 
@@ -1525,6 +1677,7 @@
 	AST_TEST_REGISTER(config_hook);
 	AST_TEST_REGISTER(ast_parse_arg_test);
 	AST_TEST_REGISTER(config_options_test);
+	AST_TEST_REGISTER(config_dialplan_function);
 	return AST_MODULE_LOAD_SUCCESS;
 }
 




More information about the svn-commits mailing list