#include "../config/pathan_config.h" /* * Copyright (c) 2001, DecisionSoft Limited All rights reserved. * Please see LICENSE.TXT for more information. */ #include #include #include #include #include #include #include #include #include #include #include #include #include /*static*/ const XMLCh GeneralComp::name[]={ XERCES_CPP_NAMESPACE_QUALIFIER chLatin_c, XERCES_CPP_NAMESPACE_QUALIFIER chLatin_o, XERCES_CPP_NAMESPACE_QUALIFIER chLatin_m, XERCES_CPP_NAMESPACE_QUALIFIER chLatin_p, XERCES_CPP_NAMESPACE_QUALIFIER chNull }; GeneralComp::GeneralComp(ComparisonOperation operation, const VectorOfDataItems &args, XPath2MemoryManager* memMgr) : DataItemOperator(name, args, memMgr) { _operation=operation; } Sequence GeneralComp::collapseTreeInternal(DynamicContext* context, int flags) const { // Atomization is applied to each operand of a general comparison. Sequence arg1 = _args[0]->collapseTree(context,DataItem::UNORDERED).atomize(context); Sequence arg2 = _args[1]->collapseTree(context,DataItem::UNORDERED).atomize(context); // The result of the comparison is true if and only if there is a pair of atomic values, // one belonging to the result of atomization of the first operand and the other belonging // to the result of atomization of the second operand, that have the required magnitude relationship. // Otherwise the result of the general comparison is false. // // The magnitude relationship between two atomic values is determined as follows: // 1) If either atomic value has the dynamic type xdt:untypedAtomic, that value is cast to a required type, // which is determined as follows: // - If the dynamic type of the other atomic value is a numeric type, the required type is xs:double. // - If the dynamic type of the other atomic value is xdt:untypedAtomic, the required type is xs:string. // - Otherwise, the required type is the dynamic type of the other atomic value. // If the cast to the required type fails, a dynamic error is raised. // 2) If XPath 1.0 compatibility mode is true, and at least one of the atomic values has a numeric type, // then both atomic values are cast to to the type xs:double. // 3) After any necessary casting, the atomic values are compared using one of the value comparison operators // eq, ne, lt, le, gt, or ge, depending on whether the general comparison operator was // =, !=, <, <=, >, or >=. The values have the required magnitude relationship if the result of this // value comparison is true. Sequence::iterator itFirst, itSecond; for(itFirst=arg1.begin();itFirst!=arg1.end();++itFirst) { for(itSecond=arg2.begin();itSecond!=arg2.end();++itSecond) { const Item* first=*itFirst; const Item* second=*itSecond; if(first->isAtomicValue() && ((const AnyAtomicType*)first)->getPrimitiveTypeIndex() == AnyAtomicType::UNTYPED_ATOMIC) { if (second->isAtomicValue() && ((const AnyAtomicType*)second)->isNumericValue()) first=((const AnyAtomicType*)first)->castAs(XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_DOUBLE, context); else if(second->isAtomicValue() && ((const AnyAtomicType*)second)->getPrimitiveTypeIndex() == AnyAtomicType::UNTYPED_ATOMIC) first=((const AnyAtomicType*)first)->castAs(XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_STRING, context); else first=((const AnyAtomicType*)first)->castAs(((const AnyAtomicType*)second)->getTypeURI(), ((const AnyAtomicType*)second)->getTypeName(), context); } if(second->isAtomicValue() && ((const AnyAtomicType*)second)->getPrimitiveTypeIndex() == AnyAtomicType::UNTYPED_ATOMIC) { if (first->isAtomicValue() && ((const AnyAtomicType*)first)->isNumericValue()) second=((const AnyAtomicType*)second)->castAs(XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_DOUBLE, context); else if(first->isAtomicValue() && ((const AnyAtomicType*)first)->getPrimitiveTypeIndex() == AnyAtomicType::UNTYPED_ATOMIC) second=((const AnyAtomicType*)second)->castAs(XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_STRING, context); else second=((const AnyAtomicType*)second)->castAs(((const AnyAtomicType*)first)->getTypeURI(), ((const AnyAtomicType*)first)->getTypeName(), context); } if(context->getXPath1CompatibilityMode() && ( (first->isAtomicValue() && ((const AnyAtomicType*)first)->isNumericValue()) || (second->isAtomicValue() && ((const AnyAtomicType*)second)->isNumericValue()) )) { first=((const AnyAtomicType*)first)->castAs(XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_DOUBLE, context); second=((const AnyAtomicType*)second)->castAs(XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_DOUBLE, context); } bool result=false; switch(_operation) { case EQUAL: result=Equals::equals(first,second,context); break; case NOT_EQUAL: result=NotEquals::not_equals(first,second,context); break; case LESS_THAN: result=LessThan::less_than(first,second,context); break; case LESS_THAN_EQUAL: result=LessThanEqual::less_than_equal(first,second,context); break; case GREATER_THAN: result=GreaterThan::greater_than(first,second,context); break; case GREATER_THAN_EQUAL: result=GreaterThanEqual::greater_than_equal(first,second,context); break; default: assert(false); } if(result) return Sequence(DatatypeFactory::POD2AT::createBoolean(context->getMemoryManager(), true, context), context->getMemoryManager()); } } return Sequence(DatatypeFactory::POD2AT::createBoolean(context->getMemoryManager(), false, context), context->getMemoryManager()); } GeneralComp::ComparisonOperation GeneralComp::getOperation() const { return _operation; }