Item::Ptr PromoteAnyURIResult::next(DynamicContext *context) { Item::Ptr item = parent_->next(context); if(item.notNull()) { assert(item->isAtomicValue()); const AnyAtomicType *atomic = (const AnyAtomicType *)item.get(); // 4. For each item of type xs:anyURI in the atomic sequence that can be promoted to the expected atomic // type using URI promotion as described in B.1 Type Promotion, the promotion is done. if(atomic->getPrimitiveTypeIndex() == AnyAtomicType::ANY_URI) { try { item = atomic->castAs(AnyAtomicType::STRING, context); } catch (XPath2TypeCastException &e) { XQThrow(XPath2ErrorException, X("SequenceType::AtomicTypeConvertFunctionArgResult::next"), X("AnyURI type promotion failed (for promotable type)")); } catch (const XMLException& e) { XQThrow(XPath2ErrorException, X("SequenceType::AtomicTypeConvertFunctionArgResult::next"), X("AnyURI type promotion failed (for promotable type)")); } } } else { parent_ = 0; } return item; }
Item::Ptr PromoteNumericResult::next(DynamicContext *context) { Item::Ptr item = parent_->next(context); if(item.notNull()) { assert(item->isAtomicValue()); const AnyAtomicType *atomic = (const AnyAtomicType *)item.get(); // 3. For each numeric item in the atomic sequence that can be promoted to the expected atomic type using // the promotion rules in B.1 Type Promotion, the promotion is done. if(atomic->isNumericValue()) { try { const Numeric::Ptr promotedType = ((const Numeric*)atomic)-> promoteTypeIfApplicable(typeIndex_, context); if(promotedType.notNull()) { item = promotedType; } } catch (XPath2TypeCastException &e) { XQThrow(XPath2ErrorException, X("SequenceType::AtomicTypeConvertFunctionArgResult::next"), X("Numeric type promotion failed (for promotable type)")); } catch (const XMLException& e) { XQThrow(XPath2ErrorException, X("SequenceType::AtomicTypeConvertFunctionArgResult::next"), X("Numeric type promotion failed (for promotable type)")); } } } else { parent_ = 0; } return item; }
Item::Ptr PromoteUntypedResult::next(DynamicContext *context) { Item::Ptr item = parent_->next(context); if(item.notNull()) { assert(item->isAtomicValue()); const AnyAtomicType *atomic = (const AnyAtomicType *)item.get(); // 2. Each item in the atomic sequence that is of type xdt:untypedAtomic is cast to the expected atomic // type. For built-in functions where the expected type is specified as numeric, arguments of type // xdt:untypedAtomic are cast to xs:double. if(atomic->getPrimitiveTypeIndex() == AnyAtomicType::UNTYPED_ATOMIC) { try { if(isPrimitive_) { item = atomic->castAs(typeIndex_, 0, 0, context); } else { item = atomic->castAs(typeIndex_, uri_, name_, context); } } catch(XPath2TypeCastException &e) { if(e.getXQueryLine() == 0) e.setXQueryPosition(this); throw; } } } else { parent_ = 0; } return item; }
virtual Item::Ptr next(DynamicContext *context) { Item::Ptr item = parent_->next(context); if(item.notNull() && item->isFunction() && !itemType_->matches((FunctionRef::Ptr)item, context)) { XPath2MemoryManager *mm = context->getMemoryManager(); VarStoreImpl scope(mm, context->getVariableStore()); scope.setVar(0, XQFunctionCoercion::funcVarName, item); AutoVariableStoreReset vsReset(context, &scope); // funcConvert_ only returns one item item = funcConvert_->createResult(context)->next(context); } return item; }
Sequence FunctionReplace::createSequence(DynamicContext* context, int flags) const { XPath2MemoryManager* memMgr = context->getMemoryManager(); const XMLCh* input = XMLUni::fgZeroLenString; Item::Ptr inputString = getParamNumber(1,context)->next(context); if(inputString.notNull()) input = inputString->asString(context); const XMLCh *pattern = getParamNumber(2,context)->next(context)->asString(context); const XMLCh *replacement = getParamNumber(3,context)->next(context)->asString(context); const XMLCh *ptr; for(ptr = replacement; *ptr != chNull; ++ptr) { if(*ptr == chDollarSign) { ++ptr; //check that after the '$' is a digit if(!XMLString::isDigit(*ptr)) XQThrow(FunctionException, X("FunctionReplace::createSequence"), X("Invalid replacement pattern - '$' without following digit [err:FORX0004]")); } else if(*ptr == chBackSlash) { ++ptr; //check that after the '\' is a '$' or '\' if(*ptr != chDollarSign && *ptr != chBackSlash) { XQThrow(FunctionException, X("FunctionReplace::createSequence"), X("Invalid replacement pattern - '\\' without following '$' or '\\' [err:FORX0004]")); } } } const XMLCh *options = XMLUni::fgZeroLenString; if(getNumArgs()>3) options=getParamNumber(4,context)->next(context)->asString(context); //Check that the options are valid - throw an exception if not (can have s,m,i and x) //Note: Are allowed to duplicate the letters. const XMLCh* cursor=options; for(; *cursor != 0; ++cursor){ switch(*cursor) { case chLatin_s: case chLatin_m: case chLatin_i: case chLatin_x: break; default: XQThrow(FunctionException, X("FunctionReplace::createSequence"),X("Invalid regular expression flags [err:FORX0001].")); } } // Now attempt to replace try { AutoDeallocate<const XMLCh> result(replace(input, pattern, replacement, options, memMgr), memMgr); return Sequence(context->getItemFactory()->createString(result.get(), context), memMgr); } catch (ParseException &e){ XMLBuffer buf(1023, memMgr); buf.set(X("Invalid regular expression: ")); buf.append(e.getMessage()); buf.append(X(" [err:FORX0002]")); XQThrow(FunctionException, X("FunctionReplace::createSequence"), buf.getRawBuffer()); } catch (RuntimeException &e){ if(e.getCode()==XMLExcepts::Regex_RepPatMatchesZeroString) XQThrow(FunctionException, X("FunctionReplace::createSequence"), X("The pattern matches the zero-length string [err:FORX0003]")); else if(e.getCode()==XMLExcepts::Regex_InvalidRepPattern) XQThrow(FunctionException, X("FunctionReplace::createSequence"), X("Invalid replacement pattern [err:FORX0004]")); else XQThrow(FunctionException, X("FunctionReplace::createSequence"), e.getMessage()); } // Never happens }
Item::Ptr SequenceType::OccurrenceMatchesResult::next(DynamicContext *context) { Item::Ptr item = _parent->next(context); // "SequenceType matching between a given value and a given SequenceType is performed as follows: // If the SequenceType is empty, the match succeeds only if the value is an empty sequence." if(_seqType->getItemType() == NULL && item.notNull()) { XMLBuffer buf; buf.set(X("Sequence does not match type ")); _seqType->toBuffer(buf); buf.append(X(" - the sequence contains items [")); buf.append(X(" [")); buf.append(_errorCode); buf.append(X("]")); XQThrow(XPath2TypeMatchException, X("SequenceType::OccurrenceMatchesResult::next"), buf.getRawBuffer()); } // "If the SequenceType contains an ItemType and an OccurrenceIndicator, the match succeeds only if // the number of items in the value matches the OccurrenceIndicator and each of these items matches the ItemType. " if(_seqType->getItemType() && (_seqType->getOccurrenceIndicator() == PLUS || _seqType->getOccurrenceIndicator() == EXACTLY_ONE) && item.isNull()) { XMLBuffer buf; buf.set(X("Sequence does not match type ")); _seqType->toBuffer(buf); buf.append(X(" - the sequence does not contain items [")); buf.append(_errorCode); buf.append(X("]")); XQThrow(XPath2TypeMatchException, X("SequenceType::OccurrenceMatchesResult::next"), buf.getRawBuffer()); } // "If the SequenceType is an ItemType with no OccurrenceIndicator, the match succeeds only if // the value contains precisely one item and that item matches the ItemType " if(_seqType->getItemType() && (_seqType->getOccurrenceIndicator() == EXACTLY_ONE || _seqType->getOccurrenceIndicator() == QUESTION_MARK) && item.notNull()) { // Do the tests on the number of items up front, // since often functions that cast to a single or // optional item only call next once. - jpcs Item::Ptr second = _parent->next(context); if(second.isNull()) { _parent = 0; } else { XMLBuffer buf; buf.set(X("Sequence does not match type ")); _seqType->toBuffer(buf); buf.append(X(" - the sequence contains more than one item [")); buf.append(_errorCode); buf.append(X("]")); XQThrow(XPath2TypeMatchException, X("SequenceType::OccurrenceMatchesResult::next"), buf.getRawBuffer()); } } if(item.isNull()) { *resultPointer_ = 0; } else { *resultPointer_ = _parent; } return item; }