bool ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>:: flexibleCompare(const Item &it1, const Item &it2, const DynamicContext::Ptr &context) const { if(m_comparator) /* The comparator was located at compile time. */ return compare(it1, it2, m_comparator, operatorID()); else { const AtomicComparator::Ptr cp(fetchComparator(it1.type(), it2.type(), context)); return cp ? compare(it1, it2, cp, operatorID()) : false; } }
Expression::Ptr ComparingAggregator<oper, result>::typeCheck(const StaticContext::Ptr &context, const SequenceType::Ptr &reqType) { Q_ASSERT(oper == AtomicComparator::OperatorGreaterThan || oper == AtomicComparator::OperatorLessThan); const Expression::Ptr me(FunctionCall::typeCheck(context, reqType)); ItemType::Ptr t1(m_operands.first()->staticType()->itemType()); if(*CommonSequenceTypes::Empty == *t1) return EmptySequence::create(this, context); else if(*BuiltinTypes::xsAnyAtomicType == *t1 || BuiltinTypes::numeric->xdtTypeMatches(t1)) return me; else if(BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t1)) { m_operands.replace(0, Expression::Ptr(new UntypedAtomicConverter(m_operands.first(), BuiltinTypes::xsDouble))); t1 = m_operands.first()->staticType()->itemType(); } else if(!BuiltinTypes::xsString->xdtTypeMatches(t1) && !BuiltinTypes::xsAnyURI->xdtTypeMatches(t1) && !BuiltinTypes::xsDayTimeDuration->xdtTypeMatches(t1) && !BuiltinTypes::xsDate->xdtTypeMatches(t1) && !BuiltinTypes::xsTime->xdtTypeMatches(t1) && !BuiltinTypes::xsDateTime->xdtTypeMatches(t1) && !BuiltinTypes::xsYearMonthDuration->xdtTypeMatches(t1)) { context->error(QtXmlPatterns::tr("The first argument to %1 cannot be of type %2.") .arg(QPatternist::formatFunction(context->namePool(), signature())) .arg(formatType(context->namePool(), m_operands.first()->staticType())), ReportContext::FORG0006, this); return me; } if(!m_operands.first()->staticType()->cardinality().allowsMany()) return m_operands.first(); // explicit scope needed in RVCT ComparingAggregator<oper, result>::prepareComparison(fetchComparator(t1, t1, context)); return me; }
AtomicComparator::ComparisonResult ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>:: detailedFlexibleCompare(const Item &it1, const Item &it2, const DynamicContext::Ptr &context) const { AtomicComparator::Ptr comp; if(m_comparator) comp = m_comparator; else { comp = fetchComparator(it1.type(), it2.type(), context); } Q_ASSERT_X(operatorID() == AtomicComparator::OperatorLessThanNaNLeast || operatorID() == AtomicComparator::OperatorLessThanNaNGreatest, Q_FUNC_INFO, "Only OperatorLessThan is currently supported for this function."); return comp->compare(it1, operatorID(), it2); }
Item ComparingAggregator<oper, result>::evaluateSingleton(const DynamicContext::Ptr &context) const { const Item::Iterator::Ptr it(m_operands.first()->evaluateSequence(context)); Item largest; while(true) { Item next(it->next()); if(!next) { return largest; } AtomicComparator::Ptr comp(comparator()); if(!comp) { ItemType::Ptr t1(next.type()); Q_ASSERT(t1); if(BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t1)) { next = cast(next, context); t1 = BuiltinTypes::xsDouble; } if(!largest) { largest = next; continue; } Q_ASSERT(largest); comp = fetchComparator(largest.type(), t1, context); Q_ASSERT(comp); } else if(!largest) { largest = next; continue; } if(comp->compare(next, operatorID(), largest) == result) { largest = applyNumericPromotion(largest, next, next); continue; } const ItemType::Ptr t(next.type()); if(BuiltinTypes::xsDouble->xdtTypeMatches(t) && next.as<Numeric>()->isNaN()) { return CommonValues::DoubleNaN; } else if(BuiltinTypes::xsFloat->xdtTypeMatches(t) && next.as<Numeric>()->isNaN()) { if(BuiltinTypes::xsDouble->xdtTypeMatches(largest.type())) return CommonValues::DoubleNaN; /* If we have a xs:double somewhere, we must promote the NaN value to xs:double, * and we really should raise error on invalid value. */ largest = it->next(); while(largest) { const ItemType::Ptr tf(largest.type()); if(BuiltinTypes::xsDouble->xdtTypeMatches(tf)) return CommonValues::DoubleNaN; else if(BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(tf)) { /* Attempt a convert, which will raise an error if it doesn't work out. */ cast(largest, context); return CommonValues::DoubleNaN; } else if(!BuiltinTypes::numeric->xdtTypeMatches(tf)) { fetchComparator(BuiltinTypes::xsFloat, tf, context); } else largest = it->next(); }; return CommonValues::FloatNaN; } else largest = applyNumericPromotion(largest, next, largest); } }