예제 #1
0
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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #4
0
  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;
  }
예제 #5
0
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
}
예제 #6
0
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;
}