<p>N A has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/16473">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/73/16473/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(&regex_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(&regex_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/+/16473">change 16473</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/+/16473"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 19 </div>
<div style="display:none"> Gerrit-Change-Id: Ice23009d4a8e9bb9718d2b2301d405567087d258 </div>
<div style="display:none"> Gerrit-Change-Number: 16473 </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>