[Asterisk-code-review] strings/json: Add string delimter match, and object create with vars ... (asterisk[18])

Friendly Automation asteriskteam at digium.com
Thu Oct 28 08:58:46 CDT 2021


Friendly Automation has submitted this change. ( https://gerrit.asterisk.org/c/asterisk/+/16641 )

Change subject: strings/json: Add string delimter match, and object create with vars methods
......................................................................

strings/json: Add string delimter match, and object create with vars methods

Add a function to check if there is an exact match a one string between
delimiters in another string.

Add a function that will create an ast_json object out of a list of
Asterisk variables. An excludes string can also optionally be passed
in.

Also, add a macro to make it easier to get object integers.

Change-Id: I5f34f18e102126aef3997f19a553a266d70d6226
---
M include/asterisk/json.h
M include/asterisk/strings.h
M main/json.c
M main/strings.c
M tests/test_json.c
M tests/test_strings.c
6 files changed, 250 insertions(+), 0 deletions(-)

Approvals:
  George Joseph: Looks good to me, approved
  Friendly Automation: Approved for Submit



diff --git a/include/asterisk/json.h b/include/asterisk/json.h
index ce0baa4..3f485d1 100644
--- a/include/asterisk/json.h
+++ b/include/asterisk/json.h
@@ -539,6 +539,15 @@
 struct ast_json *ast_json_object_create(void);
 
 /*!
+ * \brief Create a new JSON object using the given variables
+ * \param variables A list of Asterisk variables
+ * \param excludes Comma separated string of variable names to exclude (optional)
+ * \return Newly allocated object.
+ * \return \c NULL on error.
+ */
+struct ast_json *ast_json_object_create_vars(const struct ast_variable *variables, const char *excludes);
+
+/*!
  * \brief Get size of JSON object.
  * \since 12.0.0
  * \param object JSON object.
@@ -573,6 +582,14 @@
 #define ast_json_object_string_get(object, key) ast_json_string_get(ast_json_object_get(object, key))
 
 /*!
+ * \brief Get an integer field from a JSON object.
+ * \param integer JSON integer.
+ * \return Value of a JSON integer.
+ * \return 0 if \a integer is not a JSON integer.
+ */
+#define ast_json_object_integer_get(object, key) ast_json_integer_get(ast_json_object_get(object, key))
+
+/*!
  * \brief Set a field in a JSON object.
  * \since 12.0.0
  *
diff --git a/include/asterisk/strings.h b/include/asterisk/strings.h
index 929cbf5..881cf89 100644
--- a/include/asterisk/strings.h
+++ b/include/asterisk/strings.h
@@ -401,6 +401,19 @@
 )
 
 /*!
+ * \brief Check if there is an exact match for 'needle' between delimiters in 'haystack'.
+ *
+ * \note This will skip extra leading spaces between delimiters.
+ *
+ * \param needle The string to search for
+ * \param haystack The string searched in
+ * \param delim The haystack delimiter
+ *
+ * \return True if an exact match for needle is in haystack, false otherwise
+ */
+int ast_in_delimited_string(const char *needle, const char *haystack, char delim);
+
+/*!
   \brief Build a string in a buffer, designed to be called repeatedly
 
   \note This method is not recommended. New code should use ast_str_*() instead.
diff --git a/main/json.c b/main/json.c
index 09101aa..616b12e 100644
--- a/main/json.c
+++ b/main/json.c
@@ -852,3 +852,22 @@
 
 	return ret;
 }
+
+struct ast_json *ast_json_object_create_vars(const struct ast_variable *variables, const char *excludes)
+{
+	const struct ast_variable *i;
+	struct ast_json *obj;
+
+	obj = ast_json_object_create();
+	if (!obj) {
+		return NULL;
+	}
+
+	for (i = variables; i; i = i->next) {
+		if (!excludes || !ast_in_delimited_string(i->name, excludes, ',')) {
+			ast_json_object_set(obj, i->name, ast_json_string_create(i->value));
+		}
+	}
+
+	return obj;
+}
diff --git a/main/strings.c b/main/strings.c
index 0cd4692..20769fa 100644
--- a/main/strings.c
+++ b/main/strings.c
@@ -430,3 +430,28 @@
 
 	return 0;
 }
+
+int ast_in_delimited_string(const char *needle, const char *haystack, char delim)
+{
+	const char *end;
+	unsigned long needle_size;
+
+	ast_assert(haystack != NULL);
+
+	if (!needle) {
+		return 0;
+	}
+
+	needle_size = strlen(needle);
+	haystack = ast_skip_blanks(haystack);
+
+	while ((end = strchr(haystack, delim))) {
+		if (needle_size == end - haystack && !strncmp(haystack, needle, needle_size)) {
+			return 1;
+		}
+		haystack = ast_skip_blanks(end + 1);
+	}
+
+	return strcmp(haystack, needle) ? 0 : -1;
+}
+
diff --git a/tests/test_json.c b/tests/test_json.c
index 8dbb872..a14ac3a 100644
--- a/tests/test_json.c
+++ b/tests/test_json.c
@@ -37,6 +37,7 @@
 
 #include "asterisk.h"
 
+#include "asterisk/config.h"
 #include "asterisk/json.h"
 #include "asterisk/module.h"
 #include "asterisk/test.h"
@@ -1090,6 +1091,63 @@
 	return AST_TEST_PASS;
 }
 
+AST_TEST_DEFINE(json_test_object_create_vars)
+{
+	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
+	RAII_VAR(struct ast_variable *, vars, NULL, ast_variables_destroy);
+	const char *value;
+	struct ast_variable *new_var;
+
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "object_create_vars";
+		info->category = CATEGORY;
+		info->summary = "Testing JSON object creation initialized using Asterisk variables.";
+		info->description = "Test JSON abstraction library.";
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	/* NULL case */
+	ast_test_validate(test, (uut = ast_json_object_create_vars(NULL, NULL)));
+	ast_test_validate(test, !(value = ast_json_object_string_get(uut, "foo")));
+
+	ast_test_validate(test, (new_var = ast_variable_new("foo", "bar", "")));
+	ast_variable_list_append(&vars, new_var);
+	ast_test_validate(test, (new_var = ast_variable_new("bar", "baz", "")));
+	ast_variable_list_append(&vars, new_var);
+
+	/* Variables case */
+	ast_json_unref(uut);
+	ast_test_validate(test, (uut = ast_json_object_create_vars(vars, NULL)));
+	ast_test_validate(test, (value = ast_json_object_string_get(uut, "foo")));
+	ast_test_validate(test, !strcmp("bar", value));
+	ast_test_validate(test, (value = ast_json_object_string_get(uut, "bar")));
+	ast_test_validate(test, !strcmp("baz", value));
+
+	/* Variables with excludes case */
+	ast_json_unref(uut);
+	ast_test_validate(test, (uut = ast_json_object_create_vars(vars, "foo")));
+	ast_test_validate(test, !(value = ast_json_object_string_get(uut, "foo")));
+	ast_test_validate(test, (value = ast_json_object_string_get(uut, "bar")));
+	ast_test_validate(test, !strcmp("baz", value));
+
+	ast_json_unref(uut);
+	ast_test_validate(test, (uut = ast_json_object_create_vars(vars, "foo2")));
+	ast_test_validate(test, (value = ast_json_object_string_get(uut, "foo")));
+	ast_test_validate(test, (value = ast_json_object_string_get(uut, "bar")));
+	ast_test_validate(test, !strcmp("baz", value));
+
+	ast_json_unref(uut);
+	ast_test_validate(test, (uut = ast_json_object_create_vars(vars, "foobar,baz")));
+	ast_test_validate(test, (value = ast_json_object_string_get(uut, "foo")));
+	ast_test_validate(test, (value = ast_json_object_string_get(uut, "bar")));
+	ast_test_validate(test, !strcmp("baz", value));
+
+	return AST_TEST_PASS;
+}
+
 AST_TEST_DEFINE(json_test_dump_load_string)
 {
 	RAII_VAR(struct ast_json *, uut, NULL, ast_json_unref);
@@ -1738,6 +1796,7 @@
 	AST_TEST_UNREGISTER(json_test_object_null);
 	AST_TEST_UNREGISTER(json_test_object_iter);
 	AST_TEST_UNREGISTER(json_test_object_iter_null);
+	AST_TEST_UNREGISTER(json_test_object_create_vars);
 	AST_TEST_UNREGISTER(json_test_dump_load_string);
 	AST_TEST_UNREGISTER(json_test_dump_load_str);
 	AST_TEST_UNREGISTER(json_test_dump_str_fail);
@@ -1794,6 +1853,7 @@
 	AST_TEST_REGISTER(json_test_object_null);
 	AST_TEST_REGISTER(json_test_object_iter);
 	AST_TEST_REGISTER(json_test_object_iter_null);
+	AST_TEST_REGISTER(json_test_object_create_vars);
 	AST_TEST_REGISTER(json_test_dump_load_string);
 	AST_TEST_REGISTER(json_test_dump_load_str);
 	AST_TEST_REGISTER(json_test_dump_str_fail);
diff --git a/tests/test_strings.c b/tests/test_strings.c
index 3d697e5..63ac856 100644
--- a/tests/test_strings.c
+++ b/tests/test_strings.c
@@ -620,6 +620,120 @@
 	return AST_TEST_PASS;
 }
 
+AST_TEST_DEFINE(in_delimited_string)
+{
+	switch (cmd) {
+	case TEST_INIT:
+		info->name = "in_delimited_string";
+		info->category = "/main/strings/";
+		info->summary = "Test ast_in_delimited_string";
+		info->description = info->summary;
+		return AST_TEST_NOT_RUN;
+	case TEST_EXECUTE:
+		break;
+	}
+
+	/* Single letter */
+	ast_test_validate(test, ast_in_delimited_string("a", "a,b", ','));
+	ast_test_validate(test, ast_in_delimited_string("b", "a,b", ','));
+
+	ast_test_validate(test, !ast_in_delimited_string("c", "a,b", ','));
+	ast_test_validate(test, !ast_in_delimited_string("aa", "a,b", ','));
+	ast_test_validate(test, !ast_in_delimited_string("bb", "a,b", ','));
+	ast_test_validate(test, !ast_in_delimited_string("a,", "a,b", ','));
+	ast_test_validate(test, !ast_in_delimited_string(",b", "a,b", ','));
+	ast_test_validate(test, !ast_in_delimited_string("a,b", "a,b", ','));
+
+	/* Bad delimiter (ends up being just a strcmp) */
+	ast_test_validate(test, !ast_in_delimited_string("a", "a,b", '#'));
+	ast_test_validate(test, !ast_in_delimited_string("b", "a,b", '#'));
+
+	ast_test_validate(test, !ast_in_delimited_string("c", "a,b", '#'));
+	ast_test_validate(test, !ast_in_delimited_string("aa", "a,b", '#'));
+	ast_test_validate(test, !ast_in_delimited_string("bb", "a,b", '#'));
+	ast_test_validate(test, !ast_in_delimited_string("a,", "a,b", '#'));
+	ast_test_validate(test, !ast_in_delimited_string(",b", "a,b", '#'));
+
+	ast_test_validate(test, ast_in_delimited_string("a,b", "a,b", '#'));
+
+	/* Multi letter */
+	ast_test_validate(test, ast_in_delimited_string("abc", "abc,def", ','));
+	ast_test_validate(test, ast_in_delimited_string("def", "abc,def", ','));
+
+	ast_test_validate(test, !ast_in_delimited_string("a", "abc,def", ','));
+	ast_test_validate(test, !ast_in_delimited_string("b", "abc,def", ','));
+	ast_test_validate(test, !ast_in_delimited_string("c", "abc,def", ','));
+
+	ast_test_validate(test, !ast_in_delimited_string("d", "abc,def", ','));
+	ast_test_validate(test, !ast_in_delimited_string("e", "abc,def", ','));
+	ast_test_validate(test, !ast_in_delimited_string("f", "abc,def", ','));
+
+	ast_test_validate(test, !ast_in_delimited_string("abc,", "abc,def", ','));
+	ast_test_validate(test, !ast_in_delimited_string(",def", "abc,def", ','));
+	ast_test_validate(test, !ast_in_delimited_string("abc,def", "abc,def", ','));
+
+	/* Embedded */
+	ast_test_validate(test, ast_in_delimited_string("abc", "abcdef,abc", ','));
+	ast_test_validate(test, ast_in_delimited_string("abcdef", "abcdef,abc", ','));
+
+	ast_test_validate(test, !ast_in_delimited_string("abc", "abcdef,def", ','));
+	ast_test_validate(test, !ast_in_delimited_string("def", "abcdef,abc", ','));
+	ast_test_validate(test, !ast_in_delimited_string("def", "abcdefghi,abc", ','));
+
+	/* NULL and empty values */
+	ast_test_validate(test, !ast_in_delimited_string(NULL, "abc,def", ','));
+
+	ast_test_validate(test, ast_in_delimited_string("abc", ",abc,def", ','));
+	ast_test_validate(test, ast_in_delimited_string("abc", "abc,def,", ','));
+	ast_test_validate(test, ast_in_delimited_string("abc", "abc,,def,", ','));
+	ast_test_validate(test, ast_in_delimited_string("def", "abc,,def", ','));
+	ast_test_validate(test, ast_in_delimited_string("def", ",abc,,def,", ','));
+
+	ast_test_validate(test, ast_in_delimited_string("", ",abc,def", ','));
+	ast_test_validate(test, ast_in_delimited_string("", "abc,def,", ','));
+	ast_test_validate(test, ast_in_delimited_string("", "abc,,def,", ','));
+	ast_test_validate(test, !ast_in_delimited_string("", "abc,def", ','));
+
+	/* Multi word */
+	ast_test_validate(test, ast_in_delimited_string("abc", "abc,def,ghi", ','));
+	ast_test_validate(test, ast_in_delimited_string("def", "abc,def,ghi", ','));
+	ast_test_validate(test, ast_in_delimited_string("ghi", "abc,def,ghi", ','));
+
+	ast_test_validate(test, !ast_in_delimited_string("a", "abc,def,ghi", ','));
+	ast_test_validate(test, !ast_in_delimited_string("d", "abc,def,ghi", ','));
+	ast_test_validate(test, !ast_in_delimited_string("g", "abc,def,ghi", ','));
+
+	ast_test_validate(test, !ast_in_delimited_string("ab", "abc,def,ghi", ','));
+	ast_test_validate(test, !ast_in_delimited_string("de", "abc,def,ghi", ','));
+	ast_test_validate(test, !ast_in_delimited_string("gh", "abc,def,ghi", ','));
+
+
+	/* With leading spaces */
+	ast_test_validate(test, ast_in_delimited_string("abc", " abc", ','));
+	ast_test_validate(test, ast_in_delimited_string("abc", " abc, def", ','));
+	ast_test_validate(test, ast_in_delimited_string("def", " abc, def", ','));
+	ast_test_validate(test, ast_in_delimited_string("abc", " abc, def, ghi", ','));
+	ast_test_validate(test, ast_in_delimited_string("def", " abc, def, ghi", ','));
+	ast_test_validate(test, ast_in_delimited_string("ghi", " abc, def, ghi", ','));
+
+	ast_test_validate(test, ast_in_delimited_string("abc", "   abc", ','));
+	ast_test_validate(test, ast_in_delimited_string("abc", "   abc,   def", ','));
+	ast_test_validate(test, ast_in_delimited_string("def", "   abc,   def", ','));
+	ast_test_validate(test, ast_in_delimited_string("abc", "   abc,   def,   ghi", ','));
+	ast_test_validate(test, ast_in_delimited_string("def", "   abc,   def,   ghi", ','));
+	ast_test_validate(test, ast_in_delimited_string("ghi", "   abc,   def,   ghi", ','));
+
+	/* With leading spaces and space as a delimiter */
+	ast_test_validate(test, ast_in_delimited_string("abc", "   abc", ' '));
+	ast_test_validate(test, ast_in_delimited_string("abc", "   abc   def", ' '));
+	ast_test_validate(test, ast_in_delimited_string("def", "   abc   def", ' '));
+	ast_test_validate(test, ast_in_delimited_string("abc", "   abc   def   ghi", ' '));
+	ast_test_validate(test, ast_in_delimited_string("def", "   abc   def   ghi", ' '));
+	ast_test_validate(test, ast_in_delimited_string("ghi", "   abc   def   ghi", ' '));
+
+	return AST_TEST_PASS;
+}
+
 static int unload_module(void)
 {
 	AST_TEST_UNREGISTER(str_test);
@@ -630,6 +744,7 @@
 	AST_TEST_UNREGISTER(escape_test);
 	AST_TEST_UNREGISTER(strings_match);
 	AST_TEST_UNREGISTER(temp_strings);
+	AST_TEST_UNREGISTER(in_delimited_string);
 	return 0;
 }
 
@@ -643,6 +758,7 @@
 	AST_TEST_REGISTER(escape_test);
 	AST_TEST_REGISTER(strings_match);
 	AST_TEST_REGISTER(temp_strings);
+	AST_TEST_REGISTER(in_delimited_string);
 	return AST_MODULE_LOAD_SUCCESS;
 }
 

-- 
To view, visit https://gerrit.asterisk.org/c/asterisk/+/16641
To unsubscribe, or for help writing mail filters, visit https://gerrit.asterisk.org/settings

Gerrit-Project: asterisk
Gerrit-Branch: 18
Gerrit-Change-Id: I5f34f18e102126aef3997f19a553a266d70d6226
Gerrit-Change-Number: 16641
Gerrit-PatchSet: 4
Gerrit-Owner: Kevin Harwell <kharwell at digium.com>
Gerrit-Reviewer: Friendly Automation
Gerrit-Reviewer: George Joseph <gjoseph at digium.com>
Gerrit-Reviewer: Joshua Colp <jcolp at sangoma.com>
Gerrit-MessageType: merged
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.digium.com/pipermail/asterisk-code-review/attachments/20211028/cd615413/attachment-0001.html>


More information about the asterisk-code-review mailing list