Item DecimalMathematician::calculate(const Item &o1, const Operator op, const Item &o2, const QExplicitlySharedDataPointer<DynamicContext> &context) const { switch(op) { case Div: { if(o2.as<Numeric>()->toInteger() == 0) { context->error(divZeroInvalid(), ReportContext::FOAR0001, this); return Item(); /* Silences source code analyzer warning. */ } else return toItem(Decimal::fromValue(o1.as<Numeric>()->toDecimal() / o2.as<Numeric>()->toDecimal())); } case IDiv: { if(o2.as<Numeric>()->toInteger() == 0) { context->error(idivZeroInvalid(), ReportContext::FOAR0001, this); return Item(); /* Silences source code analyzer warning. */ } else return Integer::fromValue(static_cast<xsInteger>(o1.as<Numeric>()->toDecimal() / o2.as<Numeric>()->toDecimal())); } case Substract: return toItem(Decimal::fromValue(o1.as<Numeric>()->toDecimal() - o2.as<Numeric>()->toDecimal())); case Mod: { if(o2.as<Numeric>()->toInteger() == 0) { context->error(modZeroInvalid(), ReportContext::FOAR0001, this); return Item(); /* Silences source code analyzer warning. */ } else return toItem(Decimal::fromValue(::fmod(o1.as<Numeric>()->toDecimal(), o2.as<Numeric>()->toDecimal()))); } case Multiply: return toItem(Decimal::fromValue(o1.as<Numeric>()->toDecimal() * o2.as<Numeric>()->toDecimal())); case Add: return toItem(Decimal::fromValue(o1.as<Numeric>()->toDecimal() + o2.as<Numeric>()->toDecimal())); } Q_ASSERT(false); return Item(); /* GCC unbarfer. */ }
Item AbstractFloatMathematician<isDouble>::calculate(const Item &o1, const Operator op, const Item &o2, const QExplicitlySharedDataPointer<DynamicContext> &context) const { const Numeric *const num1 = o1.template as<Numeric>(); const Numeric *const num2 = o2.template as<Numeric>(); switch(op) { case Div: return toItem(AbstractFloat<isDouble>::fromValue(num1->toDouble() / num2->toDouble())); case IDiv: { if(num1->isNaN() || num2->isNaN()) { context->error(QtXmlPatterns::tr("No operand in an integer division, %1, can be %2.") .arg(formatKeyword("idiv")) .arg(formatData("NaN")), ReportContext::FOAR0002, this); } else if(num1->isInf()) { context->error(QtXmlPatterns::tr("The first operand in an integer division, %1, cannot be infinity (%2).") .arg(formatKeyword("idiv")) .arg(formatData("INF")), ReportContext::FOAR0002, this); } else if(num2->toInteger() == 0) context->error(QtXmlPatterns::tr("The second operand in a division, %1, cannot be zero (%2).") .arg(formatKeyword("idiv")) .arg(formatData("0")), ReportContext::FOAR0001, this); return Integer::fromValue(static_cast<xsInteger>(num1->toDouble() / num2->toDouble())); } case Substract: return toItem(AbstractFloat<isDouble>::fromValue(num1->toDouble() - num2->toDouble())); case Mod: return toItem(AbstractFloat<isDouble>::fromValue(::fmod(num1->toDouble(), num2->toDouble()))); case Multiply: return toItem(AbstractFloat<isDouble>::fromValue(num1->toDouble() * num2->toDouble())); case Add: return toItem(AbstractFloat<isDouble>::fromValue(num1->toDouble() + num2->toDouble())); } Q_ASSERT(false); return Item(); /* GCC unbarfer. */ }
Item DateTimeDurationMathematician::calculate(const Item &o1, const Operator op, const Item &o2, const QExplicitlySharedDataPointer<DynamicContext> &context) const { Q_ASSERT(op == Substract || op == Add); const AbstractDateTime::Ptr adt(o1.as<AbstractDateTime>()); const AbstractDuration::Ptr dur(o2.as<AbstractDuration>()); QDateTime dt(adt->toDateTime()); //pDebug() << "DateTimeDurationMathematician::calculate():" << dt.toString(); //dt.setDateOnly(false); const qint8 sign = (op == Add ? 1 : -1) * (dur->isPositive() ? 1 : -1); // TODO milli seconds dt = dt.addSecs(sign * (dur->seconds() + dur->minutes() * 60 + dur->hours() * 60 * 60)); dt = dt.addDays(sign * dur->days()); dt = dt.addMonths(sign * dur->months()); dt = dt.addYears(sign * dur->years()); QString msg; if(AbstractDateTime::isRangeValid(dt.date(), msg)) return adt->fromValue(dt); else { context->error(msg, ReportContext::FODT0001, this); return Item(); } }
bool Boolean::evaluateEBV(const Item &first, const Item::Iterator::Ptr &it, const QExplicitlySharedDataPointer<DynamicContext> &context) { Q_ASSERT(it); Q_ASSERT(context); if(!first) return false; else if(first.isNode()) return true; const Item second(it->next()); if(second) { Q_ASSERT(context); context->error(QtXmlPatterns::tr("Effective Boolean Value cannot be calculated for a sequence " "containing two or more atomic values."), ReportContext::FORG0006, QSourceLocation()); return false; } else return first.as<AtomicValue>()->evaluateEBV(context); }
bool AtomicValue::evaluateEBV(const QExplicitlySharedDataPointer<DynamicContext> &context) const { context->error(QtXmlPatterns::tr("A value of type %1 cannot have an " "Effective Boolean Value.") .arg(formatType(context->namePool(), type())), ReportContext::FORG0006, QSourceLocation()); return false; /* Silence GCC warning. */ }
Item DurationNumericMathematician::calculate(const Item &o1, const Operator op, const Item &o2, const QExplicitlySharedDataPointer<DynamicContext> &context) const { Q_ASSERT(op == Div || op == Multiply); const AbstractDuration::Ptr duration(o1.as<AbstractDuration>()); const xsDouble dbl = o2.as<Numeric>()->toDouble(); switch(op) { case Div: { if(qIsInf(dbl)) return duration->fromValue(0); else if(qIsNaN(dbl)) { context->error(QtXmlPatterns::tr( "Dividing a value of type %1 by %2 (not-a-number) " "is not allowed.") .arg(formatType(context->namePool(), duration->type())) .arg(formatData("NaN")), ReportContext::FOCA0005, this); return Item(); } else if(Double::isEqual(dbl, 0)) { context->error(QtXmlPatterns::tr( "Dividing a value of type %1 by %2 or %3 (plus or " "minus zero) is not allowed.") .arg(formatType(context->namePool(), duration->type())) .arg(formatData("-0")) .arg(formatData("0")), ReportContext::FODT0002, this); return Item(); } return duration->fromValue(static_cast<AbstractDuration::Value>(duration->value() / dbl)); } case Multiply: { if(Double::isEqual(dbl, 0)) return duration->fromValue(0); else if(qIsNaN(dbl)) { context->error(QtXmlPatterns::tr( "Dividing a value of type %1 by %2 (not-a-number) " "is not allowed.") .arg(formatType(context->namePool(), duration->type())) .arg(formatData("NaN")), ReportContext::FOCA0005, this); return Item(); } else if(qIsInf(dbl)) { context->error(QtXmlPatterns::tr( "Multiplication of a value of type %1 by %2 or %3 " "(plus or minus infinity) is not allowed.") .arg(formatType(context->namePool(), duration->type())) .arg(formatData("-INF")) .arg(formatData("INF")), ReportContext::FODT0002, this); return Item(); } return duration->fromValue(static_cast<AbstractDuration::Value>(duration->value() * dbl)); } default: { Q_ASSERT(false); return Item(); /* Silence warning. */ } } }