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 }