Thu Jul 9 13:40:35 2009

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: 89425 $")
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 += 3;
00118       *op = '\0';
00119    } else if ((op = strstr(mvalue1, "XOR"))) {
00120       iaction = BITWISEXORFUNCTION;
00121       op += 3;
00122       *op = '\0';
00123    } else if ((op = strstr(mvalue1, "OR"))) {
00124       iaction = BITWISEORFUNCTION;
00125       op += 2;
00126       *op = '\0';
00127    } else if ((op = strchr(mvalue1, '>'))) {
00128       iaction = GTFUNCTION;
00129       *op = '\0';
00130       if (*(op + 1) == '=') {
00131          *++op = '\0';
00132          iaction = GTEFUNCTION;
00133       } else if (*(op + 1) == '>') {
00134          *++op = '\0';
00135          iaction = SHRIGHTFUNCTION;
00136       }
00137    } else if ((op = strchr(mvalue1, '<'))) {
00138       iaction = LTFUNCTION;
00139       *op = '\0';
00140       if (*(op + 1) == '=') {
00141          *++op = '\0';
00142          iaction = LTEFUNCTION;
00143       } else if (*(op + 1) == '<') {
00144          *++op = '\0';
00145          iaction = SHLEFTFUNCTION;
00146       }
00147    } else if ((op = strchr(mvalue1, '='))) {
00148       *op = '\0';
00149       if (*(op + 1) == '=') {
00150          *++op = '\0';
00151          iaction = EQFUNCTION;
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 first 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, "%lf", &fnum1) != 1) {
00194       ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue1);
00195       return -1;
00196    }
00197 
00198    if (sscanf(mvalue2, "%lf", &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          ftmp = (inum1 % inum2);
00228 
00229          break;
00230       }
00231    case POWFUNCTION:
00232       ftmp = pow(fnum1, fnum2);
00233       break;
00234    case SHLEFTFUNCTION:
00235       {
00236          int inum1 = fnum1;
00237          int inum2 = fnum2;
00238 
00239          ftmp = (inum1 << inum2);
00240          break;
00241       }
00242    case SHRIGHTFUNCTION:
00243       {
00244          int inum1 = fnum1;
00245          int inum2 = fnum2;
00246 
00247          ftmp = (inum1 >> inum2);
00248          break;
00249       }
00250    case BITWISEANDFUNCTION:
00251       {
00252          int inum1 = fnum1;
00253          int inum2 = fnum2;
00254          ftmp = (inum1 & inum2);
00255          break;
00256       }
00257    case BITWISEXORFUNCTION:
00258       {
00259          int inum1 = fnum1;
00260          int inum2 = fnum2;
00261          ftmp = (inum1 ^ inum2);
00262          break;
00263       }
00264    case BITWISEORFUNCTION:
00265       {
00266          int inum1 = fnum1;
00267          int inum2 = fnum2;
00268          ftmp = (inum1 | inum2);
00269          break;
00270       }
00271    case GTFUNCTION:
00272       ast_copy_string(buf, (fnum1 > fnum2) ? "TRUE" : "FALSE", len);
00273       break;
00274    case LTFUNCTION:
00275       ast_copy_string(buf, (fnum1 < fnum2) ? "TRUE" : "FALSE", len);
00276       break;
00277    case GTEFUNCTION:
00278       ast_copy_string(buf, (fnum1 >= fnum2) ? "TRUE" : "FALSE", len);
00279       break;
00280    case LTEFUNCTION:
00281       ast_copy_string(buf, (fnum1 <= fnum2) ? "TRUE" : "FALSE", len);
00282       break;
00283    case EQFUNCTION:
00284       ast_copy_string(buf, (fnum1 == fnum2) ? "TRUE" : "FALSE", len);
00285       break;
00286    default:
00287       ast_log(LOG_WARNING,
00288             "Something happened that neither of us should be proud of %d\n",
00289             iaction);
00290       return -1;
00291    }
00292 
00293    if (iaction < GTFUNCTION || iaction > EQFUNCTION) {
00294       if (type_of_result == FLOAT_RESULT)
00295          snprintf(buf, len, "%f", ftmp);
00296       else if (type_of_result == INT_RESULT)
00297          snprintf(buf, len, "%i", (int) ftmp);
00298       else if (type_of_result == HEX_RESULT)
00299          snprintf(buf, len, "%x", (unsigned int) ftmp);
00300       else if (type_of_result == CHAR_RESULT)
00301          snprintf(buf, len, "%c", (unsigned char) ftmp);
00302    }
00303 
00304    return 0;
00305 }
00306 
00307 static struct ast_custom_function math_function = {
00308    .name = "MATH",
00309    .synopsis = "Performs Mathematical Functions",
00310    .syntax = "MATH(<number1><op><number2>[,<type_of_result>])",
00311    .desc = "Perform calculation on number1 to number2. Valid ops are: \n"
00312       "    +,-,/,*,%,<<,>>,^,AND,OR,XOR,<,>,>=,<=,==\n"
00313       "and behave as their C equivalents.\n"
00314       "<type_of_result> - wanted type of result:\n"
00315       "  f, float - float(default)\n"
00316       "  i, int - integer,\n"
00317       "  h, hex - hex,\n"
00318       "  c, char - char\n"
00319       "Example: Set(i=${MATH(123%16,int)}) - sets var i=11",
00320    .read = math
00321 };
00322 
00323 static int unload_module(void)
00324 {
00325    return ast_custom_function_unregister(&math_function);
00326 }
00327 
00328 static int load_module(void)
00329 {
00330    return ast_custom_function_register(&math_function);
00331 }
00332 
00333 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Mathematical dialplan function");

Generated on Thu Jul 9 13:40:35 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7