<p>Friendly Automation <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/19292">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span></span><br></pre><div style="white-space:pre-wrap">Approvals:
Joshua Colp: Looks good to me, but someone else must approve
George Joseph: Looks good to me, approved
Friendly Automation: Approved for Submit
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">func_strings: Add trim functions.<br><br>Adds TRIM, LTRIM, and RTRIM, which can be used<br>for trimming leading and trailing whitespace<br>from strings.<br><br>ASTERISK-30222 #close<br><br>Change-Id: I50fb0c40726d044a7a41939fa9026f3da4872554<br>---<br>A doc/CHANGES-staging/func_strings_trim.txt<br>M funcs/func_strings.c<br>2 files changed, 205 insertions(+), 1 deletion(-)<br><br></pre>
<pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/doc/CHANGES-staging/func_strings_trim.txt b/doc/CHANGES-staging/func_strings_trim.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..ade7a4b</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/func_strings_trim.txt</span><br><span>@@ -0,0 +1,5 @@</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%);">+Three new functions, TRIM, LTRIM, and RTRIM, are</span><br><span style="color: hsl(120, 100%, 40%);">+now available for trimming leading and trailing</span><br><span style="color: hsl(120, 100%, 40%);">+whitespace.</span><br><span>diff --git a/funcs/func_strings.c b/funcs/func_strings.c</span><br><span>index 77cdc99..598e6a4 100644</span><br><span>--- a/funcs/func_strings.c</span><br><span>+++ b/funcs/func_strings.c</span><br><span>@@ -4,7 +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(0, 100%, 40%);">- * Portions Copyright (C) 2021, Naveen Albert</span><br><span style="color: hsl(120, 100%, 40%);">+ * Portions Copyright (C) 2021, 2022, 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>@@ -183,6 +183,51 @@</span><br><span> </example></span><br><span> </description></span><br><span> </function></span><br><span style="color: hsl(120, 100%, 40%);">+ <function name="TRIM" language="en_US"></span><br><span style="color: hsl(120, 100%, 40%);">+ <synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ Trim leading and trailing whitespace 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="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>Replaces all leading and trailing whitespace in the provided string.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </description></span><br><span style="color: hsl(120, 100%, 40%);">+ <see-also></span><br><span style="color: hsl(120, 100%, 40%);">+ <ref type="function">LTRIM</ref></span><br><span style="color: hsl(120, 100%, 40%);">+ <ref type="function">RTRIM</ref></span><br><span style="color: hsl(120, 100%, 40%);">+ </see-also></span><br><span style="color: hsl(120, 100%, 40%);">+ </function></span><br><span style="color: hsl(120, 100%, 40%);">+ <function name="LTRIM" language="en_US"></span><br><span style="color: hsl(120, 100%, 40%);">+ <synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ Trim leading whitespace 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="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>Replaces all leading whitespace in the provided string.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </description></span><br><span style="color: hsl(120, 100%, 40%);">+ <see-also></span><br><span style="color: hsl(120, 100%, 40%);">+ <ref type="function">TRIM</ref></span><br><span style="color: hsl(120, 100%, 40%);">+ <ref type="function">RTRIM</ref></span><br><span style="color: hsl(120, 100%, 40%);">+ </see-also></span><br><span style="color: hsl(120, 100%, 40%);">+ </function></span><br><span style="color: hsl(120, 100%, 40%);">+ <function name="RTRIM" language="en_US"></span><br><span style="color: hsl(120, 100%, 40%);">+ <synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+ Trim trailing whitespace 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="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>Replaces all trailing whitespace in the provided string.</para></span><br><span style="color: hsl(120, 100%, 40%);">+ </description></span><br><span style="color: hsl(120, 100%, 40%);">+ <see-also></span><br><span style="color: hsl(120, 100%, 40%);">+ <ref type="function">TRIM</ref></span><br><span style="color: hsl(120, 100%, 40%);">+ <ref type="function">LTRIM</ref></span><br><span style="color: hsl(120, 100%, 40%);">+ </see-also></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>@@ -1045,6 +1090,84 @@</span><br><span> .read2 = strbetween,</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define ltrim(s) while (isspace(*s)) s++;</span><br><span style="color: hsl(120, 100%, 40%);">+#define rtrim(s) { \</span><br><span style="color: hsl(120, 100%, 40%);">+ if (s) { \</span><br><span style="color: hsl(120, 100%, 40%);">+ char *back = s + strlen(s); \</span><br><span style="color: hsl(120, 100%, 40%);">+ while (back != s && isspace(*--back)); \</span><br><span style="color: hsl(120, 100%, 40%);">+ if (*s) { \</span><br><span style="color: hsl(120, 100%, 40%);">+ *(back + 1) = '\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%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int function_trim(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *c;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(data)) {</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%);">+ c = ast_strdupa(data);</span><br><span style="color: hsl(120, 100%, 40%);">+ ltrim(c);</span><br><span style="color: hsl(120, 100%, 40%);">+ rtrim(c);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_copy_string(buf, c, len);</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 int function_ltrim(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *c;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(data)) {</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%);">+ c = data;</span><br><span style="color: hsl(120, 100%, 40%);">+ ltrim(c);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_copy_string(buf, c, len);</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 int function_rtrim(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t len)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ char *c;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(data)) {</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%);">+ c = ast_strdupa(data);</span><br><span style="color: hsl(120, 100%, 40%);">+ rtrim(c);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ast_copy_string(buf, c, len);</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%);">+#undef ltrim</span><br><span style="color: hsl(120, 100%, 40%);">+#undef rtrim</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_custom_function trim_function = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .name = "TRIM",</span><br><span style="color: hsl(120, 100%, 40%);">+ .read = function_trim,</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 ltrim_function = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .name = "LTRIM",</span><br><span style="color: hsl(120, 100%, 40%);">+ .read = function_ltrim,</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 rtrim_function = {</span><br><span style="color: hsl(120, 100%, 40%);">+ .name = "RTRIM",</span><br><span style="color: hsl(120, 100%, 40%);">+ .read = function_rtrim,</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>@@ -2126,6 +2249,59 @@</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_TRIM)</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%);">+ {"TRIM", " abcd ", "abcd"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"LTRIM", " abcd ", "abcd "},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"RTRIM", " abcd ", " abcd"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"TRIM", "abcd", "abcd"},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"TRIM", " a b c d ", "a b c d"},</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_TRIM";</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 TRIM functions";</span><br><span style="color: hsl(120, 100%, 40%);">+ info->description = "Verify TRIM 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%);">+ snprintf(tmp, sizeof(tmp), "${%s(%s)}", test_strings[i][0], test_strings[i][1]);</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>@@ -2137,6 +2313,7 @@</span><br><span> AST_TEST_UNREGISTER(test_FILTER);</span><br><span> AST_TEST_UNREGISTER(test_STRREPLACE);</span><br><span> AST_TEST_UNREGISTER(test_STRBETWEEN);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_UNREGISTER(test_TRIM);</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>@@ -2163,6 +2340,9 @@</span><br><span> res |= ast_custom_function_unregister(&push_function);</span><br><span> res |= ast_custom_function_unregister(&unshift_function);</span><br><span> res |= ast_custom_function_unregister(&passthru_function);</span><br><span style="color: hsl(120, 100%, 40%);">+ res |= ast_custom_function_unregister(&trim_function);</span><br><span style="color: hsl(120, 100%, 40%);">+ res |= ast_custom_function_unregister(<rim_function);</span><br><span style="color: hsl(120, 100%, 40%);">+ res |= ast_custom_function_unregister(&rtrim_function);</span><br><span> </span><br><span> return res;</span><br><span> }</span><br><span>@@ -2176,6 +2356,7 @@</span><br><span> AST_TEST_REGISTER(test_FILTER);</span><br><span> AST_TEST_REGISTER(test_STRREPLACE);</span><br><span> AST_TEST_REGISTER(test_STRBETWEEN);</span><br><span style="color: hsl(120, 100%, 40%);">+ AST_TEST_REGISTER(test_TRIM);</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>@@ -2202,6 +2383,9 @@</span><br><span> res |= ast_custom_function_register(&push_function);</span><br><span> res |= ast_custom_function_register(&unshift_function);</span><br><span> res |= ast_custom_function_register(&passthru_function);</span><br><span style="color: hsl(120, 100%, 40%);">+ res |= ast_custom_function_register(&trim_function);</span><br><span style="color: hsl(120, 100%, 40%);">+ res |= ast_custom_function_register(<rim_function);</span><br><span style="color: hsl(120, 100%, 40%);">+ res |= ast_custom_function_register(&rtrim_function);</span><br><span> </span><br><span> return res;</span><br><span> }</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/19292">change 19292</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/+/19292"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 20 </div>
<div style="display:none"> Gerrit-Change-Id: I50fb0c40726d044a7a41939fa9026f3da4872554 </div>
<div style="display:none"> Gerrit-Change-Number: 19292 </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-Reviewer: Friendly Automation </div>
<div style="display:none"> Gerrit-Reviewer: George Joseph <gjoseph@digium.com> </div>
<div style="display:none"> Gerrit-Reviewer: Joshua Colp <jcolp@sangoma.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>