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; } }
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); }
AtomicComparator::Ptr ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>:: fetchComparator(const ItemType::Ptr &t1, const ItemType::Ptr &t2, const ReportContext::Ptr &context) const { Q_ASSERT(t1); Q_ASSERT(t2); if(*BuiltinTypes::xsAnyAtomicType == *t1 || *BuiltinTypes::xsAnyAtomicType == *t2 || *BuiltinTypes::item == *t1 || *BuiltinTypes::item == *t2 || *BuiltinTypes::numeric == *t1 || *BuiltinTypes::numeric == *t2 || *CommonSequenceTypes::Empty == *t1 || *CommonSequenceTypes::Empty == *t2) { /* The static type of(at least) one of the operands could not * be narrowed further, so we do the operator * lookup at runtime. */ return AtomicComparator::Ptr(); } const AtomicComparatorLocator::Ptr locator (static_cast<const AtomicType *>(t1.data())->comparatorLocator()); if(!locator) { if(issueError) { context->error(QtXmlPatterns::tr("No comparisons can be done involving the type %1.") .arg(formatType(context->namePool(), t1)), errorCode, static_cast<const TSubClass *>(this)->actualReflection()); } return AtomicComparator::Ptr(); } const AtomicComparator::Ptr comp(static_cast<const AtomicType *>(t2.data())->accept(locator, operatorID(), static_cast<const TSubClass *>(this)->actualReflection())); if(comp) return comp; else if(issueError) { context->error(QtXmlPatterns::tr("Operator %1 is not available between atomic values of type %2 and %3.") .arg(formatKeyword(AtomicComparator::displayName(operatorID(), comparisonType)), formatType(context->namePool(), t1), formatType(context->namePool(), t2)), errorCode, static_cast<const TSubClass *>(this)->actualReflection()); } return AtomicComparator::Ptr(); }
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); } }