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(); } }
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(); }
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)); } }
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; }
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(); }