Exemple #1
0
void CastingPlatform<TSubClass, issueError>::issueCastError(const Item &validationError,
                                                            const Item &sourceValue,
                                                            const ReportContext::Ptr &context) const
{
    Q_ASSERT(validationError);
    Q_ASSERT(context);
    Q_ASSERT(validationError.isAtomicValue());
    Q_ASSERT(validationError.template as<AtomicValue>()->hasError());

    const ValidationError::Ptr err(validationError.template as<ValidationError>());
    QString msg(err->message());

    if(msg.isNull())
    {
        msg = QtXmlPatterns::tr("It's not possible to cast the value %1 of type %2 to %3")
                 .arg(formatData(sourceValue.stringValue()))
                 .arg(formatType(context->namePool(), sourceValue.type()))
                 .arg(formatType(context->namePool(), targetType()));
    }
    else
    {
        Q_ASSERT(!msg.isEmpty());
        msg = QtXmlPatterns::tr("Failure when casting from %1 to %2: %3")
                 .arg(formatType(context->namePool(), sourceValue.type()))
                 .arg(formatType(context->namePool(), targetType()))
                 .arg(msg);
    }

    /* If m_errorCode is FORG0001, we assume our sub-classer doesn't have a
     * special wish about error code, so then we use the error object's code.
     */
    context->error(msg, m_errorCode == ReportContext::FORG0001 ? err->errorCode() : m_errorCode,
                   static_cast<const TSubClass*>(this));
}
QRegExp PatternPlatform::parsePattern(const QString &patternP,
                                      const ReportContext::Ptr &context,
                                      const SourceLocationReflection *const location)
{
    if(patternP == QLatin1String("(.)\\3") ||
       patternP == QLatin1String("\\3")    ||
       patternP == QLatin1String("(.)\\2"))
    {
        context->error(QLatin1String("We don't want to hang infinitely on K2-MatchesFunc-9, "
                                     "10 and 11."),
                       ReportContext::FOER0000, location);
        return QRegExp();
    }

    QString rewrittenPattern(patternP);

    /* We rewrite some well known patterns to QRegExp style here. Note that
     * these character classes only works in the ASCII range, and fail for
     * others. This support needs to be in QRegExp, since it's about checking
     * QChar::category(). */
    rewrittenPattern.replace(QLatin1String("[\\i-[:]]"), QLatin1String("[a-zA-Z_]"));
    rewrittenPattern.replace(QLatin1String("[\\c-[:]]"), QLatin1String("[a-zA-Z0-9_\\-\\.]"));

    QRegExp retval(rewrittenPattern, Qt::CaseSensitive, QRegExp::W3CXmlSchema11);

    if(retval.isValid())
        return retval;
    else
    {
        context->error(QtXmlPatterns::tr("%1 is an invalid regular expression pattern: %2")
                                        .arg(formatExpression(patternP), retval.errorString()),
                                   ReportContext::FORX0002, location);
        return QRegExp();
    }
}
Exemple #3
0
void Template::raiseXTSE0680(const ReportContext::Ptr &context,
                             const QXmlName &name,
                             const SourceLocationReflection *const reflection)
{
    context->error(QtXmlPatterns::tr("The parameter %1 is passed, but no corresponding %2 exists.")
                                     .arg(formatKeyword(context->namePool(), name),
                                          formatKeyword(QLatin1String("xsl:param"))),
                   ReportContext::XTSE0680,
                   reflection);
}
AtomicComparator::Ptr ComparisonPlatform<TSubClass, issueError, comparisonType, errorCode>::
fetchComparator(const ItemType::Ptr &t1,
                const ItemType::Ptr &t2,
                const ReportContext::Ptr &context) const
{
    Q_ASSERT(t1);
    Q_ASSERT(t2);

    if(*BuiltinTypes::xsAnyAtomicType == *t1    ||
       *BuiltinTypes::xsAnyAtomicType == *t2    ||
       *BuiltinTypes::item == *t1               ||
       *BuiltinTypes::item == *t2               ||
       *BuiltinTypes::numeric == *t1            ||
       *BuiltinTypes::numeric == *t2            ||
       *CommonSequenceTypes::Empty == *t1       ||
       *CommonSequenceTypes::Empty == *t2)
    {
        /* The static type of(at least) one of the operands could not
         * be narrowed further, so we do the operator
         * lookup at runtime.
         */
        return AtomicComparator::Ptr();
    }

    const AtomicComparatorLocator::Ptr locator
        (static_cast<const AtomicType *>(t1.data())->comparatorLocator());

    if(!locator)
    {
        if(issueError)
        {
            context->error(QtXmlPatterns::tr("No comparisons can be done involving the type %1.")
                                            .arg(formatType(context->namePool(), t1)),
                                       errorCode, static_cast<const TSubClass *>(this)->actualReflection());
        }
        return AtomicComparator::Ptr();
    }

    const AtomicComparator::Ptr comp(static_cast<const AtomicType *>(t2.data())->accept(locator, operatorID(),
                                                                                       static_cast<const TSubClass *>(this)->actualReflection()));

    if(comp)
        return comp;
    else if(issueError)
    {
        context->error(QtXmlPatterns::tr("Operator %1 is not available between atomic values of type %2 and %3.")
                                        .arg(formatKeyword(AtomicComparator::displayName(operatorID(),
                                                                                         comparisonType)),
                                             formatType(context->namePool(), t1),
                                             formatType(context->namePool(), t2)),
                                   errorCode, static_cast<const TSubClass *>(this)->actualReflection());
    }

    return AtomicComparator::Ptr();
}
Exemple #5
0
void CastingPlatform<TSubClass, issueError>::checkTargetType(const ReportContext::Ptr &context) const
{
    Q_ASSERT(context);

    const ItemType::Ptr tType(targetType());
    Q_ASSERT(tType);
    Q_ASSERT(tType->isAtomicType());
    const AtomicType::Ptr asAtomic(tType);

    /* This catches casting to xs:NOTATION and xs:anyAtomicType. */
    if(asAtomic->isAbstract())
    {
        context->error(QtXmlPatterns::tr("Casting to %1 is not possible because it "
                                     "is an abstract type, and can therefore never be instantiated.")
                                .arg(formatType(context->namePool(), tType)),
                          ReportContext::XPST0080,
                          static_cast<const TSubClass*>(this));
    }
}
Exemple #6
0
AtomicCaster::Ptr CastingPlatform<TSubClass, issueError>::locateCaster(const ItemType::Ptr &sourceType,
                                                                       const ReportContext::Ptr &context,
                                                                       bool &castImpossible,
                                                                       const SourceLocationReflection *const location,
                                                                       const ItemType::Ptr &targetType)
{
    Q_ASSERT(sourceType);
    Q_ASSERT(targetType);

    const AtomicCasterLocator::Ptr locator(static_cast<AtomicType *>(
            targetType.data())->casterLocator());
    if(!locator)
    {
        if(issueError)
        {
            context->error(QtXmlPatterns::tr("No casting is possible with %1 as the target type.")
                                        .arg(formatType(context->namePool(), targetType)),
                                       ReportContext::XPTY0004, location);
        }
        else
            castImpossible = true;

        return AtomicCaster::Ptr();
    }

    const AtomicCaster::Ptr caster(static_cast<const AtomicType *>(sourceType.data())->accept(locator, location));
    if(!caster)
    {
        if(issueError)
        {
            context->error(QtXmlPatterns::tr("It is not possible to cast from %1 to %2.")
                                            .arg(formatType(context->namePool(), sourceType))
                                            .arg(formatType(context->namePool(), targetType)),
                                       ReportContext::XPTY0004, location);
        }
        else
            castImpossible = true;

        return AtomicCaster::Ptr();
    }

    return caster;
}
bool AccelTreeResourceLoader::retrieveDocument(QIODevice *source, const QUrl &documentUri, const ReportContext::Ptr &context)
{
    Q_ASSERT(source);
    Q_ASSERT(source->isReadable());
    Q_ASSERT(documentUri.isValid());

    AccelTreeBuilder<true> builder(documentUri, documentUri, m_namePool, context.data(), m_features);

    bool success = false;
    success = streamToReceiver(source, &builder, m_namePool, context, documentUri);

    m_loadedDocuments.insert(documentUri, builder.builtDocument());

    return success;
}
bool AccelTreeResourceLoader::retrieveDocument(const QUrl &uri,
                                               const ReportContext::Ptr &context)
{
    Q_ASSERT(uri.isValid());
    AccelTreeBuilder<true> builder(uri, uri, m_namePool, context.data(), m_features);

    const AutoPtr<QNetworkReply> reply(load(uri, m_networkAccessDelegator, context));

    if(!reply)
        return false;

    bool success = false;
    success = streamToReceiver(reply.data(), &builder, m_namePool, context, uri);

    m_loadedDocuments.insert(uri, builder.builtDocument());
    return success;
}
bool AccelTreeResourceLoader::retrieveUnparsedText(const QUrl &uri,
                                                   const QString &encoding,
                                                   const ReportContext::Ptr &context,
                                                   const SourceLocationReflection *const where)
{
    const AutoPtr<QNetworkReply> reply(load(uri, m_networkAccessDelegator, context));

    if(!reply)
        return false;

    const QTextCodec * codec;
    if(encoding.isEmpty())
    {
        /* XSL Transformations (XSLT) Version 2.0 16.2 Reading Text Files:
         *
         * "if the media type of the resource is text/xml or application/xml
         * (see [RFC2376]), or if it matches the conventions text/\*+xml or
         * application/\*+xml (see [RFC3023] and/or its successors), then the
         * encoding is recognized as specified in [XML 1.0]"
         */
        codec = QTextCodec::codecForMib(106);
    }
    else
    {
        codec = QTextCodec::codecForName(encoding.toLatin1());
        if(codec && context)
        {
            context->error(QtXmlPatterns::tr("%1 is an unsupported encoding.").arg(formatURI(encoding)),
                           ReportContext::XTDE1190,
                           where);
        }
        else
            return false;
    }

    QTextCodec::ConverterState converterState;
    const QByteArray inData(reply->readAll());
    const QString result(codec->toUnicode(inData.constData(), inData.length(), &converterState));

    if(converterState.invalidChars)
    {
        if(context)
        {
            context->error(QtXmlPatterns::tr("%1 contains octets which are disallowed in "
                                             "the requested encoding %2.").arg(formatURI(uri),
                                                                               formatURI(encoding)),
                           ReportContext::XTDE1190,
                           where);
        }
        else
            return false;
    }

    const int len = result.length();
    /* This code is a candidate for threading. Divide and conqueror. */
    for(int i = 0; i < len; ++i)
    {
        if(!QXmlUtils::isChar(result.at(i)))
        {
            if(context)
            {
                context->error(QtXmlPatterns::tr("The codepoint %1, occurring in %2 using encoding %3, "
                                                 "is an invalid XML character.").arg(formatData(result.at(i)),
                                                                                     formatURI(uri),
                                                                                     formatURI(encoding)),
                               ReportContext::XTDE1190,
                               where);
            }
            else
                return false;
        }
    }

    m_unparsedTexts.insert(qMakePair(uri, encoding), result);
    return true;
}
bool AccelTreeResourceLoader::streamToReceiver(QIODevice *const dev,
                                               AccelTreeBuilder<true> *const receiver,
                                               const NamePool::Ptr &np,
                                               const ReportContext::Ptr &context,
                                               const QUrl &uri)
{
    Q_ASSERT(dev);
    Q_ASSERT(receiver);
    Q_ASSERT(np);

    QXmlStreamReader reader(dev);

    /* Optimize: change NamePool to take QStringRef such that we don't have to call toString() below. That
     * will save us a gazillion of temporary QStrings. */

    while(!reader.atEnd())
    {
        reader.readNext();

        switch(reader.tokenType())
        {
            case QXmlStreamReader::StartElement:
            {
                /* Send the name. */
                receiver->startElement(np->allocateQName(reader.namespaceUri().toString(), reader.name().toString(),
                                                         reader.prefix().toString()), reader.lineNumber(), reader.columnNumber());

                /* Send namespace declarations. */
                const QXmlStreamNamespaceDeclarations &nss = reader.namespaceDeclarations();

                /* The far most common case, is for it to be empty. */
                if(!nss.isEmpty())
                {
                    const int len = nss.size();

                    for(int i = 0; i < len; ++i)
                    {
                        const QXmlStreamNamespaceDeclaration &ns = nss.at(i);
                        receiver->namespaceBinding(np->allocateBinding(ns.prefix().toString(), ns.namespaceUri().toString()));
                    }
                }

                /* Send attributes. */
                const QXmlStreamAttributes &attrs = reader.attributes();
                const int len = attrs.size();

                for(int i = 0; i < len; ++i)
                {
                    const QXmlStreamAttribute &attr = attrs.at(i);

                    receiver->attribute(np->allocateQName(attr.namespaceUri().toString(), attr.name().toString(),
                                                          attr.prefix().toString()),
                                        attr.value());
                }

                continue;
            }
            case QXmlStreamReader::EndElement:
            {
                receiver->endElement();
                continue;
            }
            case QXmlStreamReader::Characters:
            {
                if(reader.isWhitespace())
                    receiver->whitespaceOnly(reader.text());
                else
                    receiver->characters(reader.text());

                continue;
            }
            case QXmlStreamReader::Comment:
            {
                receiver->comment(reader.text().toString());
                continue;
            }
            case QXmlStreamReader::ProcessingInstruction:
            {
                receiver->processingInstruction(np->allocateQName(QString(), reader.processingInstructionTarget().toString()),
                                                reader.processingInstructionData().toString());
                continue;
            }
            case QXmlStreamReader::StartDocument:
            {
                receiver->startDocument();
                continue;
            }
            case QXmlStreamReader::EndDocument:
            {
                receiver->endDocument();
                continue;
            }
            case QXmlStreamReader::EntityReference:
            /* Fallthrough. */
            case QXmlStreamReader::DTD:
            {
                /* We just ignore any DTD and entity references. */
                continue;
            }
            case QXmlStreamReader::Invalid:
            {
                if(context)
                    context->error(escape(reader.errorString()), ReportContext::FODC0002, QSourceLocation(uri, reader.lineNumber(), reader.columnNumber()));

                return false;
            }
            case QXmlStreamReader::NoToken:
            {
                Q_ASSERT_X(false, Q_FUNC_INFO,
                           "This token is never expected to be received.");
                return false;
            }
        }
    }

    return true;
}
Exemple #11
0
AtomicMathematician::Ptr
ArithmeticExpression::fetchMathematician(Expression::Ptr &op1,
        Expression::Ptr &op2,
        const AtomicMathematician::Operator op,
        const bool issueError,
        const ReportContext::Ptr &context,
        const SourceLocationReflection *const reflection,
        const ReportContext::ErrorCode code,
        const bool isCompat)
{
    ItemType::Ptr t1(op1->staticType()->itemType());
    ItemType::Ptr t2(op2->staticType()->itemType());

    if(BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t1)
            || (isCompat && (BuiltinTypes::xsString->xdtTypeMatches(t1)
                             || BuiltinTypes::xsDecimal->xdtTypeMatches(t1))))
    {
        op1 = Expression::Ptr(new UntypedAtomicConverter(op1, BuiltinTypes::xsDouble));
        /* The types might have changed, reload. */
        t1 = op1->staticType()->itemType();
    }

    if(BuiltinTypes::xsUntypedAtomic->xdtTypeMatches(t2)
            || (isCompat && (BuiltinTypes::xsString->xdtTypeMatches(t1)
                             || BuiltinTypes::xsDecimal->xdtTypeMatches(t1))))
    {
        op2 = Expression::Ptr(new UntypedAtomicConverter(op2, BuiltinTypes::xsDouble));
        /* The types might have changed, reload. */
        t2 = op2->staticType()->itemType();
    }

    const AtomicMathematicianLocator::Ptr locator
    (static_cast<const AtomicType *>(t1.data())->mathematicianLocator());

    if(!locator)
    {
        if(!issueError)
            return AtomicMathematician::Ptr();

        context->error(QtXmlPatterns::tr(
                           "Operator %1 cannot be used on type %2.")
                       .arg(formatKeyword(AtomicMathematician::displayName(op)))
                       .arg(formatType(context->namePool(), t1)),
                       code, reflection);
        return AtomicMathematician::Ptr();
    }

    const AtomicMathematician::Ptr comp
    (static_cast<const AtomicType *>(t2.data())->accept(locator, op, reflection));

    if(comp)
        return comp;

    if(!issueError)
        return AtomicMathematician::Ptr();

    context->error(QtXmlPatterns::tr("Operator %1 cannot be used on "
                                     "atomic values of type %2 and %3.")
                   .arg(formatKeyword(AtomicMathematician::displayName(op)))
                   .arg(formatType(context->namePool(), t1))
                   .arg(formatType(context->namePool(), t2)),
                   code, reflection);
    return AtomicMathematician::Ptr();
}