File indexing completed on 2024-04-28 16:21:23

0001 /* This file is part of the KDE project
0002    Copyright (C) 2003,2004 Ariya Hidayat <ariya@kde.org>
0003    Copyright (C) 2005 Tomas Mecir <mecirt@gmail.com>
0004 
0005    This library is free software; you can redistribute it and/or
0006    modify it under the terms of the GNU Library General Public
0007    License as published by the Free Software Foundation; only
0008    version 2 of the License.
0009 
0010    This library is distributed in the hope that it will be useful,
0011    but WITHOUT ANY WARRANTY; without even the implied warranty of
0012    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0013    Library General Public License for more details.
0014 
0015    You should have received a copy of the GNU Library General Public License
0016    along with this library; see the file COPYING.LIB.  If not, write to
0017    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0018    Boston, MA 02110-1301, USA.
0019 */
0020 
0021 // Local
0022 #include "Function.h"
0023 
0024 #include "Value.h"
0025 
0026 using namespace Calligra::Sheets;
0027 
0028 class Q_DECL_HIDDEN Function::Private
0029 {
0030 public:
0031     QString name;
0032     QString alternateName;
0033     FunctionPtr ptr;
0034     int paramMin, paramMax;
0035     bool acceptArray;
0036     bool ne;   // need FunctionExtra* when called ?
0037 };
0038 
0039 Function::Function(const QString& name, FunctionPtr ptr)
0040         : d(new Private)
0041 {
0042     d->name = name;
0043     d->ptr = ptr;
0044     d->acceptArray = false;
0045     d->paramMin = 1;
0046     d->paramMax = 1;
0047     d->ne = false;
0048 }
0049 
0050 Function::~Function()
0051 {
0052     delete d;
0053 }
0054 
0055 QString Function::name() const
0056 {
0057     return d->name;
0058 }
0059 
0060 QString Function::alternateName() const
0061 {
0062     return d->alternateName;
0063 }
0064 
0065 void Function::setAlternateName(const QString &name)
0066 {
0067     d->alternateName = name;
0068 }
0069 
0070 void Function::setParamCount(int min, int max)
0071 {
0072     d->paramMin = min;
0073     d->paramMax = (max == 0) ? min : max;
0074 }
0075 
0076 bool Function::paramCountOkay(int count)
0077 {
0078     // less than needed
0079     if (count < d->paramMin) return false;
0080     // no upper limit
0081     if (d->paramMax == -1) return true;
0082     // more than needed
0083     if (count > d->paramMax) return false;
0084     // okay otherwise
0085     return true;
0086 }
0087 
0088 void Function::setAcceptArray(bool accept)
0089 {
0090     d->acceptArray = accept;
0091 }
0092 
0093 bool Function::needsExtra()
0094 {
0095     return d->ne;
0096 }
0097 void Function::setNeedsExtra(bool extra)
0098 {
0099     d->ne = extra;
0100 }
0101 
0102 Value Function::exec(valVector args, ValueCalc *calc, FuncExtra *extra)
0103 {
0104     // check number of parameters
0105     if (!paramCountOkay(args.count()))
0106         return Value::errorVALUE();
0107 
0108     if (extra)
0109         extra->function = this;
0110 
0111     // do we need to perform array expansion ?
0112     bool mustExpandArray = false;
0113     if (!d->acceptArray)
0114         for (int i = 0; i < args.count(); ++i) {
0115             if (args[i].isArray())
0116                 mustExpandArray = true;
0117         }
0118 
0119     if (!d->ptr) return Value::errorVALUE();
0120 
0121     // perform the actual array expansion if need be
0122 
0123     if (mustExpandArray) {
0124         // compute number of rows/cols of the result
0125         int rows = 0;
0126         int cols = 0;
0127         for (int i = 0; i < args.count(); ++i) {
0128             int x = 1;
0129             if (extra) x = extra->ranges[i].rows();
0130             if (x > rows) rows = x;
0131             if (extra) x = extra->ranges[i].columns();
0132             if (x > cols) cols = x;
0133         }
0134         // allocate the resulting array
0135         Value res(Value::Array);
0136         // perform the actual computation for each element of the array
0137         for (int row = 0; row < rows; ++row)
0138             for (int col = 0; col < cols; ++col) {
0139                 // fill in the parameter vector
0140                 valVector vals(args.count());
0141                 FuncExtra extra2 = *extra;
0142                 for (int i = 0; i < args.count(); ++i) {
0143                     int r = extra->ranges[i].rows();
0144                     int c = extra->ranges[i].columns();
0145                     vals[i] = args[i].isArray() ?
0146                               args[i].element(col % c, row % r) : args[i];
0147 
0148                     // adjust the FuncExtra structure to refer to the correct cells
0149                     extra2.ranges[i].col1 += col;
0150                     extra2.ranges[i].row1 += row;
0151                     extra2.ranges[i].col2 = extra2.ranges[i].col1;
0152                     extra2.ranges[i].row2 = extra2.ranges[i].row1;
0153                 }
0154                 // execute the function on each element
0155                 res.setElement(col, row, exec(vals, calc, &extra2));
0156             }
0157         return res;
0158     } else
0159         // call the function
0160         return (*d->ptr)(args, calc, extra);
0161 }
0162 
0163 FunctionCaller::FunctionCaller(FunctionPtr ptr, const valVector &args, ValueCalc *calc, FuncExtra *extra)
0164     : m_ptr(ptr), m_args(args), m_calc(calc), m_extra(extra)
0165 {
0166 }
0167 
0168 Value FunctionCaller::exec()
0169 {
0170     return (*m_ptr)(m_args, m_calc, m_extra);
0171 }
0172 
0173 Value FunctionCaller::exec(const valVector &args)
0174 {
0175     return (*m_ptr)(args, m_calc, m_extra);
0176 }