#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 "../exceptions/SequenceException.hpp" #include #include "../utils/NumUtils.hpp" #include #include #include #include #include #include Sequence::Sequence(XPath2MemoryManager* memMgr) : _itemList(PathanAllocator(memMgr)), _memMgr(memMgr) { } Sequence::~Sequence() { //no-op } Sequence::Sequence(const Item* item, XPath2MemoryManager* memMgr) : _itemList(1, item, PathanAllocator(memMgr)), _memMgr(memMgr) { } Sequence::Sequence(const Sequence & s) : _itemList(s._itemList), _memMgr(s._memMgr) { } Sequence::Sequence(const Sequence &s, XPath2MemoryManager* memMgr) : _itemList(PathanAllocator(memMgr)), _memMgr(memMgr) { joinSequence(s); } Sequence::Sequence(unsigned int n, XPath2MemoryManager* memMgr) : _itemList(PathanAllocator(memMgr)), _memMgr(memMgr) { _itemList.reserve(n); } Sequence & Sequence::operator=(const Sequence & s) { if( this != &s ) { // no self-assignment _itemList = s._itemList; } return *this; } Sequence::Sequence(const XERCES_CPP_NAMESPACE_QUALIFIER DOMNodeList *domList, XPath2MemoryManager* memMgr) : _itemList(PathanAllocator(memMgr)), _memMgr(memMgr) { unsigned int listSize=domList->getLength(); _itemList.reserve(listSize); for(unsigned int i = 0; i < listSize; i++) { _itemList.push_back(memMgr->createNode(domList->item(i))); } } void Sequence::addItemFront(const Item* item) { //This is a hack since the redhat 6.2 deque warns with push_front _itemList.insert(_itemList.begin(), item); } // returns the first item in the Sequence, or null if it is empty const Item* Sequence::first() const { assert(!isEmpty()); // should not be asking for elements if the list is empty return _itemList[0]; } // returns the second item in the Sequence, or null if it is empty const Item* Sequence::second() const { assert(!isEmpty()); // should not be asking for elements if the list is empty return _itemList[1]; } // might return NULL const Item* Sequence::item(unsigned int index) const { return _itemList[index]; } const Item* Sequence::item(const ATDecimalOrDerived* index) const { if(index->isNegative()) { DSLthrow(SequenceException,X("Sequence:item"),X("Index less than zero")); } return item(NumUtils::MAPMtoInt(index->asMAPM())); } void Sequence::clear(void) { _itemList.clear(); } Sequence::iterator Sequence::begin(void) { return _itemList.begin(); } Sequence::iterator Sequence::end(void) { return _itemList.end(); } Sequence::const_iterator Sequence::begin(void) const { return _itemList.begin(); } Sequence::const_iterator Sequence::end(void) const { return _itemList.end(); } Sequence::reverse_iterator Sequence::rbegin(void) { return _itemList.rbegin(); } Sequence::reverse_iterator Sequence::rend(void) { return _itemList.rend(); } Sequence::const_reverse_iterator Sequence::rbegin(void) const { return _itemList.rbegin(); } Sequence::const_reverse_iterator Sequence::rend(void) const { return _itemList.rend(); } unsigned int Sequence::getLength(void) const { return _itemList.size(); } void Sequence::addItem(const Item* item) { _itemList.push_back(item); } void Sequence::joinSequence(const Sequence & s) { _itemList.insert(_itemList.end(),s._itemList.begin(),s._itemList.end()); } bool Sequence::isEmpty() const { return _itemList.empty(); } bool compareFn(const Item* first, const Item* second) { return ((const Node*)first)->lessThan((const Node*)second); } void Sequence::sortIntoDocumentOrder() { std::sort(_itemList.begin(), _itemList.end(), compareFn); } struct CollationCompare { CollationCompare(const Collation *collation, const DynamicContext *context) : _collation(collation), _context(context) {} bool operator()(const Item* arg1, const Item* arg2) const { const XMLCh* s1 = arg1->asString(_context); const XMLCh* s2 = arg2->asString(_context); return (_collation->compare(s1,s2) == -1); } const Collation *_collation; const DynamicContext *_context; }; void Sequence::sortWithCollation(const Collation *collation, const DynamicContext *context) { std::sort(_itemList.begin(), _itemList.end(), CollationCompare(collation, context)); } Sequence Sequence::atomize(const DynamicContext* context) const { // for $item in (Expr) return // typeswitch ($item) // case $value as atomic value return $value // default $node return fn:data($node) Sequence result(context->getMemoryManager()); Sequence::const_iterator end(Sequence::end()); for(const_iterator i = begin(); i != end; ++i) { if((*i)->isNode()) result.joinSequence(((const Node*)(*i))->dmTypedValue(context)); else result.addItem(*i); } return result; } Sequence Sequence::castAs(const SequenceType* sequenceType, DynamicContext* context) const { return sequenceType->castAsFunction(*this, context); } const XMLCh* Sequence::castAsSingleString(DynamicContext* context) const { static SequenceType stringType(XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgURI_SCHEMAFORSCHEMA, XERCES_CPP_NAMESPACE_QUALIFIER SchemaSymbols::fgDT_STRING); Sequence singleString = castAs(&stringType, context); return singleString.first()->asString(context); } bool Sequence::getEffectiveBooleanValue(const DynamicContext* context) const { // From $ 15.1.4 of the F&O specs: // The effective boolean value of an operand is defined as follows: // // If $arg is the empty sequence, returns false. if(isEmpty()) { return false; } // If $arg contains a single atomic value, then the function returns false if $arg is: if(getLength()==1 && first()->isAtomicValue()) { const AnyAtomicType* arg1 = (const AnyAtomicType*)first(); // The singleton xs:boolean value false. if(arg1->getPrimitiveTypeIndex() == AnyAtomicType::BOOLEAN && ((const ATBooleanOrDerived*)arg1)->isFalse()) return false; // The singleton value "" (zero-length string) of type xs:string or xdt:untypedAtomic. if((arg1->getPrimitiveTypeIndex() == AnyAtomicType::STRING || arg1->getPrimitiveTypeIndex() == AnyAtomicType::UNTYPED_ATOMIC) && XERCES_CPP_NAMESPACE_QUALIFIER XMLString::equals(arg1->asString(context), XERCES_CPP_NAMESPACE_QUALIFIER XMLUni::fgZeroLenString)) return false; // A singleton numeric value that is numerically equal to zero. if(arg1->isNumericValue()) { const Numeric* num1 = (const Numeric*)arg1; if(num1->isZero()) return false; // The singleton xs:float or xs:double value NaN. if(num1->getPrimitiveTypeIndex() == AnyAtomicType::FLOAT && ((const ATFloatOrDerived*)num1)->isNaN()) return false; if(num1->getPrimitiveTypeIndex() == AnyAtomicType::DOUBLE && ((const ATDoubleOrDerived*)num1)->isNaN()) return false; } } // In all other cases, returns true. return true; }