Esempio n. 1
0
void DocumentConstructor::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const
{
    QAbstractXmlReceiver *const receiver = context->outputReceiver();

    DocumentContentValidator validator(receiver, context, ConstPtr(this));

    const DynamicContext::Ptr receiverContext(context->createReceiverContext(&validator));

    validator.startDocument();
    m_operand->evaluateToSequenceReceiver(receiverContext);
    validator.endDocument();
}
Item::Iterator::Ptr AxisStep::evaluateSequence(const DynamicContext::Ptr &context) const
{
    /* If we don't have a focus, it's either a bug or our parent isn't a Path
     * that have advanced the focus iterator. Hence, attempt to advance the focus on our own. */
    if(!context->contextItem())
        context->focusIterator()->next();

    Q_ASSERT(context->contextItem());

    const QXmlNodeModelIndex::Iterator::Ptr source(context->contextItem().asNode().iterate(m_axis));

    return makeItemMappingIterator<Item>(ConstPtr(this), source, context);
}
Esempio n. 3
0
Item PrefixFromQNameFN::evaluateSingleton(const DynamicContext::Ptr &context) const
{
    const QNameValue::Ptr arg(m_operands.first()->evaluateSingleton(context).as<QNameValue>());
    if(!arg)
        return Item();

    const QString prefix(context->namePool()->stringForPrefix(arg->qName().prefix()));

    if(prefix.isEmpty())
        return Item();
    else
        return AtomicString::fromValue(context->namePool()->stringForPrefix(arg->qName().prefix()));
}
Esempio n. 4
0
Item EvaluationCache<IsForGlobal>::evaluateSingleton(const DynamicContext::Ptr &context) const
{
    ItemCacheCell &cell = IsForGlobal ? context->globalItemCacheCell(m_varSlot) : context->itemCacheCell(m_varSlot);

    if(cell.cacheState == ItemCacheCell::Full)
        return cell.cachedItem;
    else
    {
        Q_ASSERT(cell.cacheState == ItemCacheCell::Empty);
        cell.cachedItem = m_operand->evaluateSingleton(IsForGlobal ? topFocusContext(context) : context);
        cell.cacheState = ItemCacheCell::Full;
        return cell.cachedItem;
    }
}
Esempio n. 5
0
void ContextNodeChecker::checkTargetNode(const QXmlNodeModelIndex &node,
                                         const DynamicContext::Ptr &context,
                                         const ReportContext::ErrorCode code) const
{
    if(node.root().kind() != QXmlNodeModelIndex::Document)
    {
        context->error(QtXmlPatterns::tr("The root node of the second argument "
                                         "to function %1 must be a document "
                                         "node. %2 is not a document node.")
                       .arg(formatFunction(context->namePool(), signature()),
                            formatData(node)),
                       code, this);
    }
}
Item AttributeConstructor::evaluateSingleton(const DynamicContext::Ptr &context) const
{
    const Item nameItem(m_operand1->evaluateSingleton(context));
    const Item content(m_operand2->evaluateSingleton(context));

    const QXmlName name(nameItem.as<QNameValue>()->qName());
    const QString value(processValue(name, content ? content.stringValue() : QString()));
    const NodeBuilder::Ptr nodeBuilder(context->nodeBuilder(QUrl()));

    nodeBuilder->attribute(name, QStringRef(&value));

    const QAbstractXmlNodeModel::Ptr nm(nodeBuilder->builtDocument());
    context->addNodeModel(nm);
    return nm->root(QXmlNodeModelIndex());
}
Item::Iterator::Ptr CardinalityVerifier::evaluateSequence(const DynamicContext::Ptr &context) const
{
    const Item::Iterator::Ptr it(m_operand->evaluateSequence(context));
    const Item next(it->next());

    if(next)
    {
        const Item next2(it->next());

        if(next2)
        {
            if(m_reqCard.allowsMany())
            {
                Item::List start;
                start.append(next);
                start.append(next2);

                return Item::Iterator::Ptr(new InsertionIterator(it, 1, makeListIterator(start)));
            }
            else
            {
                context->error(wrongCardinality(m_reqCard, Cardinality::twoOrMore()), m_errorCode, this);
                return CommonValues::emptyIterator;
            }
        }
        else
        {
            /* We might be instantiated for the empty sequence. */
            if(m_reqCard.isEmpty())
            {
                context->error(wrongCardinality(m_reqCard, Cardinality::twoOrMore()), m_errorCode, this);
                return CommonValues::emptyIterator;
            }
            else
                return makeSingletonIterator(next);
        }
    }
    else
    {
        if(m_reqCard.allowsEmpty())
            return CommonValues::emptyIterator;
        else
        {
            context->error(wrongCardinality(m_reqCard, Cardinality::twoOrMore()), m_errorCode, this);
            return CommonValues::emptyIterator;
        }
    }
}
Esempio n. 8
0
Item::Iterator::Ptr Path::evaluateSequence(const DynamicContext::Ptr &context) const
{
    /* Note, we use the old context for m_operand1. */
    const Item::Iterator::Ptr source(m_operand1->evaluateSequence(context));

    const DynamicContext::Ptr focus(context->createFocus());
    focus->setFocusIterator(source);

    const Item::Iterator::Ptr result(makeSequenceMappingIterator<Item>(ConstPtr(this), source, focus));

    if(m_checkXPTY0018)
    {
        /* This is an expensive code path, but it should happen very rarely. */

        enum FoundItem
        {
            FoundNone,
            FoundNode,
            FoundAtomicValue
        } hasFound = FoundNone;

        Item::List whenChecked;

        Item next(result->next());

        while(next)
        {
            const FoundItem found = next.isAtomicValue() ? FoundAtomicValue : FoundNode;

            if(hasFound != FoundNone && hasFound != found)
            {
                /* It's an atomic value and we've already found a node. Mixed content. */
                context->error(QtXmlPatterns::tr("The last step in a path must contain either nodes "
                                                 "or atomic values. It cannot be a mixture between the two."),
                               ReportContext::XPTY0018, this);
            }
            else
                hasFound = found;

            whenChecked.append(next);
            next = result->next();
        }

        return makeListIterator(whenChecked);
    }
    else
        return result;
}
Esempio n. 9
0
Item DocumentConstructor::evaluateSingleton(const DynamicContext::Ptr &context) const
{
    NodeBuilder::Ptr nodeBuilder(context->nodeBuilder(m_staticBaseURI));

    DocumentContentValidator validator(nodeBuilder.data(), context, ConstPtr(this));
    const DynamicContext::Ptr receiverContext(context->createReceiverContext(&validator));

    validator.startDocument();
    m_operand->evaluateToSequenceReceiver(receiverContext);
    validator.endDocument();

    const QAbstractXmlNodeModel::Ptr nm(nodeBuilder->builtDocument());
    context->addNodeModel(nm);

    return nm->root(QXmlNodeModelIndex());
}
Esempio n. 10
0
void CommentConstructor::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const
{
    const QString content(evaluateContent(context));
    QAbstractXmlReceiver *const receiver = context->outputReceiver();

    receiver->comment(content);
}
Esempio n. 11
0
        /**
         * Performs the actual tracing.
         */
        Item mapToItem(const Item &item,
                            const DynamicContext::Ptr &context)
        {
            QTextStream out(stderr);
            ++m_position;
            if(m_position == 1)
            {
                if(item)
                {
                    out << qPrintable(m_msg)
                        << " : "
                        << qPrintable(item.stringValue());
                }
                else
                {
                    out << qPrintable(m_msg)
                        << " : ("
                        << qPrintable(formatType(context->namePool(), CommonSequenceTypes::Empty))
                        << ")\n";
                    return Item();
                }
            }
            else
            {
                out << qPrintable(item.stringValue())
                    << '['
                    << m_position
                    << "]\n";
            }

            return item;
        }
void ElementConstructor::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const
{
    /* We create an OutputValidator here too. If we're serializing(a common case, unfortunately)
     * the receiver is already validating in order to catch cases where a computed attribute
     * constructor is followed by an element constructor, but in the cases where we're not serializing
     * it's necessary that we validate in this step. */
    const Item name(m_operand1->evaluateSingleton(context));
    QAbstractXmlReceiver *const receiver = context->outputReceiver();

    OutputValidator validator(receiver, context, this);
    const DynamicContext::Ptr receiverContext(context->createReceiverContext(&validator));

    receiver->startElement(name.as<QNameValue>()->qName());
    m_operand2->evaluateToSequenceReceiver(receiverContext);
    receiver->endElement();
}
Esempio n. 13
0
Item CastAs::evaluateSingleton(const DynamicContext::Ptr &context) const
{
    Q_ASSERT(context);
    const Item val(m_operand->evaluateSingleton(context));

    if(val)
        return cast(val, context);
    else
    {
        /* No item supplied, let's handle the cardinality part. */

        if(m_targetType->cardinality().allowsEmpty())
            return Item();
        else
        {
            Q_ASSERT(context);
            context->error(QtXmlPatterns::tr("Type error in cast, expected %1, "
                                             "received %2.")
                           .arg(formatType(Cardinality::exactlyOne()))
                           .arg(formatType(Cardinality::empty())),
                           ReportContext::XPTY0004, this);
            return Item();
        }
    }
}
Esempio n. 14
0
int NormalizeUnicodeFN::determineNormalizationForm(const DynamicContext::Ptr &context) const
{
    const QString strRepr(m_operands.last()->evaluateSingleton(context).stringValue().trimmed().toUpper());

    /* TODO. Put these values in a QHash for faster lookup. Keep thread safety in mind. */
    if(strRepr.isEmpty())
        return -1;
    else if(strRepr == QLatin1String("NFC"))
        return QString::NormalizationForm_C;
    else if(strRepr == QLatin1String("NFD"))
        return QString::NormalizationForm_D;
    else if(strRepr == QLatin1String("NFKC"))
        return QString::NormalizationForm_KC;
    else if(strRepr == QLatin1String("NFKD"))
        return QString::NormalizationForm_KD;
    else
    {
        /* What form is FULLY_NORMALIZED? Is a code path available for that somewhere? */
        context->error(QtXmlPatterns::tr("The normalization form %1 is "
                                         "unsupported. The supported forms are "
                                         "%2, %3, %4, and %5, and none, i.e. "
                                         "the empty string (no normalization).")
                                        .arg(formatKeyword(strRepr))
                                        .arg(formatKeyword("NFC"))
                                        .arg(formatKeyword("NFD"))
                                        .arg(formatKeyword("NFKC"))
                                        .arg(formatKeyword("NFKD")),
                                   ReportContext::FOCH0003,
                                   this);
        return QString::NormalizationForm_C; /* Silence compiler warning. */
    }
}
Item TextNodeConstructor::evaluateSingleton(const DynamicContext::Ptr &context) const
{
    const Item chars(m_operand->evaluateSingleton(context));

    if(!chars)
        return Item();

    const NodeBuilder::Ptr nodeBuilder(context->nodeBuilder(QUrl()));
    const QString &v = chars.stringValue();
    nodeBuilder->characters(QStringRef(&v));

    const QAbstractXmlNodeModel::Ptr nm(nodeBuilder->builtDocument());
    context->addNodeModel(nm);

    return nm->root(QXmlNodeModelIndex());
}
Item CodepointsToStringFN::evaluateSingleton(const DynamicContext::Ptr &context) const
{
    const Item::Iterator::Ptr it(m_operands.first()->evaluateSequence(context));

    if(!it)
        return CommonValues::EmptyString;

    QString retval;
    Item item(it->next());
    while(item)
    {
        const qint32 cp = static_cast<qint32>(item.as<Numeric>()->toInteger());

        if(!isValidXML10Char(cp))
        {
            context->error(QtXmlPatterns::tr("%1 is not a valid XML 1.0 character.")
                                            .arg(formatData(QLatin1String("0x") +
                                                          QString::number(cp, 16))),
                                       ReportContext::FOCH0001, this);

            return CommonValues::EmptyString;
        }
        retval.append(QChar(cp));
        item = it->next();
    }

    return AtomicString::fromValue(retval);
}
Item ElementConstructor::evaluateSingleton(const DynamicContext::Ptr &context) const
{
    const Item name(m_operand1->evaluateSingleton(context));

    const NodeBuilder::Ptr nodeBuilder(context->nodeBuilder(m_staticBaseURI));
    OutputValidator validator(nodeBuilder.data(), context, this, m_isXSLT);

    const DynamicContext::Ptr receiverContext(context->createReceiverContext(&validator));

    nodeBuilder->startElement(name.as<QNameValue>()->qName());
    m_operand2->evaluateToSequenceReceiver(receiverContext);
    nodeBuilder->endElement();

    const QAbstractXmlNodeModel::Ptr nm(nodeBuilder->builtDocument());
    context->addNodeModel(nm);

    return nm->root(QXmlNodeModelIndex());
}
bool DocAvailableFN::evaluateEBV(const DynamicContext::Ptr &context) const
{
    const Item itemURI(m_operands.first()->evaluateSingleton(context));

    /* 15.5.4 fn:doc reads: "If $uri is the empty sequence, the result is an empty sequence."
     * Hence, we return false for the empty sequence, because this doesn't hold true:
     * "If this function returns true, then calling fn:doc($uri) within
     * the same execution scope must return a document node."(15.5.5 fn:doc-available) */
    if(!itemURI)
        return false;

    /* These two lines are duplicated in DocFN::evaluateSingleton(), as part
     * of a workaround for solaris-cc-64. */
    const QUrl mayRela(AnyURI::toQUrl<ReportContext::FODC0005>(itemURI.stringValue(), context, this));
    const QUrl uri(context->resolveURI(mayRela, staticBaseURI()));

    Q_ASSERT(!uri.isRelative());
    return context->resourceLoader()->isDocumentAvailable(uri);
}
Esempio n. 19
0
DynamicContext::Ptr UserFunctionCallsite::bindVariables(const DynamicContext::Ptr &context) const
{
    const DynamicContext::Ptr stackContext(context->createStack());
    Q_ASSERT(stackContext);

    const Expression::List::const_iterator end(m_operands.constEnd());
    Expression::List::const_iterator it(m_operands.constBegin());

    VariableSlotID slot = m_expressionSlotOffset;

    for(; it != end; ++it)
    {
        stackContext->setExpressionVariable(slot,
                                            Expression::Ptr(new DynamicContextStore(*it, context)));
        ++slot;
    }

    return stackContext;
}
Esempio n. 20
0
Item::Iterator::Ptr EvaluationCache<IsForGlobal>::evaluateSequence(const DynamicContext::Ptr &context) const
{
    ItemSequenceCacheCell::Vector &cells = IsForGlobal ? context->globalItemSequenceCacheCells(m_varSlot) : context->itemSequenceCacheCells(m_varSlot);
    ItemSequenceCacheCell &cell = cells[m_varSlot];


    if(cell.inUse)
    {
        context->error(QtXmlPatterns::tr("Circularity detected"),
                       ReportContext::XTDE0640, this);
    }

    switch(cell.cacheState)
    {
        case ItemSequenceCacheCell::Full:
        {
            /**
             * We don't use makeListIterator() here because the MIPSPro compiler can't handle it.
             */
            return Item::Iterator::Ptr(new ListIterator<Item, Item::List>(cell.cachedItems));
        }
        case ItemSequenceCacheCell::Empty:
        {
            cell.inUse = true;
            cell.sourceIterator = m_operand->evaluateSequence(IsForGlobal ? topFocusContext(context) : context);
            cell.cacheState = ItemSequenceCacheCell::PartiallyPopulated;
            /* Fallthrough. */
        }
        case ItemSequenceCacheCell::PartiallyPopulated:
        {
            cell.inUse = false;
            Q_ASSERT_X(cells.at(m_varSlot).sourceIterator, Q_FUNC_INFO,
                       "This trigger for a cache bug which hasn't yet been analyzed.");
            return Item::Iterator::Ptr(new CachingIterator(cells, m_varSlot, IsForGlobal ? topFocusContext(context) : context));
        }
        default:
        {
            Q_ASSERT_X(false, Q_FUNC_INFO, "This path is not supposed to be run.");
            return Item::Iterator::Ptr();
        }
    }
}
Esempio n. 21
0
void AttributeConstructor::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const
{
    QAbstractXmlReceiver *const receiver = context->outputReceiver();
    const Item nameItem(m_operand1->evaluateSingleton(context));

    const Item content(m_operand2->evaluateSingleton(context));
    const QXmlName name(nameItem.as<QNameValue>()->qName());
    const QString value(processValue(name, content ? content.stringValue() : QString()));

    receiver->attribute(name, QStringRef(&value));
}
Item CardinalityVerifier::evaluateSingleton(const DynamicContext::Ptr &context) const
{
    if(m_allowsMany)
    {
        const Item::Iterator::Ptr it(m_operand->evaluateSequence(context));
        const Item item(it->next());

        if(item)
        {
            if(it->next())
            {
                context->error(wrongCardinality(m_reqCard, Cardinality::twoOrMore()),
                               m_errorCode, this);
                return Item();
            }
            else
                return item;
        }
        else if(m_reqCard.allowsEmpty())
            return Item();
        else
        {
            context->error(wrongCardinality(m_reqCard), m_errorCode, this);
            return Item();
        }
    }
    else
    {
        const Item item(m_operand->evaluateSingleton(context));

        if(item)
            return item;
        else if(m_reqCard.allowsEmpty())
            return Item();
        else
        {
            context->error(wrongCardinality(m_reqCard), m_errorCode, this);
            return Item();
        }
    }
}
Item DocFN::evaluateSingleton(const DynamicContext::Ptr &context) const
{
    const Item itemURI(m_operands.first()->evaluateSingleton(context));

    if(!itemURI)
        return Item();

    /* These two lines were previously in a separate function but are now duplicated
     * in DocAvailableFN::evaluateEBV() and DocFN::typeCheck(),
     * as part of a workaround for solaris-cc-64. DocFN::typeCheck() is in qsequencefns.cpp
     * as part of that workaround. */
    const QUrl mayRela(AnyURI::toQUrl<ReportContext::FODC0005>(itemURI.stringValue(), context, this));
    const QUrl uri(context->resolveURI(mayRela, staticBaseURI()));

    Q_ASSERT(uri.isValid());
    Q_ASSERT(!uri.isRelative());

    const Item doc(context->resourceLoader()->openDocument(uri, context));

    return doc;
}
Esempio n. 24
0
void Expression::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const
{
    QAbstractXmlReceiver *const receiver = context->outputReceiver();
    const Item::Iterator::Ptr it(evaluateSequence(context));
    Item next(it->next());

    while(next)
    {
        receiver->item(next);
        next = it->next();
    }
}
Esempio n. 25
0
Item QNameConstructor::evaluateSingleton(const DynamicContext::Ptr &context) const
{
    Q_ASSERT(context);
    const QString lexQName(m_operand->evaluateSingleton(context).stringValue());

    const QXmlName expQName(expandQName<DynamicContext::Ptr,
                                        ReportContext::XQDY0074,
                                        ReportContext::XQDY0074>(lexQName,
                                                                 context,
                                                                 m_nsResolver,
                                                                 this));
    return toItem(QNameValue::fromValue(context->namePool(), expQName));
}
Esempio n. 26
0
PatternPlatform::Flags PatternPlatform::parseFlags(const QString &flags,
                                                   const DynamicContext::Ptr &context) const
{

    if(flags.isEmpty())
        return NoFlags;

    const PatternFlag::Hash flagDescrs(flagDescriptions());
    const int len = flags.length();
    Flags retval = NoFlags;

    for(int i = 0; i < len; ++i)
    {
        const QChar flag(flags.at(i));
        const Flag specified = flagDescrs.value(flag).flag;

        if(specified != NoFlags)
        {
            retval |= specified;
            continue;
        }

        /* Generate a nice error message. */
        QString message(QtXmlPatterns::tr("%1 is an invalid flag for regular expressions. Valid flags are:")
                             .arg(formatKeyword(flag)));

        /* This is formatting, so don't bother translators with it. */
        message.append(QLatin1Char('\n'));

        const PatternFlag::Hash::const_iterator end(flagDescrs.constEnd());
        PatternFlag::Hash::const_iterator it(flagDescrs.constBegin());

        for(; it != end;)
        {
            // TODO handle bidi correctly
            // TODO format this with rich text(list/table)
            message.append(formatKeyword(it.key()));
            message.append(QLatin1String(" - "));
            message.append(it.value().description);

            ++it;
            if(it != end)
                message.append(QLatin1Char('\n'));
        }

        context->error(message, ReportContext::FORX0001, this);
        return NoFlags;
    }

    return retval;
}
Esempio n. 27
0
TemplateMode::Ptr ApplyTemplate::effectiveMode(const DynamicContext::Ptr &context) const
{
    if(m_mode)
        return m_mode;
    else
    {
        const TemplateMode::Ptr currentMode(context->currentTemplateMode());

        if(currentMode)
            return currentMode;
        else
            return m_defaultMode;
    }
}
void TextNodeConstructor::evaluateToSequenceReceiver(const DynamicContext::Ptr &context) const
{
    const Item item(m_operand->evaluateSingleton(context));

    QAbstractXmlReceiver *const receiver = context->outputReceiver();

    if(item)
    {
        const QString &v = item.stringValue();
        receiver->characters(QStringRef(&v));
    }
    else
        receiver->characters(QStringRef());
}
Esempio n. 29
0
Item Path::evaluateSingleton(const DynamicContext::Ptr &context) const
{
    /* This function is called if both operands' cardinality is exactly-one. Therefore
     * we manually go forward in the focus by calling next().
     *
     * We don't check for XPTY0018, only in evaluateSequence(), since if we're guaranteed
     * to evaluate to one item, we can only evaluate to one node or one atomic value.
     */

    /* Note, we use the old context for m_operand1. */
    const Item::Iterator::Ptr source(m_operand1->evaluateSequence(context));

    const DynamicContext::Ptr focus(context->createFocus());
    focus->setFocusIterator(source);

    /* This test is needed because if the focus is empty, we don't want to(nor can't) evaluate
     * the next step. */
    // TODO Why are we at all invoked then?
    if(source->next())
        return m_operand2->evaluateSingleton(focus);
    else
        return Item();
}
Esempio n. 30
0
Item ErrorFN::evaluateSingleton(const DynamicContext::Ptr &context) const
{
    QString msg;

    switch(m_operands.count())
    {
        case 0: /* No args. */
        {
            context->error(QtXmlPatterns::tr("%1 was called.").arg(formatFunction(context->namePool(), signature())),
                            ReportContext::FOER0000, this);
            return Item();
        }
        case 3:
        /* Fallthrough, we don't use the 'error object' param. */
        case 2:
            msg = m_operands.at(1)->evaluateSingleton(context).stringValue();
        /* Fall through. */
        case 1:
        {
            const QNameValue::Ptr qName(m_operands.first()->evaluateSingleton(context).as<QNameValue>());

            if(qName)
                context->error(msg, qName->qName(), this);
            else
                context->error(msg, ReportContext::FOER0000, this);

            return Item();
        }
        default:
        {
            Q_ASSERT_X(false, Q_FUNC_INFO,
                       "Invalid number of arguments passed to fn:error.");
            return Item();
        }
    }
}