diff options
Diffstat (limited to 'src/corelib/serialization/qxmlstreamparser_p.h')
-rw-r--r-- | src/corelib/serialization/qxmlstreamparser_p.h | 1027 |
1 files changed, 1027 insertions, 0 deletions
diff --git a/src/corelib/serialization/qxmlstreamparser_p.h b/src/corelib/serialization/qxmlstreamparser_p.h new file mode 100644 index 0000000000..1d28923a11 --- /dev/null +++ b/src/corelib/serialization/qxmlstreamparser_p.h @@ -0,0 +1,1027 @@ +/**************************************************************************** +** +** Copyright (C) 2020 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +// +// W A R N I N G +// ------------- +// +// This file is automatically generated from qxmlstream.g. +// Changes should be made to that file, not here. Any change to this file will +// be lost! +// +// To regenerate this file, run: +// qlalr --no-debug --no-lines --qt qxmlstream.g +// + +#include <QtCore/private/qglobal_p.h> +#include <qxmlstream.h> +#include "qxmlstream_p.h" +#include "qxmlutils_p.h" +#include <qstringconverter.h> + +#include <memory> + +#ifndef QXMLSTREAMPARSER_P_H +#define QXMLSTREAMPARSER_P_H + +QT_BEGIN_NAMESPACE + +#ifndef QT_NO_XMLSTREAMREADER + +bool QXmlStreamReaderPrivate::parse() +{ + // cleanup currently reported token + + switch (type) { + case QXmlStreamReader::StartElement: + name.clear(); + prefix.clear(); + qualifiedName.clear(); + namespaceUri.clear(); + publicNamespaceDeclarations.clear(); + attributes.clear(); + if (isEmptyElement) { + setType(QXmlStreamReader::EndElement); + Tag &tag = tagStack_pop(); + namespaceUri = tag.namespaceDeclaration.namespaceUri; + name = tag.name; + qualifiedName = tag.qualifiedName; + isEmptyElement = false; + return true; + } + clearTextBuffer(); + break; + case QXmlStreamReader::EndElement: + name.clear(); + prefix.clear(); + qualifiedName.clear(); + namespaceUri.clear(); + clearTextBuffer(); + break; + case QXmlStreamReader::DTD: + publicNotationDeclarations.clear(); + publicEntityDeclarations.clear(); + dtdName.clear(); + dtdPublicId.clear(); + dtdSystemId.clear(); + Q_FALLTHROUGH(); + case QXmlStreamReader::Comment: + case QXmlStreamReader::Characters: + isCDATA = false; + isWhitespace = true; + text.clear(); + clearTextBuffer(); + break; + case QXmlStreamReader::EntityReference: + text.clear(); + name.clear(); + clearTextBuffer(); + break; + case QXmlStreamReader::ProcessingInstruction: + processingInstructionTarget.clear(); + processingInstructionData.clear(); + clearTextBuffer(); + break; + case QXmlStreamReader::NoToken: + case QXmlStreamReader::Invalid: + break; + case QXmlStreamReader::StartDocument: + lockEncoding = true; + documentVersion.clear(); + documentEncoding.clear(); + if (decoder.isValid() && decoder.hasError()) { + raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content.")); + readBuffer.clear(); + return false; + } + Q_FALLTHROUGH(); + default: + clearTextBuffer(); + ; + } + + setType(QXmlStreamReader::NoToken); + + + // the main parse loop + int act, r; + + if (resumeReduction) { + act = state_stack[tos-1]; + r = resumeReduction; + resumeReduction = 0; + goto ResumeReduction; + } + + act = state_stack[tos]; + + forever { + if (token == -1 && - TERMINAL_COUNT != action_index[act]) { + uint cu = getChar(); + token = NOTOKEN; + token_char = cu == ~0U ? cu : ushort(cu); + if ((cu != ~0U) && (cu & 0xff0000)) { + token = cu >> 16; + } else switch (token_char) { + case 0xfffe: + case 0xffff: + token = ERROR; + break; + case '\r': + token = SPACE; + if (cu == '\r') { + if ((token_char = filterCarriageReturn())) { + ++lineNumber; + lastLineStart = characterOffset + readBufferPos; + break; + } + } else { + break; + } + Q_FALLTHROUGH(); + case ~0U: { + token = EOF_SYMBOL; + if (!tagsDone && !inParseEntity) { + int a = t_action(act, token); + if (a < 0) { + raiseError(QXmlStreamReader::PrematureEndOfDocumentError); + return false; + } + } + + } break; + case '\n': + ++lineNumber; + lastLineStart = characterOffset + readBufferPos; + Q_FALLTHROUGH(); + case ' ': + case '\t': + token = SPACE; + break; + case '&': + token = AMPERSAND; + break; + case '#': + token = HASH; + break; + case '\'': + token = QUOTE; + break; + case '\"': + token = DBLQUOTE; + break; + case '<': + token = LANGLE; + break; + case '>': + token = RANGLE; + break; + case '[': + token = LBRACK; + break; + case ']': + token = RBRACK; + break; + case '(': + token = LPAREN; + break; + case ')': + token = RPAREN; + break; + case '|': + token = PIPE; + break; + case '=': + token = EQ; + break; + case '%': + token = PERCENT; + break; + case '/': + token = SLASH; + break; + case ':': + token = COLON; + break; + case ';': + token = SEMICOLON; + break; + case ',': + token = COMMA; + break; + case '-': + token = DASH; + break; + case '+': + token = PLUS; + break; + case '*': + token = STAR; + break; + case '.': + token = DOT; + break; + case '?': + token = QUESTIONMARK; + break; + case '!': + token = BANG; + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + token = DIGIT; + break; + default: + if (cu < 0x20) + token = NOTOKEN; + else + token = LETTER; + break; + } + } + + act = t_action (act, token); + if (act == ACCEPT_STATE) { + // reset the parser in case someone resumes (process instructions can follow a valid document) + tos = 0; + state_stack[tos++] = 0; + state_stack[tos] = 0; + return true; + } else if (act > 0) { + if (++tos >= stack_size-1) + reallocateStack(); + + Value &val = sym_stack[tos]; + val.c = token_char; + val.pos = textBuffer.size(); + val.prefix = 0; + val.len = 1; + if (token_char) + textBuffer += QChar(token_char); + + state_stack[tos] = act; + token = -1; + + + } else if (act < 0) { + r = - act - 1; + +#if defined (QLALR_DEBUG) + int ridx = rule_index[r]; + printf ("%3d) %s ::=", r + 1, spell[rule_info[ridx]]); + ++ridx; + for (int i = ridx; i < ridx + rhs[r]; ++i) { + int symbol = rule_info[i]; + if (const char *name = spell[symbol]) + printf (" %s", name); + else + printf (" #%d", symbol); + } + printf ("\n"); +#endif + + tos -= rhs[r]; + act = state_stack[tos++]; + ResumeReduction: + switch (r) { + + case 0: + setType(QXmlStreamReader::EndDocument); + break; + + case 1: + if (type != QXmlStreamReader::Invalid) { + if (hasSeenTag || inParseEntity) { + setType(QXmlStreamReader::EndDocument); + } else { + raiseError(QXmlStreamReader::NotWellFormedError, QXmlStream::tr("Start tag expected.")); + // reset the parser + tos = 0; + state_stack[tos++] = 0; + state_stack[tos] = 0; + return false; + } + } + break; + + case 10: + entityReferenceStack.pop()->isCurrentlyReferenced = false; + if (entityReferenceStack.isEmpty()) + entityLength = 0; + clearSym(); + break; + + case 11: + if (!scanString(spell[VERSION], VERSION, false) && atEnd) { + resume(11); + return false; + } + break; + + case 12: + setType(QXmlStreamReader::StartDocument); + documentVersion = symString(6); + startDocument(); + break; + + case 13: + hasExternalDtdSubset = true; + dtdSystemId = symString(2); + break; + + case 14: + checkPublicLiteral(symString(2)); + dtdPublicId = symString(2); + dtdSystemId = symString(4); + hasExternalDtdSubset = true; + break; + + case 16: + if (!scanPublicOrSystem() && atEnd) { + resume(16); + return false; + } + dtdName = symString(3); + break; + + case 17: + case 18: + dtdName = symString(3); + Q_FALLTHROUGH(); + + case 19: + case 20: + setType(QXmlStreamReader::DTD); + text = &textBuffer; + break; + + case 21: + scanDtd = true; + break; + + case 22: + scanDtd = false; + break; + + case 37: + if (!scanString(spell[EMPTY], EMPTY, false) + && !scanString(spell[ANY], ANY, false) + && atEnd) { + resume(37); + return false; + } + break; + + case 43: + if (!scanString(spell[PCDATA], PCDATA, false) && atEnd) { + resume(43); + return false; + } + break; + + case 68: { + lastAttributeIsCData = true; + } break; + + case 78: + if (!scanAfterDefaultDecl() && atEnd) { + resume(78); + return false; + } + break; + + case 83: + sym(1) = sym(2); + lastAttributeValue.clear(); + lastAttributeIsCData = false; + if (!scanAttType() && atEnd) { + resume(83); + return false; + } + break; + + case 84: { + DtdAttribute &dtdAttribute = dtdAttributes.push(); + dtdAttribute.tagName.clear(); + dtdAttribute.isCDATA = lastAttributeIsCData; + dtdAttribute.attributePrefix = addToStringStorage(symPrefix(1)); + dtdAttribute.attributeName = addToStringStorage(symString(1)); + dtdAttribute.attributeQualifiedName = addToStringStorage(symName(1)); + dtdAttribute.isNamespaceAttribute = (dtdAttribute.attributePrefix == QLatin1String("xmlns") + || (dtdAttribute.attributePrefix.isEmpty() + && dtdAttribute.attributeName == QLatin1String("xmlns"))); + if (lastAttributeValue.isNull()) { + dtdAttribute.defaultValue.clear(); + } else { + if (dtdAttribute.isCDATA) + dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue); + else + dtdAttribute.defaultValue = addToStringStorage(lastAttributeValue.toString().simplified()); + + } + } break; + + case 88: { + if (referenceToUnparsedEntityDetected && !standalone) + break; + int n = dtdAttributes.size(); + QStringRef tagName = addToStringStorage(symName(3)); + while (n--) { + DtdAttribute &dtdAttribute = dtdAttributes[n]; + if (!dtdAttribute.tagName.isNull()) + break; + dtdAttribute.tagName = tagName; + for (int i = 0; i < n; ++i) { + if ((dtdAttributes[i].tagName.isNull() || dtdAttributes[i].tagName == tagName) + && dtdAttributes[i].attributeQualifiedName == dtdAttribute.attributeQualifiedName) { + dtdAttribute.attributeQualifiedName.clear(); // redefined, delete it + break; + } + } + } + } break; + + case 89: { + if (!scanPublicOrSystem() && atEnd) { + resume(89); + return false; + } + EntityDeclaration &entityDeclaration = entityDeclarations.push(); + entityDeclaration.clear(); + entityDeclaration.name = symString(3); + } break; + + case 90: { + if (!scanPublicOrSystem() && atEnd) { + resume(90); + return false; + } + EntityDeclaration &entityDeclaration = entityDeclarations.push(); + entityDeclaration.clear(); + entityDeclaration.name = symString(5); + entityDeclaration.parameter = true; + } break; + + case 91: { + if (!scanNData() && atEnd) { + resume(91); + return false; + } + EntityDeclaration &entityDeclaration = entityDeclarations.top(); + entityDeclaration.systemId = symString(3); + entityDeclaration.external = true; + } break; + + case 92: { + if (!scanNData() && atEnd) { + resume(92); + return false; + } + EntityDeclaration &entityDeclaration = entityDeclarations.top(); + checkPublicLiteral((entityDeclaration.publicId = symString(3))); + entityDeclaration.systemId = symString(5); + entityDeclaration.external = true; + } break; + + case 93: { + EntityDeclaration &entityDeclaration = entityDeclarations.top(); + entityDeclaration.notationName = symString(3); + if (entityDeclaration.parameter) + raiseWellFormedError(QXmlStream::tr("NDATA in parameter entity declaration.")); + } + Q_FALLTHROUGH(); + + case 94: + case 95: { + if (referenceToUnparsedEntityDetected && !standalone) { + entityDeclarations.pop(); + break; + } + EntityDeclaration &entityDeclaration = entityDeclarations.top(); + if (!entityDeclaration.external) + entityDeclaration.value = symString(2); + auto &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash; + if (!hash.contains(qToStringViewIgnoringNull(entityDeclaration.name))) { + Entity entity(entityDeclaration.name.toString(), + entityDeclaration.value.toString()); + entity.unparsed = (!entityDeclaration.notationName.isNull()); + entity.external = entityDeclaration.external; + hash.insert(qToStringViewIgnoringNull(entity.name), entity); + } + } break; + + case 96: { + setType(QXmlStreamReader::ProcessingInstruction); + int pos = sym(4).pos + sym(4).len; + processingInstructionTarget = symString(3); + if (scanUntil("?>")) { + processingInstructionData = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 2); + if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) { + raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document.")); + } + else if (!QXmlUtils::isNCName(processingInstructionTarget)) + raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.") + .arg(processingInstructionTarget)); + } else if (type != QXmlStreamReader::Invalid){ + resume(96); + return false; + } + } break; + + case 97: + setType(QXmlStreamReader::ProcessingInstruction); + processingInstructionTarget = symString(3); + if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) + raiseWellFormedError(QXmlStream::tr("Invalid processing instruction name.")); + break; + + case 98: + if (!scanAfterLangleBang() && atEnd) { + resume(98); + return false; + } + break; + + case 99: + if (!scanUntil("--")) { + resume(99); + return false; + } + break; + + case 100: { + setType(QXmlStreamReader::Comment); + int pos = sym(1).pos + 4; + text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3); + } break; + + case 101: { + setType(QXmlStreamReader::Characters); + isCDATA = true; + isWhitespace = false; + int pos = sym(2).pos; + if (scanUntil("]]>", -1)) { + text = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 3); + } else { + resume(101); + return false; + } + } break; + + case 102: { + if (!scanPublicOrSystem() && atEnd) { + resume(102); + return false; + } + NotationDeclaration ¬ationDeclaration = notationDeclarations.push(); + notationDeclaration.name = symString(3); + } break; + + case 103: { + NotationDeclaration ¬ationDeclaration = notationDeclarations.top(); + notationDeclaration.systemId = symString(3); + notationDeclaration.publicId.clear(); + } break; + + case 104: { + NotationDeclaration ¬ationDeclaration = notationDeclarations.top(); + notationDeclaration.systemId.clear(); + checkPublicLiteral((notationDeclaration.publicId = symString(3))); + } break; + + case 105: { + NotationDeclaration ¬ationDeclaration = notationDeclarations.top(); + checkPublicLiteral((notationDeclaration.publicId = symString(3))); + notationDeclaration.systemId = symString(5); + } break; + + case 129: + isWhitespace = false; + Q_FALLTHROUGH(); + + case 130: + sym(1).len += fastScanContentCharList(); + if (atEnd && !inParseEntity) { + resume(130); + return false; + } + break; + + case 139: + if (!textBuffer.isEmpty()) { + setType(QXmlStreamReader::Characters); + text = &textBuffer; + } + break; + + case 140: + case 141: + clearSym(); + break; + + case 142: + case 143: + sym(1) = sym(2); + break; + + case 144: + case 145: + case 146: + case 147: + sym(1).len += sym(2).len; + break; + + case 173: + if (normalizeLiterals) + textBuffer.data()[textBuffer.size()-1] = QLatin1Char(' '); + break; + + case 174: + sym(1).len += fastScanLiteralContent(); + if (atEnd) { + resume(174); + return false; + } + break; + + case 175: { + if (!QXmlUtils::isPublicID(symString(1))) { + raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1))); + resume(175); + return false; + } + } break; + + case 176: + case 177: + clearSym(); + break; + + case 178: + case 179: + sym(1) = sym(2); + break; + + case 180: + case 181: + case 182: + case 183: + sym(1).len += sym(2).len; + break; + + case 213: + case 214: + clearSym(); + break; + + case 215: + case 216: + sym(1) = sym(2); + lastAttributeValue = symString(1); + break; + + case 217: + case 218: + case 219: + case 220: + sym(1).len += sym(2).len; + break; + + case 229: { + QStringRef prefix = symPrefix(1); + if (prefix.isEmpty() && symString(1) == QLatin1String("xmlns") && namespaceProcessing) { + NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push(); + namespaceDeclaration.prefix.clear(); + + const QStringRef ns(symString(5)); + if (ns == QLatin1String("http://www.w3.org/2000/xmlns/") || + ns == QLatin1String("http://www.w3.org/XML/1998/namespace")) + raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration.")); + else + namespaceDeclaration.namespaceUri = addToStringStorage(ns); + } else { + Attribute &attribute = attributeStack.push(); + attribute.key = sym(1); + attribute.value = sym(5); + + QStringRef attributeQualifiedName = symName(1); + bool normalize = false; + for (int a = 0; a < dtdAttributes.size(); ++a) { + DtdAttribute &dtdAttribute = dtdAttributes[a]; + if (!dtdAttribute.isCDATA + && dtdAttribute.tagName == qualifiedName + && dtdAttribute.attributeQualifiedName == attributeQualifiedName + ) { + normalize = true; + break; + } + } + if (normalize) { + // normalize attribute value (simplify and trim) + int pos = textBuffer.size(); + int n = 0; + bool wasSpace = true; + for (int i = 0; i < attribute.value.len; ++i) { + QChar c = textBuffer.at(attribute.value.pos + i); + if (c.unicode() == ' ') { + if (wasSpace) + continue; + wasSpace = true; + } else { + wasSpace = false; + } + textBuffer += textBuffer.at(attribute.value.pos + i); + ++n; + } + if (wasSpace) + while (n && textBuffer.at(pos + n - 1).unicode() == ' ') + --n; + attribute.value.pos = pos; + attribute.value.len = n; + } + if (prefix == QLatin1String("xmlns") && namespaceProcessing) { + NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push(); + QStringRef namespacePrefix = symString(attribute.key); + QStringRef namespaceUri = symString(attribute.value); + attributeStack.pop(); + if (((namespacePrefix == QLatin1String("xml")) + ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace"))) + || namespaceUri == QLatin1String("http://www.w3.org/2000/xmlns/") + || namespaceUri.isEmpty() + || namespacePrefix == QLatin1String("xmlns")) + raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration.")); + + namespaceDeclaration.prefix = addToStringStorage(namespacePrefix); + namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri); + } + } + } break; + + case 235: { + normalizeLiterals = true; + Tag &tag = tagStack_push(); + prefix = tag.namespaceDeclaration.prefix = addToStringStorage(symPrefix(2)); + name = tag.name = addToStringStorage(symString(2)); + qualifiedName = tag.qualifiedName = addToStringStorage(symName(2)); + if ((!prefix.isEmpty() && !QXmlUtils::isNCName(prefix)) || !QXmlUtils::isNCName(name)) + raiseWellFormedError(QXmlStream::tr("Invalid XML name.")); + } break; + + case 236: + isEmptyElement = true; + Q_FALLTHROUGH(); + + case 237: + setType(QXmlStreamReader::StartElement); + resolveTag(); + if (tagStack.size() == 1 && hasSeenTag && !inParseEntity) + raiseWellFormedError(QXmlStream::tr("Extra content at end of document.")); + hasSeenTag = true; + break; + + case 238: { + setType(QXmlStreamReader::EndElement); + Tag &tag = tagStack_pop(); + + namespaceUri = tag.namespaceDeclaration.namespaceUri; + name = tag.name; + qualifiedName = tag.qualifiedName; + if (qualifiedName != symName(3)) + raiseWellFormedError(QXmlStream::tr("Opening and ending tag mismatch.")); + } break; + + case 239: + if (entitiesMustBeDeclared()) { + raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(unresolvedEntity)); + break; + } + setType(QXmlStreamReader::EntityReference); + name = &unresolvedEntity; + break; + + case 240: { + sym(1).len += sym(2).len + 1; + QStringView reference = symView(2); + if (const auto it = entityHash.find(reference); it != entityHash.end()) { + Entity &entity = *it; + if (entity.unparsed) { + raiseWellFormedError(QXmlStream::tr("Reference to unparsed entity '%1'.").arg(reference)); + } else { + if (!entity.hasBeenParsed) { + parseEntity(entity.value); + entity.hasBeenParsed = true; + } + if (entity.literal) + putStringLiteral(entity.value); + else if (referenceEntity(entity)) + putReplacement(entity.value); + textBuffer.chop(2 + sym(2).len); + clearSym(); + } + break; + } + + if (entityResolver) { + QString replacementText = resolveUndeclaredEntity(reference.toString()); + if (!replacementText.isNull()) { + putReplacement(replacementText); + textBuffer.chop(2 + sym(2).len); + clearSym(); + break; + } + } + + injectToken(UNRESOLVED_ENTITY); + unresolvedEntity = symString(2).toString(); + textBuffer.chop(2 + sym(2).len); + clearSym(); + + } break; + + case 241: { + sym(1).len += sym(2).len + 1; + QStringView reference = symView(2); + if (const auto it = parameterEntityHash.find(reference); it != parameterEntityHash.end()) { + referenceToParameterEntityDetected = true; + Entity &entity = *it; + if (entity.unparsed || entity.external) { + referenceToUnparsedEntityDetected = true; + } else { + if (referenceEntity(entity)) + putString(entity.value); + textBuffer.chop(2 + sym(2).len); + clearSym(); + } + } else if (entitiesMustBeDeclared()) { + raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(symString(2))); + } + } break; + + case 242: + sym(1).len += sym(2).len + 1; + break; + + case 243: { + sym(1).len += sym(2).len + 1; + QStringView reference = symView(2); + if (const auto it = entityHash.find(reference); it != entityHash.end()) { + Entity &entity = *it; + if (entity.unparsed || entity.value.isNull()) { + raiseWellFormedError(QXmlStream::tr("Reference to external entity '%1' in attribute value.").arg(reference)); + break; + } + if (!entity.hasBeenParsed) { + parseEntity(entity.value); + entity.hasBeenParsed = true; + } + if (entity.literal) + putStringLiteral(entity.value); + else if (referenceEntity(entity)) + putReplacementInAttributeValue(entity.value); + textBuffer.chop(2 + sym(2).len); + clearSym(); + break; + } + + if (entityResolver) { + QString replacementText = resolveUndeclaredEntity(reference.toString()); + if (!replacementText.isNull()) { + putReplacement(replacementText); + textBuffer.chop(2 + sym(2).len); + clearSym(); + break; + } + } + if (entitiesMustBeDeclared()) { + raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(reference)); + } + } break; + + case 244: { + if (char32_t s = resolveCharRef(3)) { + putStringLiteral(QChar::fromUcs4(s)); + textBuffer.chop(3 + sym(3).len); + clearSym(); + } else { + raiseWellFormedError(QXmlStream::tr("Invalid character reference.")); + } + } break; + + case 247: + case 248: + sym(1).len += sym(2).len; + break; + + case 259: + sym(1).len += fastScanSpace(); + if (atEnd) { + resume(259); + return false; + } + break; + + case 262: { + sym(1).len += fastScanName(&sym(1).prefix); + if (atEnd) { + resume(262); + return false; + } + } break; + + case 263: + sym(1).len += fastScanName(); + if (atEnd) { + resume(263); + return false; + } + break; + + case 264: + case 265: + case 266: + case 267: + case 268: + sym(1).len += fastScanNMTOKEN(); + if (atEnd) { + resume(268); + return false; + } + + break; + + default: + ; + } // switch + act = state_stack[tos] = nt_action (act, lhs[r] - TERMINAL_COUNT); + if (type != QXmlStreamReader::NoToken) + return true; + } else { + parseError(); + break; + } + } + return false; +} + +#endif + +QT_END_NAMESPACE + +#endif + |