<p>Friendly Automation <strong>submitted</strong> this change.</p><p><a href="https://gerrit.asterisk.org/c/asterisk/+/15905">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Joshua Colp: Looks good to me, but someone else must approve
  Kevin Harwell: Looks good to me, approved
  Benjamin Keith Ford: Looks good to me, but someone else must approve
  George Joseph: Looks good to me, but someone else must approve
  Friendly Automation: Approved for Submit

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">func_math: Three new dialplan functions<br><br>Introduces three new dialplan functions, MIN and MAX,<br>which can be used to calculate the minimum or<br>maximum of up to two numbers, and ABS, an absolute<br>value function.<br><br>ASTERISK-29431<br><br>Change-Id: I2bda9269d18f9d54833c85e48e41fce0e0ce4d8d<br>---<br>A doc/CHANGES-staging/func_min_max.txt<br>M funcs/func_math.c<br>2 files changed, 177 insertions(+), 0 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/doc/CHANGES-staging/func_min_max.txt b/doc/CHANGES-staging/func_min_max.txt</span><br><span>new file mode 100644</span><br><span>index 0000000..df2b665</span><br><span>--- /dev/null</span><br><span>+++ b/doc/CHANGES-staging/func_min_max.txt</span><br><span>@@ -0,0 +1,4 @@</span><br><span style="color: hsl(120, 100%, 40%);">+Subject: func_math: Three new dialplan functions</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Introduce three new functions, MIN, MAX, and ABS, which can be used to</span><br><span style="color: hsl(120, 100%, 40%);">+obtain the minimum or maximum of up to two integers or absolute value.</span><br><span>diff --git a/funcs/func_math.c b/funcs/func_math.c</span><br><span>index 6fc7255..b8a6eb6 100644</span><br><span>--- a/funcs/func_math.c</span><br><span>+++ b/funcs/func_math.c</span><br><span>@@ -5,6 +5,7 @@</span><br><span>  *</span><br><span>  * Updated by Mark Spencer <markster@digium.com></span><br><span>  * Updated by Nir Simionovich <nirs@greenfieldtech.net></span><br><span style="color: hsl(120, 100%, 40%);">+ * Updated by Naveen Albert <asterisk@phreaknet.org></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>@@ -24,6 +25,7 @@</span><br><span>  * \author Andy Powell</span><br><span>  * \author Mark Spencer <markster@digium.com></span><br><span>  * \author Nir Simionovich <nirs@greenfieldtech.net></span><br><span style="color: hsl(120, 100%, 40%);">+ * \author Naveen Albert <asterisk@phreaknet.org></span><br><span>  *</span><br><span>  * \ingroup functions</span><br><span>  */</span><br><span>@@ -40,6 +42,7 @@</span><br><span> #include "asterisk/channel.h"</span><br><span> #include "asterisk/pbx.h"</span><br><span> #include "asterisk/utils.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "asterisk/conversions.h"</span><br><span> #include "asterisk/app.h"</span><br><span> #include "asterisk/config.h"</span><br><span> #include "asterisk/test.h"</span><br><span>@@ -105,6 +108,47 @@</span><br><span>                      <para>Note: DEC(${MyVAR}) - Is wrong, as DEC expects the variable name, not its value</para></span><br><span>             </description></span><br><span>         </function></span><br><span style="color: hsl(120, 100%, 40%);">+     <function name="MIN" language="en_US"></span><br><span style="color: hsl(120, 100%, 40%);">+              <synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                      Returns the minimum of two numbers.</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="num1" /></span><br><span style="color: hsl(120, 100%, 40%);">+                     <parameter name="num2" /></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>Returns the minimum of two numbers <replaceable>num1</replaceable> and <replaceable>num2</replaceable>.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                      <para>Example:  Set(min=${MIN(7,4)});</span><br><span style="color: hsl(120, 100%, 40%);">+                   Sets the min variable equal to 4.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                </description></span><br><span style="color: hsl(120, 100%, 40%);">+  </function></span><br><span style="color: hsl(120, 100%, 40%);">+     <function name="MAX" language="en_US"></span><br><span style="color: hsl(120, 100%, 40%);">+              <synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                      Returns the maximum of two numbers.</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="num1" /></span><br><span style="color: hsl(120, 100%, 40%);">+                     <parameter name="num2" /></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>Returns the maximum of two numbers <replaceable>num1</replaceable> and <replaceable>num2</replaceable>.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                      <para>Example:  Set(max=${MAX(4,7)});</span><br><span style="color: hsl(120, 100%, 40%);">+                   Sets the max variable equal to 7.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                </description></span><br><span style="color: hsl(120, 100%, 40%);">+  </function></span><br><span style="color: hsl(120, 100%, 40%);">+     <function name="ABS" language="en_US"></span><br><span style="color: hsl(120, 100%, 40%);">+              <synopsis></span><br><span style="color: hsl(120, 100%, 40%);">+                      Returns absolute value of a number.</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="num" /></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>Returns the absolute value of a number <replaceable>num</replaceable>.</para></span><br><span style="color: hsl(120, 100%, 40%);">+                   <para>Example:  Set(absval=${ABS(-13)});</span><br><span style="color: hsl(120, 100%, 40%);">+                        Sets the absval variable equal to 13.</para></span><br><span style="color: hsl(120, 100%, 40%);">+            </description></span><br><span style="color: hsl(120, 100%, 40%);">+  </function></span><br><span>  ***/</span><br><span> </span><br><span> enum TypeOfFunctions {</span><br><span>@@ -444,6 +488,111 @@</span><br><span>     return ret;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static int acf_min_exec(struct ast_channel *chan, const char *cmd,</span><br><span style="color: hsl(120, 100%, 40%);">+                       char *parse, char *buffer, size_t buflen)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ double num1, num2, response_num = 0;</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(num1);</span><br><span style="color: hsl(120, 100%, 40%);">+                            AST_APP_ARG(num2);</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, parse);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(args.num1) && ast_strlen_zero(args.num2)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_log(LOG_ERROR, "Missing argument for number(s).");</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%);">+   if (ast_strlen_zero(args.num1)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             response_num = -1; /* couldn't read num1 successfully */</span><br><span style="color: hsl(120, 100%, 40%);">+  } else if (sscanf(args.num1, "%30lf", &num1) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_log(LOG_WARNING, "'%s' is not a valid number\n", args.num1);</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%);">+   if (ast_strlen_zero(args.num2)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             num2 = num1; /* num1 must be a valid integer here */</span><br><span style="color: hsl(120, 100%, 40%);">+  } else if (sscanf(args.num2, "%30lf", &num2) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_log(LOG_WARNING, "'%s' is not a valid number\n", args.num2);</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%);">+   if (response_num == -1) { /* could only read num2 */</span><br><span style="color: hsl(120, 100%, 40%);">+          response_num = num2;</span><br><span style="color: hsl(120, 100%, 40%);">+  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              response_num = (num1 > num2) ? num2 : num1;</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_debug(1, "%f is the minimum of [%f,%f]\n", response_num, num1, num2);</span><br><span style="color: hsl(120, 100%, 40%);">+   snprintf(buffer, buflen, "%f", response_num);</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 acf_max_exec(struct ast_channel *chan, const char *cmd,</span><br><span style="color: hsl(120, 100%, 40%);">+                     char *parse, char *buffer, size_t buflen)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ double num1, num2, response_num = 0;</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(num1);</span><br><span style="color: hsl(120, 100%, 40%);">+                            AST_APP_ARG(num2);</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, parse);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(args.num1) && ast_strlen_zero(args.num2)) {</span><br><span style="color: hsl(120, 100%, 40%);">+               ast_log(LOG_ERROR, "Missing argument for number(s).");</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%);">+   if (ast_strlen_zero(args.num1)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             response_num = -1; /* couldn't read num1 successfully */</span><br><span style="color: hsl(120, 100%, 40%);">+  } else if (sscanf(args.num1, "%30lf", &num1) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_log(LOG_WARNING, "'%s' is not a valid number\n", args.num1);</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%);">+   if (ast_strlen_zero(args.num2)) {</span><br><span style="color: hsl(120, 100%, 40%);">+             num2 = num1; /* num1 must be a valid integer here */</span><br><span style="color: hsl(120, 100%, 40%);">+  } else if (sscanf(args.num2, "%30lf", &num2) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+            ast_log(LOG_WARNING, "'%s' is not a valid number\n", args.num2);</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%);">+   if (response_num == -1) { /* could only read num2 */</span><br><span style="color: hsl(120, 100%, 40%);">+          response_num = num2;</span><br><span style="color: hsl(120, 100%, 40%);">+  } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              response_num = (num1 < num2) ? num2 : num1;</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_debug(1, "%f is the maximum of [%f,%f]\n", response_num, num1, num2);</span><br><span style="color: hsl(120, 100%, 40%);">+   snprintf(buffer, buflen, "%f", response_num);</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 acf_abs_exec(struct ast_channel *chan, const char *cmd,</span><br><span style="color: hsl(120, 100%, 40%);">+                     char *parse, char *buffer, size_t buflen)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ double num1, response_num;</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(num1);</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, parse);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (ast_strlen_zero(args.num1) || sscanf(args.num1, "%30lf", &num1) != 1) {</span><br><span style="color: hsl(120, 100%, 40%);">+             ast_log(LOG_WARNING, "Bad or missing argument for number: %s", args.num1);</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%);">+   response_num = fabs(num1);</span><br><span style="color: hsl(120, 100%, 40%);">+    ast_debug(1, "%f is the absolute value of %f\n", response_num, num1);</span><br><span style="color: hsl(120, 100%, 40%);">+       snprintf(buffer, buflen, "%f", response_num);</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> </span><br><span> static struct ast_custom_function math_function = {</span><br><span>      .name = "MATH",</span><br><span>@@ -460,6 +609,24 @@</span><br><span>     .read = crement_function_read,</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static struct ast_custom_function acf_min = {</span><br><span style="color: hsl(120, 100%, 40%);">+       .name = "MIN",</span><br><span style="color: hsl(120, 100%, 40%);">+      .read = acf_min_exec,</span><br><span style="color: hsl(120, 100%, 40%);">+ .read_max = 12,</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 acf_max = {</span><br><span style="color: hsl(120, 100%, 40%);">+  .name = "MAX",</span><br><span style="color: hsl(120, 100%, 40%);">+      .read = acf_max_exec,</span><br><span style="color: hsl(120, 100%, 40%);">+ .read_max = 12,</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 acf_abs = {</span><br><span style="color: hsl(120, 100%, 40%);">+  .name = "ABS",</span><br><span style="color: hsl(120, 100%, 40%);">+      .read = acf_abs_exec,</span><br><span style="color: hsl(120, 100%, 40%);">+ .read_max = 12,</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #ifdef TEST_FRAMEWORK</span><br><span> AST_TEST_DEFINE(test_MATH_function)</span><br><span> {</span><br><span>@@ -518,6 +685,9 @@</span><br><span>     res |= ast_custom_function_unregister(&math_function);</span><br><span>   res |= ast_custom_function_unregister(&increment_function);</span><br><span>      res |= ast_custom_function_unregister(&decrement_function);</span><br><span style="color: hsl(120, 100%, 40%);">+       res |= ast_custom_function_unregister(&acf_min);</span><br><span style="color: hsl(120, 100%, 40%);">+  res |= ast_custom_function_unregister(&acf_max);</span><br><span style="color: hsl(120, 100%, 40%);">+  res |= ast_custom_function_unregister(&acf_abs);</span><br><span>         AST_TEST_UNREGISTER(test_MATH_function);</span><br><span> </span><br><span>         return res;</span><br><span>@@ -530,6 +700,9 @@</span><br><span>    res |= ast_custom_function_register(&math_function);</span><br><span>     res |= ast_custom_function_register(&increment_function);</span><br><span>        res |= ast_custom_function_register(&decrement_function);</span><br><span style="color: hsl(120, 100%, 40%);">+ res |= ast_custom_function_register(&acf_min);</span><br><span style="color: hsl(120, 100%, 40%);">+    res |= ast_custom_function_register(&acf_max);</span><br><span style="color: hsl(120, 100%, 40%);">+    res |= ast_custom_function_register(&acf_abs);</span><br><span>   AST_TEST_REGISTER(test_MATH_function);</span><br><span> </span><br><span>   return res;</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.asterisk.org/c/asterisk/+/15905">change 15905</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/+/15905"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: asterisk </div>
<div style="display:none"> Gerrit-Branch: 18 </div>
<div style="display:none"> Gerrit-Change-Id: I2bda9269d18f9d54833c85e48e41fce0e0ce4d8d </div>
<div style="display:none"> Gerrit-Change-Number: 15905 </div>
<div style="display:none"> Gerrit-PatchSet: 10 </div>
<div style="display:none"> Gerrit-Owner: N A <mail@interlinked.x10host.com> </div>
<div style="display:none"> Gerrit-Reviewer: Benjamin Keith Ford <bford@digium.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-Reviewer: Kevin Harwell <kharwell@digium.com> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>