Use the same delimited character as the FILTER function in FIELDQTY and CUT.
[asterisk/asterisk.git] / funcs / func_math.c
index 4dbfac8..70882d1 100644 (file)
@@ -22,6 +22,8 @@
  *
  * \author Andy Powell
  * \author Mark Spencer <markster@digium.com>
+ *
+ * \ingroup functions
  */
 
 #include "asterisk.h"
@@ -51,6 +53,9 @@ enum TypeOfFunctions {
        POWFUNCTION,
        SHLEFTFUNCTION,
        SHRIGHTFUNCTION,
+       BITWISEANDFUNCTION,
+       BITWISEXORFUNCTION,
+       BITWISEORFUNCTION,
        GTFUNCTION,
        LTFUNCTION,
        GTEFUNCTION,
@@ -68,13 +73,14 @@ enum TypeOfResult {
 static int math(struct ast_channel *chan, const char *cmd, char *parse,
                char *buf, size_t len)
 {
-       float fnum1;
-       float fnum2;
-       float ftmp = 0;
+       double fnum1;
+       double fnum2;
+       double ftmp = 0;
        char *op;
        int iaction = -1;
        int type_of_result = FLOAT_RESULT;
        char *mvalue1, *mvalue2 = NULL, *mtype_of_result;
+       int negvalue1 = 0;
        AST_DECLARE_APP_ARGS(args,
                             AST_APP_ARG(argv0);
                             AST_APP_ARG(argv1);
@@ -94,13 +100,12 @@ static int math(struct ast_channel *chan, const char *cmd, char *parse,
 
        mvalue1 = args.argv0;
 
-       if ((op = strchr(mvalue1, '+'))) {
-               iaction = ADDFUNCTION;
-               *op = '\0';
-       } else if ((op = strchr(mvalue1, '-'))) {
-               iaction = SUBTRACTFUNCTION;
-               *op = '\0';
-       } else if ((op = strchr(mvalue1, '*'))) {
+       if (mvalue1[0] == '-') {
+               negvalue1 = 1;
+               mvalue1++;
+       }
+
+       if ((op = strchr(mvalue1, '*'))) {
                iaction = MULTIPLYFUNCTION;
                *op = '\0';
        } else if ((op = strchr(mvalue1, '/'))) {
@@ -112,6 +117,18 @@ static int math(struct ast_channel *chan, const char *cmd, char *parse,
        } else if ((op = strchr(mvalue1, '^'))) {
                iaction = POWFUNCTION;
                *op = '\0';
+       } else if ((op = strstr(mvalue1, "AND"))) {
+               iaction = BITWISEANDFUNCTION;
+               op += 3;
+               *op = '\0';
+       } else if ((op = strstr(mvalue1, "XOR"))) {
+               iaction = BITWISEXORFUNCTION;
+               op += 3;
+               *op = '\0';
+       } else if ((op = strstr(mvalue1, "OR"))) {
+               iaction = BITWISEORFUNCTION;
+               op += 2;
+               *op = '\0';
        } else if ((op = strchr(mvalue1, '>'))) {
                iaction = GTFUNCTION;
                *op = '\0';
@@ -139,6 +156,12 @@ static int math(struct ast_channel *chan, const char *cmd, char *parse,
                        iaction = EQFUNCTION;
                } else
                        op = NULL;
+       } else if ((op = strchr(mvalue1, '+'))) {
+               iaction = ADDFUNCTION;
+               *op = '\0';
+       } else if ((op = strchr(mvalue1, '-'))) { /* subtraction MUST always be last, in case we have a negative first number */
+               iaction = SUBTRACTFUNCTION;
+               *op = '\0';
        }
 
        if (op)
@@ -172,16 +195,19 @@ static int math(struct ast_channel *chan, const char *cmd, char *parse,
                return -1;
        }
 
-       if (sscanf(mvalue1, "%f", &fnum1) != 1) {
+       if (sscanf(mvalue1, "%lf", &fnum1) != 1) {
                ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue1);
                return -1;
        }
 
-       if (sscanf(mvalue2, "%f", &fnum2) != 1) {
+       if (sscanf(mvalue2, "%lf", &fnum2) != 1) {
                ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue2);
                return -1;
        }
 
+       if (negvalue1)
+               fnum1 = 0 - fnum1;
+
        switch (iaction) {
        case ADDFUNCTION:
                ftmp = fnum1 + fnum2;
@@ -226,6 +252,27 @@ static int math(struct ast_channel *chan, const char *cmd, char *parse,
                        ftmp = (inum1 >> inum2);
                        break;
                }
+       case BITWISEANDFUNCTION:
+               {
+                       int inum1 = fnum1;
+                       int inum2 = fnum2;
+                       ftmp = (inum1 & inum2);
+                       break;
+               }
+       case BITWISEXORFUNCTION:
+               {
+                       int inum1 = fnum1;
+                       int inum2 = fnum2;
+                       ftmp = (inum1 ^ inum2);
+                       break;
+               }
+       case BITWISEORFUNCTION:
+               {
+                       int inum1 = fnum1;
+                       int inum2 = fnum2;
+                       ftmp = (inum1 | inum2);
+                       break;
+               }
        case GTFUNCTION:
                ast_copy_string(buf, (fnum1 > fnum2) ? "TRUE" : "FALSE", len);
                break;
@@ -267,7 +314,7 @@ static struct ast_custom_function math_function = {
        .synopsis = "Performs Mathematical Functions",
        .syntax = "MATH(<number1><op><number2>[,<type_of_result>])",
        .desc = "Perform calculation on number1 to number2. Valid ops are: \n"
-               "    +,-,/,*,%,<<,>>,^,<,>,>=,<=,==\n"
+               "    +,-,/,*,%,<<,>>,^,AND,OR,XOR,<,>,>=,<=,==\n"
                "and behave as their C equivalents.\n"
                "<type_of_result> - wanted type of result:\n"
                "       f, float - float(default)\n"