1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
|
#include "../config/pathan_config.h"
/*
* Copyright (c) 2001, DecisionSoft Limited All rights reserved.
* Please see LICENSE.TXT for more information.
*/
#include <assert.h>
#include <xercesc/dom/DOMNode.hpp>
#include <xercesc/dom/DOMNodeList.hpp>
#include <xercesc/util/XMLString.hpp>
#include <xercesc/validators/schema/SchemaSymbols.hpp>
#include <pathan/Sequence.hpp>
#include <pathan/SequenceType.hpp>
#include <pathan/DynamicContext.hpp>
#include "../exceptions/SequenceException.hpp"
#include <pathan/XPath2Utils.hpp>
#include "../utils/NumUtils.hpp"
#include <pathan/ATDecimalOrDerived.hpp>
#include <pathan/ATBooleanOrDerived.hpp>
#include <pathan/ATFloatOrDerived.hpp>
#include <pathan/ATDoubleOrDerived.hpp>
#include <pathan/Node.hpp>
#include <pathan/Collation.hpp>
Sequence::Sequence(XPath2MemoryManager* memMgr)
: _itemList(PathanAllocator<const Item*>(memMgr)),
_memMgr(memMgr)
{
}
Sequence::~Sequence()
{
//no-op
}
Sequence::Sequence(const Item* item, XPath2MemoryManager* memMgr)
: _itemList(1, item, PathanAllocator<const Item*>(memMgr)),
_memMgr(memMgr)
{
}
Sequence::Sequence(const Sequence & s)
: _itemList(s._itemList),
_memMgr(s._memMgr)
{
}
Sequence::Sequence(const Sequence &s, XPath2MemoryManager* memMgr)
: _itemList(PathanAllocator<const Item*>(memMgr)),
_memMgr(memMgr)
{
joinSequence(s);
}
Sequence::Sequence(unsigned int n, XPath2MemoryManager* memMgr)
: _itemList(PathanAllocator<const Item*>(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<const Item*>(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());
const_iterator end(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;
}
|