1 | /* This file is part of the KDE project |
2 | Copyright (C) 2003,2004 Ariya Hidayat <ariya@kde.org> |
3 | Copyright (C) 2005 Tomas Mecir <mecirt@gmail.com> |
4 | |
5 | This library is free software; you can redistribute it and/or |
6 | modify it under the terms of the GNU Library General Public |
7 | License as published by the Free Software Foundation; only |
8 | version 2 of the License. |
9 | |
10 | This library is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | Library General Public License for more details. |
14 | |
15 | You should have received a copy of the GNU Library General Public License |
16 | along with this library; see the file COPYING.LIB. If not, write to |
17 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
18 | Boston, MA 02110-1301, USA. |
19 | */ |
20 | |
21 | // Local |
22 | #include "Function.h" |
23 | |
24 | #include "Value.h" |
25 | |
26 | using namespace Calligra::Sheets; |
27 | |
28 | class Function::Private |
29 | { |
30 | public: |
31 | QString name; |
32 | QString alternateName; |
33 | FunctionPtr ptr; |
34 | int paramMin, paramMax; |
35 | bool acceptArray; |
36 | bool ne; // need FunctionExtra* when called ? |
37 | }; |
38 | |
39 | Function::(const QString& name, FunctionPtr ptr) |
40 | : d(new Private) |
41 | { |
42 | d->name = name; |
43 | d->ptr = ptr; |
44 | d->acceptArray = false; |
45 | d->paramMin = 1; |
46 | d->paramMax = 1; |
47 | d->ne = false; |
48 | } |
49 | |
50 | Function::~Function() |
51 | { |
52 | delete d; |
53 | } |
54 | |
55 | QString Function::name() const |
56 | { |
57 | return d->name; |
58 | } |
59 | |
60 | QString Function::alternateName() const |
61 | { |
62 | return d->alternateName; |
63 | } |
64 | |
65 | void Function::setAlternateName(const QString &name) |
66 | { |
67 | d->alternateName = name; |
68 | } |
69 | |
70 | void Function::setParamCount(int min, int max) |
71 | { |
72 | d->paramMin = min; |
73 | d->paramMax = (max == 0) ? min : max; |
74 | } |
75 | |
76 | bool Function::paramCountOkay(int count) |
77 | { |
78 | // less than needed |
79 | if (count < d->paramMin) return false; |
80 | // no upper limit |
81 | if (d->paramMax == -1) return true; |
82 | // more than needed |
83 | if (count > d->paramMax) return false; |
84 | // okay otherwise |
85 | return true; |
86 | } |
87 | |
88 | void Function::setAcceptArray(bool accept) |
89 | { |
90 | d->acceptArray = accept; |
91 | } |
92 | |
93 | bool Function::() |
94 | { |
95 | return d->ne; |
96 | } |
97 | void Function::(bool ) |
98 | { |
99 | d->ne = extra; |
100 | } |
101 | |
102 | Value Function::(valVector args, ValueCalc *calc, FuncExtra *) |
103 | { |
104 | // check number of parameters |
105 | if (!paramCountOkay(args.count())) |
106 | return Value::errorVALUE(); |
107 | |
108 | if (extra) |
109 | extra->function = this; |
110 | |
111 | // do we need to perform array expansion ? |
112 | bool mustExpandArray = false; |
113 | if (!d->acceptArray) |
114 | for (int i = 0; i < args.count(); ++i) { |
115 | if (args[i].isArray()) |
116 | mustExpandArray = true; |
117 | } |
118 | |
119 | if (!d->ptr) return Value::errorVALUE(); |
120 | |
121 | // perform the actual array expansion if need be |
122 | |
123 | if (mustExpandArray) { |
124 | // compute number of rows/cols of the result |
125 | int rows = 0; |
126 | int cols = 0; |
127 | for (int i = 0; i < args.count(); ++i) { |
128 | int x = 1; |
129 | if (extra) x = extra->ranges[i].rows(); |
130 | if (x > rows) rows = x; |
131 | if (extra) x = extra->ranges[i].columns(); |
132 | if (x > cols) cols = x; |
133 | } |
134 | // allocate the resulting array |
135 | Value res(Value::Array); |
136 | // perform the actual computation for each element of the array |
137 | for (int row = 0; row < rows; ++row) |
138 | for (int col = 0; col < cols; ++col) { |
139 | // fill in the parameter vector |
140 | valVector vals(args.count()); |
141 | FuncExtra = *extra; |
142 | for (int i = 0; i < args.count(); ++i) { |
143 | int r = extra->ranges[i].rows(); |
144 | int c = extra->ranges[i].columns(); |
145 | vals[i] = args[i].isArray() ? |
146 | args[i].element(col % c, row % r) : args[i]; |
147 | |
148 | // adjust the FuncExtra structure to refer to the correct cells |
149 | extra2.ranges[i].col1 += col; |
150 | extra2.ranges[i].row1 += row; |
151 | extra2.ranges[i].col2 = extra2.ranges[i].col1; |
152 | extra2.ranges[i].row2 = extra2.ranges[i].row1; |
153 | } |
154 | // execute the function on each element |
155 | res.setElement(col, row, exec(vals, calc, &extra2)); |
156 | } |
157 | return res; |
158 | } else |
159 | // call the function |
160 | return (*d->ptr)(args, calc, extra); |
161 | } |
162 | |
163 | FunctionCaller::(FunctionPtr ptr, const valVector &args, ValueCalc *calc, FuncExtra *) |
164 | : m_ptr(ptr), m_args(args), m_calc(calc), m_extra(extra) |
165 | { |
166 | } |
167 | |
168 | Value FunctionCaller::exec() |
169 | { |
170 | return (*m_ptr)(m_args, m_calc, m_extra); |
171 | } |
172 | |
173 | Value FunctionCaller::exec(const valVector &args) |
174 | { |
175 | return (*m_ptr)(args, m_calc, m_extra); |
176 | } |
177 | |