<p>N A has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/16463">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">func_strings: Add STRBETWEEN function<br><br>Adds the STRBETWEEN function, which can be used to insert a<br>substring between each character in a string. For instance,<br>this can be used to insert pauses between DTMF tones in a<br>string of digits.<br><br>ASTERISK-29627<br><br>Change-Id: Ice23009d4a8e9bb9718d2b2301d405567087d258<br>---<br>A doc/CHANGES-staging/func_strings.txt<br>M funcs/func_strings.c<br>2 files changed, 151 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.asterisk.org:29418/asterisk refs/changes/63/16463/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/doc/CHANGES-staging/func_strings.txt b/doc/CHANGES-staging/func_strings.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..d154464</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/func_strings.txt</span><br><span>@@ -0,0 +1,7 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: func_strings</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+A new STRBETWEEN function is now included which</span><br><span style="color: hsl(120, 100%, 40%);">+allows a substring to be inserted between characters</span><br><span style="color: hsl(120, 100%, 40%);">+in a string. This is particularly useful for transforming</span><br><span style="color: hsl(120, 100%, 40%);">+dial strings, such as adding pauses between digits</span><br><span style="color: hsl(120, 100%, 40%);">+for a string of digits that are sent to another channel.</span><br><span>diff --git a/funcs/func_strings.c b/funcs/func_strings.c</span><br><span>index 7afc40e..c70c9bd 100644</span><br><span>--- a/funcs/func_strings.c</span><br><span>+++ b/funcs/func_strings.c</span><br><span>@@ -4,6 +4,7 @@</span><br><span> * Copyright (C) 2005-2006, Digium, Inc.</span><br><span> * Portions Copyright (C) 2005, Tilghman Lesher. All rights reserved.</span><br><span> * Portions Copyright (C) 2005, Anthony Minessale II</span><br><span style="color: hsl(120, 100%, 40%);">+ * Portions Copyright (C) 2021, Naveen Albert</span><br><span> *</span><br><span> * See http://www.asterisk.org for more information about</span><br><span> * the Asterisk project. Please do not directly contact</span><br><span>@@ -22,6 +23,7 @@</span><br><span> *</span><br><span> * \author Tilghman Lesher</span><br><span> * \author Anothony Minessale II</span><br><span style="color: hsl(120, 100%, 40%);">+ * \author Naveen Albert</span><br><span> * \ingroup functions</span><br><span> */</span><br><span> </span><br><span>@@ -152,6 +154,24 @@</span><br><span> <note><para>The replacement only occurs in the output. The original variable is not altered.</para></note></span><br><span> </description></span><br><span> </function></span><br><span style="color: hsl(120, 100%, 40%);">+ <function name="STRBETWEEN" language="en_US"></span><br><span style="color: hsl(120, 100%, 40%);">+ <synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ Inserts a substring between each character in a string.</span><br><span style="color: hsl(120, 100%, 40%);">+ </synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ <syntax></span><br><span style="color: hsl(120, 100%, 40%);">+ <parameter name="varname" required="true" /></span><br><span style="color: hsl(120, 100%, 40%);">+ <parameter name="insert-string" required="true" /></span><br><span style="color: hsl(120, 100%, 40%);">+ </syntax></span><br><span style="color: hsl(120, 100%, 40%);">+ <description></span><br><span style="color: hsl(120, 100%, 40%);">+ <para>Inserts a substring <replaceable>find-string</replaceable> between each character in</span><br><span style="color: hsl(120, 100%, 40%);">+ <replaceable>varname</replaceable>.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ <note><para>The replacement only occurs in the output. The original variable is not altered.</para></note></span><br><span style="color: hsl(120, 100%, 40%);">+ <example title="Add half-second pause between dialed digits"></span><br><span style="color: hsl(120, 100%, 40%);">+ same => n,Set(digits=5551212)</span><br><span style="color: hsl(120, 100%, 40%);">+ same => n,SendDTMF(${STRBETWEEN(digits,w)) ; this will send 5w5w5w1w2w1w2</span><br><span style="color: hsl(120, 100%, 40%);">+ </example></span><br><span style="color: hsl(120, 100%, 40%);">+ </description></span><br><span style="color: hsl(120, 100%, 40%);">+ </function></span><br><span> <function name="PASSTHRU" language="en_US"></span><br><span> <synopsis></span><br><span> Pass the given argument back as a value.</span><br><span>@@ -945,6 +965,53 @@</span><br><span> .read2 = strreplace,</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int strbetween(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int c, origsize;</span><br><span style="color: hsl(120, 100%, 40%);">+ char *varsubstr, *origstr;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_str *str = ast_str_thread_get(&result_buf, 16); /* Holds the data obtained from varname */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_DECLARE_APP_ARGS(args,</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_APP_ARG(varname);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_APP_ARG(insert_string);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_APP_ARG(other); /* Any remining unused arguments */</span><br><span style="color: hsl(120, 100%, 40%);">+ );</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_reset(*buf);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!str) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "Couldn't obtain string\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_STANDARD_APP_ARGS(args, data);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (args.argc != 2 || ast_strlen_zero(args.varname)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_log(LOG_ERROR, "Usage: %s(<varname>,<insert-string>)\n", cmd);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ varsubstr = ast_alloca(strlen(args.varname) + 4);</span><br><span style="color: hsl(120, 100%, 40%);">+ sprintf(varsubstr, "${%s}", args.varname);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_substitute_variables(&str, 0, chan, varsubstr);</span><br><span style="color: hsl(120, 100%, 40%);">+ origstr = ast_str_buffer(str);</span><br><span style="color: hsl(120, 100%, 40%);">+ origsize = strlen(origstr);</span><br><span style="color: hsl(120, 100%, 40%);">+ for (c = 0; c < origsize; c++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_append(buf, len, "%c", origstr[c]);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* no insert after the last character */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (c < (origsize - 1)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_append(buf, len, "%s", args.insert_string);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_custom_function strbetween_function = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .name = "STRBETWEEN",</span><br><span style="color: hsl(120, 100%, 40%);">+ .read2 = strbetween,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static int regex(struct ast_channel *chan, const char *cmd, char *parse, char *buf,</span><br><span> size_t len)</span><br><span> {</span><br><span>@@ -1953,6 +2020,79 @@</span><br><span> </span><br><span> return res;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AST_TEST_DEFINE(test_STRBETWEEN)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int i, res = AST_TEST_PASS;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_channel *chan; /* dummy channel */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_str *str; /* fancy string for holding comparing value */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *test_strings[][5] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ {"0", "w", "0"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"30", "w", "3w0"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"212", "w", "2w1w2"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"212", "55", "2551552"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"212", " ", "2 1 2"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"", "w", ""},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"555", "", "555"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"abcdefg", "_", "a_b_c_d_e_f_g"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"A", "A", "A"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"AA", "B", "ABA"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"AAA", "B", "ABABA"},</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (cmd) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_INIT:</span><br><span style="color: hsl(120, 100%, 40%);">+ info->name = "func_STRBETWEEN";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->category = "/funcs/func_strings/";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->summary = "Test STRBETWEEN function";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->description = "Verify STRBETWEEN behavior";</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_NOT_RUN;</span><br><span style="color: hsl(120, 100%, 40%);">+ case TEST_EXECUTE:</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!(chan = ast_dummy_channel_alloc())) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Unable to allocate dummy channel\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!(str = ast_str_create(64))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Unable to allocate dynamic string buffer\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_release(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < ARRAY_LEN(test_strings); i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+ char tmp[512], tmp2[512] = "";</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ struct ast_var_t *var = ast_var_assign("test_string", test_strings[i][0]);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!var) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Unable to allocate variable\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_free(str);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_release(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+ return AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_LIST_INSERT_HEAD(ast_channel_varshead(chan), var, entries);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (test_strings[i][1]) {</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(tmp, sizeof(tmp), "${STRBETWEEN(%s,%s)}", "test_string", test_strings[i][1]);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ snprintf(tmp, sizeof(tmp), "${STRBETWEEN(%s)}", "test_string");</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_str_substitute_variables(&str, 0, chan, tmp);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (strcmp(test_strings[i][2], ast_str_buffer(str))) {</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_test_status_update(test, "Format string '%s' substituted to '%s'. Expected '%s'.\n", test_strings[i][0], tmp2, test_strings[i][2]);</span><br><span style="color: hsl(120, 100%, 40%);">+ res = AST_TEST_FAIL;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_free(str);</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_channel_release(chan);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return res;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> #endif</span><br><span> </span><br><span> static int unload_module(void)</span><br><span>@@ -1963,11 +2103,13 @@</span><br><span> AST_TEST_UNREGISTER(test_REPLACE);</span><br><span> AST_TEST_UNREGISTER(test_FILTER);</span><br><span> AST_TEST_UNREGISTER(test_STRREPLACE);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_UNREGISTER(test_STRBETWEEN);</span><br><span> res |= ast_custom_function_unregister(&fieldqty_function);</span><br><span> res |= ast_custom_function_unregister(&fieldnum_function);</span><br><span> res |= ast_custom_function_unregister(&filter_function);</span><br><span> res |= ast_custom_function_unregister(&replace_function);</span><br><span> res |= ast_custom_function_unregister(&strreplace_function);</span><br><span style="color: hsl(120, 100%, 40%);">+ res |= ast_custom_function_unregister(&strbetween_function);</span><br><span> res |= ast_custom_function_unregister(&listfilter_function);</span><br><span> res |= ast_custom_function_unregister(®ex_function);</span><br><span> res |= ast_custom_function_unregister(&array_function);</span><br><span>@@ -2000,11 +2142,13 @@</span><br><span> AST_TEST_REGISTER(test_REPLACE);</span><br><span> AST_TEST_REGISTER(test_FILTER);</span><br><span> AST_TEST_REGISTER(test_STRREPLACE);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_REGISTER(test_STRBETWEEN);</span><br><span> res |= ast_custom_function_register(&fieldqty_function);</span><br><span> res |= ast_custom_function_register(&fieldnum_function);</span><br><span> res |= ast_custom_function_register(&filter_function);</span><br><span> res |= ast_custom_function_register(&replace_function);</span><br><span> res |= ast_custom_function_register(&strreplace_function);</span><br><span style="color: hsl(120, 100%, 40%);">+ res |= ast_custom_function_register(&strbetween_function);</span><br><span> res |= ast_custom_function_register(&listfilter_function);</span><br><span> res |= ast_custom_function_register(®ex_function);</span><br><span> res |= ast_custom_function_register(&array_function);</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/16463">change 16463</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.asterisk.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.asterisk.org/c/asterisk/+/16463"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 16 </div>
<div style="display:none"> Gerrit-Change-Id: Ice23009d4a8e9bb9718d2b2301d405567087d258 </div>
<div style="display:none"> Gerrit-Change-Number: 16463 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: N A <mail@interlinked.x10host.com> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>