File indexing completed on 2024-05-12 16:35:31

0001 /* This file is part of the KDE project
0002    Copyright (C) 1998-2002 The KSpread Team <calligra-devel@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 // built-in logical functions
0022 #include "LogicModule.h"
0023 
0024 #include "Function.h"
0025 #include "FunctionModuleRegistry.h"
0026 #include "ValueCalc.h"
0027 #include "ValueConverter.h"
0028 
0029 using namespace Calligra::Sheets;
0030 
0031 // prototypes (sorted alphabetically)
0032 Value func_and(valVector args, ValueCalc *calc, FuncExtra *);
0033 Value func_false(valVector args, ValueCalc *calc, FuncExtra *);
0034 Value func_if(valVector args, ValueCalc *calc, FuncExtra *);
0035 Value func_iferror(valVector args, ValueCalc *calc, FuncExtra *);
0036 Value func_ifna(valVector args, ValueCalc *calc, FuncExtra *);
0037 Value func_nand(valVector args, ValueCalc *calc, FuncExtra *);
0038 Value func_nor(valVector args, ValueCalc *calc, FuncExtra *);
0039 Value func_not(valVector args, ValueCalc *calc, FuncExtra *);
0040 Value func_or(valVector args, ValueCalc *calc, FuncExtra *);
0041 Value func_true(valVector args, ValueCalc *calc, FuncExtra *);
0042 Value func_xor(valVector args, ValueCalc *calc, FuncExtra *);
0043 
0044 
0045 CALLIGRA_SHEETS_EXPORT_FUNCTION_MODULE("kspreadlogicmodule.json", LogicModule)
0046 
0047 
0048 LogicModule::LogicModule(QObject* parent, const QVariantList&)
0049         : FunctionModule(parent)
0050 {
0051     Function *f;
0052 
0053     f = new Function("FALSE", func_false);
0054     f->setParamCount(0);
0055     add(f);
0056     f = new Function("TRUE", func_true);
0057     f->setParamCount(0);
0058     add(f);
0059     f = new Function("NOT", func_not);
0060     f->setParamCount(1);
0061     add(f);
0062     f = new Function("AND", func_and);
0063     f->setParamCount(1, -1);
0064     f->setAcceptArray();
0065     add(f);
0066     f = new Function("NAND", func_nand);
0067     f->setParamCount(1, -1);
0068     f->setAcceptArray();
0069     add(f);
0070     f = new Function("NOR", func_nor);
0071     f->setParamCount(1, -1);
0072     f->setAcceptArray();
0073     add(f);
0074     f = new Function("OR", func_or);
0075     f->setParamCount(1, -1);
0076     f->setAcceptArray();
0077     add(f);
0078     f = new Function("XOR", func_xor);
0079     f->setParamCount(1, -1);
0080     f->setAcceptArray();
0081     add(f);
0082     f = new Function("IF", func_if);
0083     f->setParamCount(2, 3);
0084     add(f);
0085     f = new Function("IFERROR", func_iferror);
0086     f->setParamCount(2);
0087     add(f);
0088     f = new Function("IFNA", func_ifna);
0089     f->setParamCount(2);
0090     add(f);
0091 }
0092 
0093 QString LogicModule::descriptionFileName() const
0094 {
0095     return QString("logic.xml");
0096 }
0097 
0098 
0099 // helper for most logical functions
0100 static bool asBool(Value val, ValueCalc *calc, bool* ok = 0)
0101 {
0102     return calc->conv()->asBoolean(val, ok).asBoolean();
0103 }
0104 
0105 ///////////////////////////////////////////////////////////////////////////////
0106 
0107 
0108 //
0109 // ArrayWalker: AND
0110 //
0111 void awAnd(ValueCalc *calc, Value &res, Value value, Value)
0112 {
0113     if (res.asBoolean())
0114         res = Value(asBool(value, calc));
0115 }
0116 
0117 
0118 //
0119 // ArrayWalker: OR
0120 //
0121 void awOr(ValueCalc *calc, Value &res, Value value, Value)
0122 {
0123     if (!res.asBoolean())
0124         res = Value(asBool(value, calc));
0125 }
0126 
0127 
0128 //
0129 // ArrayWalker: XOR
0130 //
0131 void awXor(ValueCalc *calc, Value &count, Value value, Value)
0132 {
0133     if (asBool(value, calc))
0134         count = Value(count.asInteger() + 1);
0135 }
0136 
0137 ///////////////////////////////////////////////////////////////////////////////
0138 
0139 
0140 //
0141 // Function: AND
0142 //
0143 Value func_and(valVector args, ValueCalc *calc, FuncExtra *)
0144 {
0145     Value result(true);
0146     int cnt = args.count();
0147     for (int i = 0; i < cnt; ++i) {
0148         if (args[i].isError())
0149             return args[i];
0150     }
0151     for (int i = 0; i < cnt; ++i) {
0152         calc->arrayWalk(args[i], result, awAnd, Value(0));
0153         if (! result.asBoolean())
0154             // if any value is false, return false
0155             return result;
0156     }
0157     // nothing is false -> return true
0158     return result;
0159 }
0160 
0161 
0162 //
0163 // Function: FALSE
0164 //
0165 Value func_false(valVector, ValueCalc *, FuncExtra *)
0166 {
0167     return Value(false);
0168 }
0169 
0170 
0171 //
0172 // Function: IF
0173 //
0174 Value func_if(valVector args, ValueCalc *calc, FuncExtra *)
0175 {
0176     if ((args[0].isError()))
0177         return args[0];
0178     bool ok = true;
0179     bool guard = asBool(args[0], calc, &ok);
0180     if (!ok)
0181         return Value::errorVALUE();
0182     if (guard)
0183         return args[1];
0184     // evaluated to false
0185     if (args.count() == 3) {
0186         if (args[2].isNull()) {
0187             return Value(0);
0188         } else {
0189             return args[2];
0190         }
0191     } else {
0192         // only two arguments
0193         return Value(false);
0194     }
0195 }
0196 
0197 
0198 //
0199 // Function: IFERROR
0200 //
0201 Value func_iferror(valVector args, ValueCalc *, FuncExtra *)
0202 {
0203     if (args[0].isError())
0204         return args[1];
0205     return args[0];
0206 }
0207 
0208 
0209 //
0210 // Function: IFNA
0211 //
0212 Value func_ifna(valVector args, ValueCalc *, FuncExtra *)
0213 {
0214     if (args[0] == Value::errorNA())
0215         return args[1];
0216     return args[0];
0217 }
0218 
0219 
0220 //
0221 // Function: NAND
0222 //
0223 Value func_nand(valVector args, ValueCalc *calc, FuncExtra *extra)
0224 {
0225     // AND in reverse
0226     return Value(! func_and(args, calc, extra).asBoolean());
0227 }
0228 
0229 
0230 //
0231 // Function: NOR
0232 //
0233 Value func_nor(valVector args, ValueCalc *calc, FuncExtra *extra)
0234 {
0235     // OR in reverse
0236     return Value(! func_or(args, calc, extra).asBoolean());
0237 }
0238 
0239 
0240 //
0241 // Function: NOT
0242 //
0243 Value func_not(valVector args, ValueCalc *calc, FuncExtra *)
0244 {
0245     if (args[0].isError())
0246         return args[0];
0247 
0248     bool ok = true;
0249     bool val = !asBool(args[0], calc, &ok);
0250     if (!ok) return Value::errorVALUE();
0251     return Value(val);
0252 }
0253 
0254 
0255 //
0256 // Function: OR
0257 //
0258 Value func_or(valVector args, ValueCalc *calc, FuncExtra *)
0259 {
0260     Value result(false);
0261     int cnt = args.count();
0262     for (int i = 0; i < cnt; ++i) {
0263         if (args[i].isError())
0264             return args[i];
0265     }
0266     for (int i = 0; i < cnt; ++i) {
0267         calc->arrayWalk(args[i], result, awOr, Value(0));
0268         if (result.asBoolean())
0269             // if any value is true, return true
0270             return result;
0271     }
0272     // nothing is true -> return false
0273     return result;
0274 }
0275 
0276 
0277 //
0278 // Function: TRUE
0279 //
0280 Value func_true(valVector, ValueCalc *, FuncExtra *)
0281 {
0282     return Value(true);
0283 }
0284 
0285 
0286 //
0287 // Function: XOR
0288 //
0289 Value func_xor(valVector args, ValueCalc *calc, FuncExtra *)
0290 {
0291     // exclusive OR - odd number of values must be true
0292     int cnt = args.count();
0293     Value count(0);
0294     for (int i = 0; i < cnt; ++i) {
0295         if (args[i].isError())
0296             return args[i];
0297     }
0298     for (int i = 0; i < cnt; ++i)
0299         calc->arrayWalk(args[i], count, awXor, Value(0));
0300     return Value((count.asInteger() & 1) == 1);
0301 }
0302 
0303 #include "logic.moc"