Sat Aug 6 00:39:29 2011

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 
00027 #include "asterisk.h"
00028 
00029 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 241765 $")
00030 
00031 #include <stdlib.h>
00032 #include <stdio.h>
00033 #include <string.h>
00034 #include <sys/types.h>
00035 
00036 #include "asterisk/module.h"
00037 #include "asterisk/channel.h"
00038 #include "asterisk/pbx.h"
00039 #include "asterisk/logger.h"
00040 #include "asterisk/utils.h"
00041 #include "asterisk/app.h"
00042 #include "asterisk/config.h"
00043 
00044 enum TypeOfFunctions {
00045    ADDFUNCTION,
00046    DIVIDEFUNCTION,
00047    MULTIPLYFUNCTION,
00048    SUBTRACTFUNCTION,
00049    MODULUSFUNCTION,
00050    GTFUNCTION,
00051    LTFUNCTION,
00052    GTEFUNCTION,
00053    LTEFUNCTION,
00054    EQFUNCTION
00055 };
00056 
00057 enum TypeOfResult {
00058    FLOAT_RESULT,
00059    INT_RESULT,
00060    HEX_RESULT,
00061    CHAR_RESULT
00062 };
00063 
00064 static int math(struct ast_channel *chan, char *cmd, char *parse,
00065       char *buf, size_t len)
00066 {
00067    double fnum1;
00068    double fnum2;
00069    double ftmp = 0;
00070    char *op;
00071    int iaction = -1;
00072    int type_of_result = FLOAT_RESULT;
00073    char *mvalue1, *mvalue2 = NULL, *mtype_of_result;
00074    int negvalue1 = 0;
00075    AST_DECLARE_APP_ARGS(args,
00076               AST_APP_ARG(argv0);
00077               AST_APP_ARG(argv1);
00078    );
00079 
00080    if (ast_strlen_zero(parse)) {
00081       ast_log(LOG_WARNING, "Syntax: MATH(<number1><op><number 2>[,<type_of_result>]) - missing argument!\n");
00082       return -1;
00083    }
00084 
00085    AST_STANDARD_APP_ARGS(args, parse);
00086 
00087    if (args.argc < 1) {
00088       ast_log(LOG_WARNING, "Syntax: MATH(<number1><op><number 2>[,<type_of_result>]) - missing argument!\n");
00089       return -1;
00090    }
00091 
00092    mvalue1 = args.argv0;
00093 
00094    if (mvalue1[0] == '-') {
00095       negvalue1 = 1;
00096       mvalue1++;
00097    }
00098 
00099    if ((op = strchr(mvalue1, '*'))) {
00100       iaction = MULTIPLYFUNCTION;
00101       *op = '\0';
00102    } else if ((op = strchr(mvalue1, '/'))) {
00103       iaction = DIVIDEFUNCTION;
00104       *op = '\0';
00105    } else if ((op = strchr(mvalue1, '%'))) {
00106       iaction = MODULUSFUNCTION;
00107       *op = '\0';
00108    } else if ((op = strchr(mvalue1, '>'))) {
00109       iaction = GTFUNCTION;
00110       *op = '\0';
00111       if (*(op + 1) == '=') {
00112          *++op = '\0';
00113          iaction = GTEFUNCTION;
00114       }
00115    } else if ((op = strchr(mvalue1, '<'))) {
00116       iaction = LTFUNCTION;
00117       *op = '\0';
00118       if (*(op + 1) == '=') {
00119          *++op = '\0';
00120          iaction = LTEFUNCTION;
00121       }
00122    } else if ((op = strchr(mvalue1, '='))) {
00123       *op = '\0';
00124       if (*(op + 1) == '=') {
00125          *++op = '\0';
00126          iaction = EQFUNCTION;
00127       } else
00128          op = NULL;
00129    } else if ((op = strchr(mvalue1, '+'))) {
00130       iaction = ADDFUNCTION;
00131       *op = '\0';
00132    } else if ((op = strchr(mvalue1, '-'))) { /* subtraction MUST always be last, in case we have a negative first number */
00133       iaction = SUBTRACTFUNCTION;
00134       *op = '\0';
00135    }
00136 
00137    if (op)
00138       mvalue2 = op + 1;
00139 
00140    /* detect wanted type of result */
00141    mtype_of_result = args.argv1;
00142    if (mtype_of_result) {
00143       if (!strcasecmp(mtype_of_result, "float")
00144           || !strcasecmp(mtype_of_result, "f"))
00145          type_of_result = FLOAT_RESULT;
00146       else if (!strcasecmp(mtype_of_result, "int")
00147           || !strcasecmp(mtype_of_result, "i"))
00148          type_of_result = INT_RESULT;
00149       else if (!strcasecmp(mtype_of_result, "hex")
00150           || !strcasecmp(mtype_of_result, "h"))
00151          type_of_result = HEX_RESULT;
00152       else if (!strcasecmp(mtype_of_result, "char")
00153           || !strcasecmp(mtype_of_result, "c"))
00154          type_of_result = CHAR_RESULT;
00155       else {
00156          ast_log(LOG_WARNING, "Unknown type of result requested '%s'.\n",
00157                mtype_of_result);
00158          return -1;
00159       }
00160    }
00161 
00162    if (!mvalue1 || !mvalue2) {
00163       ast_log(LOG_WARNING,
00164             "Supply all the parameters - just this once, please\n");
00165       return -1;
00166    }
00167 
00168    if (sscanf(mvalue1, "%30lf", &fnum1) != 1) {
00169       ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue1);
00170       return -1;
00171    }
00172 
00173    if (sscanf(mvalue2, "%30lf", &fnum2) != 1) {
00174       ast_log(LOG_WARNING, "'%s' is not a valid number\n", mvalue2);
00175       return -1;
00176    }
00177 
00178    if (negvalue1)
00179       fnum1 = 0 - fnum1;
00180 
00181    switch (iaction) {
00182    case ADDFUNCTION:
00183       ftmp = fnum1 + fnum2;
00184       break;
00185    case DIVIDEFUNCTION:
00186       if (fnum2 <= 0)
00187          ftmp = 0;         /* can't do a divide by 0 */
00188       else
00189          ftmp = (fnum1 / fnum2);
00190       break;
00191    case MULTIPLYFUNCTION:
00192       ftmp = (fnum1 * fnum2);
00193       break;
00194    case SUBTRACTFUNCTION:
00195       ftmp = (fnum1 - fnum2);
00196       break;
00197    case MODULUSFUNCTION:
00198       {
00199          int inum1 = fnum1;
00200          int inum2 = fnum2;
00201 
00202          if (inum2 == 0) {
00203             ftmp = 0;
00204          } else {
00205             ftmp = (inum1 % inum2);
00206          }
00207 
00208          break;
00209       }
00210    case GTFUNCTION:
00211       ast_copy_string(buf, (fnum1 > fnum2) ? "TRUE" : "FALSE", len);
00212       break;
00213    case LTFUNCTION:
00214       ast_copy_string(buf, (fnum1 < fnum2) ? "TRUE" : "FALSE", len);
00215       break;
00216    case GTEFUNCTION:
00217       ast_copy_string(buf, (fnum1 >= fnum2) ? "TRUE" : "FALSE", len);
00218       break;
00219    case LTEFUNCTION:
00220       ast_copy_string(buf, (fnum1 <= fnum2) ? "TRUE" : "FALSE", len);
00221       break;
00222    case EQFUNCTION:
00223       ast_copy_string(buf, (fnum1 == fnum2) ? "TRUE" : "FALSE", len);
00224       break;
00225    default:
00226       ast_log(LOG_WARNING,
00227             "Something happened that neither of us should be proud of %d\n",
00228             iaction);
00229       return -1;
00230    }
00231 
00232    if (iaction < GTFUNCTION || iaction > EQFUNCTION) {
00233       if (type_of_result == FLOAT_RESULT)
00234          snprintf(buf, len, "%f", ftmp);
00235       else if (type_of_result == INT_RESULT)
00236          snprintf(buf, len, "%i", (int) ftmp);
00237       else if (type_of_result == HEX_RESULT)
00238          snprintf(buf, len, "%x", (unsigned int) ftmp);
00239       else if (type_of_result == CHAR_RESULT)
00240          snprintf(buf, len, "%c", (unsigned char) ftmp);
00241    }
00242 
00243    return 0;
00244 }
00245 
00246 static struct ast_custom_function math_function = {
00247    .name = "MATH",
00248    .synopsis = "Performs Mathematical Functions",
00249    .syntax = "MATH(<number1><op><number 2>[,<type_of_result>])",
00250    .desc = "Perform calculation on number 1 to number 2. Valid ops are: \n"
00251       "    +,-,/,*,%,<,>,>=,<=,==\n"
00252       "and behave as their C equivalents.\n"
00253       "<type_of_result> - wanted type of result:\n"
00254       "  f, float - float(default)\n"
00255       "  i, int - integer,\n"
00256       "  h, hex - hex,\n"
00257       "  c, char - char\n"
00258       "Example: Set(i=${MATH(123%16,int)}) - sets var i=11",
00259    .read = math
00260 };
00261 
00262 static int unload_module(void)
00263 {
00264    return ast_custom_function_unregister(&math_function);
00265 }
00266 
00267 static int load_module(void)
00268 {
00269    return ast_custom_function_register(&math_function);
00270 }
00271 
00272 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Mathematical dialplan function");

Generated on Sat Aug 6 00:39:29 2011 for Asterisk - the Open Source PBX by  doxygen 1.4.7