Wed Aug 18 22:33:52 2010

Asterisk developer's documentation


func_math.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 2004 - 2006, Andy Powell 
00005  *
00006  * Updated by Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief Math related dialplan function
00022  *
00023  * \author Andy Powell
00024  * \author Mark Spencer <markster@digium.com>
00025  *
00026  * \ingroup functions
00027  */
00028 
00029 #include "asterisk.h"
00030 
00031 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 244333 $")
00032 
00033 #include <math.h>
00034 
00035 #include "asterisk/module.h"
00036 #include "asterisk/channel.h"
00037 #include "asterisk/pbx.h"
00038 #include "asterisk/utils.h"
00039 #include "asterisk/app.h"
00040 #include "asterisk/config.h"
00041 
00042 enum TypeOfFunctions {
00043    ADDFUNCTION,
00044    DIVIDEFUNCTION,
00045    MULTIPLYFUNCTION,
00046    SUBTRACTFUNCTION,
00047    MODULUSFUNCTION,
00048    POWFUNCTION,
00049    SHLEFTFUNCTION,
00050    SHRIGHTFUNCTION,
00051    BITWISEANDFUNCTION,
00052    BITWISEXORFUNCTION,
00053    BITWISEORFUNCTION,
00054    GTFUNCTION,
00055    LTFUNCTION,
00056    GTEFUNCTION,
00057    LTEFUNCTION,
00058    EQFUNCTION
00059 };
00060 
00061 enum TypeOfResult {
00062    FLOAT_RESULT,
00063    INT_RESULT,
00064    HEX_RESULT,
00065    CHAR_RESULT
00066 };
00067 
00068 static int math(struct ast_channel *chan, const char *cmd, char *parse,
00069       char *buf, size_t len)
00070 {
00071    double fnum1;
00072    double fnum2;
00073    double ftmp = 0;
00074    char *op;
00075    int iaction = -1;
00076    int type_of_result = FLOAT_RESULT;
00077    char *mvalue1, *mvalue2 = NULL, *mtype_of_result;
00078    int negvalue1 = 0;
00079    AST_DECLARE_APP_ARGS(args,
00080               AST_APP_ARG(argv0);
00081               AST_APP_ARG(argv1);
00082    );
00083 
00084    if (ast_strlen_zero(parse)) {
00085       ast_log(LOG_WARNING, "Syntax: MATH(<number1><op><number 2>[,<type_of_result>]) - missing argument!\n");
00086       return -1;
00087    }
00088 
00089    AST_STANDARD_APP_ARGS(args, parse);
00090 
00091    if (args.argc < 1) {
00092       ast_log(LOG_WARNING, "Syntax: MATH(<number1><op><number 2>[,<type_of_result>]) - missing argument!\n");
00093       return -1;
00094    }
00095 
00096    mvalue1 = args.argv0;
00097 
00098    if (mvalue1[0] == '-') {
00099       negvalue1 = 1;
00100       mvalue1++;
00101    }
00102 
00103    if ((op = strchr(mvalue1, '*'))) {
00104       iaction = MULTIPLYFUNCTION;
00105       *op = '\0';
00106    } else if ((op = strchr(mvalue1, '/'))) {
00107       iaction = DIVIDEFUNCTION;
00108       *op = '\0';
00109    } else if ((op = strchr(mvalue1, '%'))) {
00110       iaction = MODULUSFUNCTION;
00111       *op = '\0';
00112    } else if ((op = strchr(mvalue1, '^'))) {
00113       iaction = POWFUNCTION;
00114       *op = '\0';
00115    } else if ((op = strstr(mvalue1, "AND"))) {
00116       iaction = BITWISEANDFUNCTION;
00117       *op = '\0';
00118       op += 2;
00119    } else if ((op = strstr(mvalue1, "XOR"))) {
00120       iaction = BITWISEXORFUNCTION;
00121       *op = '\0';
00122       op += 2;
00123    } else if ((op = strstr(mvalue1, "OR"))) {
00124       iaction = BITWISEORFUNCTION;
00125       *op = '\0';
00126       ++op;
00127    } else if ((op = strchr(mvalue1, '>'))) {
00128       iaction = GTFUNCTION;
00129       *op = '\0';
00130       if (*(op + 1) == '=') {
00131          iaction = GTEFUNCTION;
00132          ++op;
00133       } else if (*(op + 1) == '>') {
00134          iaction = SHRIGHTFUNCTION;
00135          ++op;
00136       }
00137    } else if ((op = strchr(mvalue1, '<'))) {
00138       iaction = LTFUNCTION;
00139       *op = '\0';
00140       if (*(op + 1) == '=') {
00141          iaction = LTEFUNCTION;
00142          ++op;
00143       } else if (*(op + 1) == '<') {
00144          iaction = SHLEFTFUNCTION;
00145          ++op;
00146       }
00147    } else if ((op = strchr(mvalue1, '='))) {
00148       *op = '\0';
00149       if (*(op + 1) == '=') {
00150          iaction = EQFUNCTION;
00151          ++op;
00152       } else
00153          op = NULL;
00154    } else if ((op = strchr(mvalue1, '+'))) {
00155       iaction = ADDFUNCTION;
00156       *op = '\0';
00157    } else if ((op = strchr(mvalue1, '-'))) { /* subtraction MUST always be last, in case we have a negative second number */
00158       iaction = SUBTRACTFUNCTION;
00159       *op = '\0';
00160    }
00161 
00162    if (op)
00163       mvalue2 = op + 1;
00164 
00165    /* detect wanted type of result */
00166    mtype_of_result = args.argv1;
00167    if (mtype_of_result) {
00168       if (!strcasecmp(mtype_of_result, "float")
00169           || !strcasecmp(mtype_of_result, "f"))
00170          type_of_result = FLOAT_RESULT;
00171       else if (!strcasecmp(mtype_of_result, "int")
00172           || !strcasecmp(mtype_of_result, "i"))
00173          type_of_result = INT_RESULT;
00174       else if (!strcasecmp(mtype_of_result, "hex")
00175           || !strcasecmp(mtype_of_result, "h"))
00176          type_of_result = HEX_RESULT;
00177       else if (!strcasecmp(mtype_of_result, "char")
00178           || !strcasecmp(mtype_of_result, "c"))
00179          type_of_result = CHAR_RESULT;
00180       else {
00181          ast_log(LOG_WARNING, "Unknown type of result requested '%s'.\n",
00182                mtype_of_result);
00183          return -1;
00184       }
00185    }
00186 
00187    if (!mvalue1 || !mvalue2) {
00188       ast_log(LOG_WARNING,
00189             "Supply all the parameters - just this once, please\n");
00190       return -1;
00191    }
00192 
00193    if (sscanf(mvalue1, "%30lf", &fnum1) != 1) {
00194       ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue1);
00195       return -1;
00196    }
00197 
00198    if (sscanf(mvalue2, "%30lf", &fnum2) != 1) {
00199       ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue2);
00200       return -1;
00201    }
00202 
00203    if (negvalue1)
00204       fnum1 = 0 - fnum1;
00205 
00206    switch (iaction) {
00207    case ADDFUNCTION:
00208       ftmp = fnum1 + fnum2;
00209       break;
00210    case DIVIDEFUNCTION:
00211       if (fnum2 <= 0)
00212          ftmp = 0;         /* can't do a divide by 0 */
00213       else
00214          ftmp = (fnum1 / fnum2);
00215       break;
00216    case MULTIPLYFUNCTION:
00217       ftmp = (fnum1 * fnum2);
00218       break;
00219    case SUBTRACTFUNCTION:
00220       ftmp = (fnum1 - fnum2);
00221       break;
00222    case MODULUSFUNCTION:
00223       {
00224          int inum1 = fnum1;
00225          int inum2 = fnum2;
00226 
00227          if (inum2 == 0) {
00228             ftmp = 0;
00229          } else {
00230             ftmp = (inum1 % inum2);
00231          }
00232 
00233          break;
00234       }
00235    case POWFUNCTION:
00236       ftmp = pow(fnum1, fnum2);
00237       break;
00238    case SHLEFTFUNCTION:
00239       {
00240          int inum1 = fnum1;
00241          int inum2 = fnum2;
00242 
00243          ftmp = (inum1 << inum2);
00244          break;
00245       }
00246    case SHRIGHTFUNCTION:
00247       {
00248          int inum1 = fnum1;
00249          int inum2 = fnum2;
00250 
00251          ftmp = (inum1 >> inum2);
00252          break;
00253       }
00254    case BITWISEANDFUNCTION:
00255       {
00256          int inum1 = fnum1;
00257          int inum2 = fnum2;
00258          ftmp = (inum1 & inum2);
00259          break;
00260       }
00261    case BITWISEXORFUNCTION:
00262       {
00263          int inum1 = fnum1;
00264          int inum2 = fnum2;
00265          ftmp = (inum1 ^ inum2);
00266          break;
00267       }
00268    case BITWISEORFUNCTION:
00269       {
00270          int inum1 = fnum1;
00271          int inum2 = fnum2;
00272          ftmp = (inum1 | inum2);
00273          break;
00274       }
00275    case GTFUNCTION:
00276       ast_copy_string(buf, (fnum1 > fnum2) ? "TRUE" : "FALSE", len);
00277       break;
00278    case LTFUNCTION:
00279       ast_copy_string(buf, (fnum1 < fnum2) ? "TRUE" : "FALSE", len);
00280       break;
00281    case GTEFUNCTION:
00282       ast_copy_string(buf, (fnum1 >= fnum2) ? "TRUE" : "FALSE", len);
00283       break;
00284    case LTEFUNCTION:
00285       ast_copy_string(buf, (fnum1 <= fnum2) ? "TRUE" : "FALSE", len);
00286       break;
00287    case EQFUNCTION:
00288       ast_copy_string(buf, (fnum1 == fnum2) ? "TRUE" : "FALSE", len);
00289       break;
00290    default:
00291       ast_log(LOG_WARNING,
00292             "Something happened that neither of us should be proud of %d\n",
00293             iaction);
00294       return -1;
00295    }
00296 
00297    if (iaction < GTFUNCTION || iaction > EQFUNCTION) {
00298       if (type_of_result == FLOAT_RESULT)
00299          snprintf(buf, len, "%f", ftmp);
00300       else if (type_of_result == INT_RESULT)
00301          snprintf(buf, len, "%i", (int) ftmp);
00302       else if (type_of_result == HEX_RESULT)
00303          snprintf(buf, len, "%x", (unsigned int) ftmp);
00304       else if (type_of_result == CHAR_RESULT)
00305          snprintf(buf, len, "%c", (unsigned char) ftmp);
00306    }
00307 
00308    return 0;
00309 }
00310 
00311 static struct ast_custom_function math_function = {
00312    .name = "MATH",
00313    .synopsis = "Performs Mathematical Functions",
00314    .syntax = "MATH(<number1><op><number2>[,<type_of_result>])",
00315    .desc = "Perform calculation on number1 to number2. Valid ops are: \n"
00316       "    +,-,/,*,%,<<,>>,^,AND,OR,XOR,<,>,>=,<=,==\n"
00317       "and behave as their C equivalents.\n"
00318       "<type_of_result> - wanted type of result:\n"
00319       "  f, float - float(default)\n"
00320       "  i, int - integer,\n"
00321       "  h, hex - hex,\n"
00322       "  c, char - char\n"
00323       "Example: Set(i=${MATH(123%16,int)}) - sets var i=11",
00324    .read = math
00325 };
00326 
00327 static int unload_module(void)
00328 {
00329    return ast_custom_function_unregister(&math_function);
00330 }
00331 
00332 static int load_module(void)
00333 {
00334    return ast_custom_function_register(&math_function);
00335 }
00336 
00337 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Mathematical dialplan function");

Generated on Wed Aug 18 22:33:52 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7