diff options
Diffstat (limited to 'src/corelib/xml')
-rw-r--r-- | src/corelib/xml/qxmlstream.cpp | 70 | ||||
-rw-r--r-- | src/corelib/xml/qxmlstream.g | 105 | ||||
-rw-r--r-- | src/corelib/xml/qxmlstream_p.h | 73 | ||||
-rw-r--r-- | src/corelib/xml/qxmlutils.cpp | 37 | ||||
-rw-r--r-- | src/corelib/xml/qxmlutils_p.h | 7 |
5 files changed, 150 insertions, 142 deletions
diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp index af35193b13..f6ae3571ab 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/xml/qxmlstream.cpp @@ -775,8 +775,8 @@ QXmlStreamPrivateTagStack::QXmlStreamPrivateTagStack() tagStackStringStorage.reserve(32); tagStackStringStorageSize = 0; NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push(); - namespaceDeclaration.prefix = addToStringStorage(QLatin1String("xml")); - namespaceDeclaration.namespaceUri = addToStringStorage(QLatin1String("http://www.w3.org/XML/1998/namespace")); + namespaceDeclaration.prefix = addToStringStorage(QStringViewLiteral("xml")); + namespaceDeclaration.namespaceUri = addToStringStorage(QStringViewLiteral("http://www.w3.org/XML/1998/namespace")); initialTagStackStringStorageSize = tagStackStringStorageSize; } @@ -796,11 +796,17 @@ QXmlStreamReaderPrivate::QXmlStreamReaderPrivate(QXmlStreamReader *q) reallocateStack(); entityResolver = 0; init(); - entityHash.insert(QLatin1String("lt"), Entity::createLiteral(QLatin1String("<"))); - entityHash.insert(QLatin1String("gt"), Entity::createLiteral(QLatin1String(">"))); - entityHash.insert(QLatin1String("amp"), Entity::createLiteral(QLatin1String("&"))); - entityHash.insert(QLatin1String("apos"), Entity::createLiteral(QLatin1String("'"))); - entityHash.insert(QLatin1String("quot"), Entity::createLiteral(QLatin1String("\""))); +#define ADD_PREDEFINED(n, v) \ + do { \ + Entity e = Entity::createLiteral(QLatin1String(n), QLatin1String(v)); \ + entityHash.insert(qToStringViewIgnoringNull(e.name), std::move(e)); \ + } while (false) + ADD_PREDEFINED("lt", "<"); + ADD_PREDEFINED("gt", ">"); + ADD_PREDEFINED("amp", "&"); + ADD_PREDEFINED("apos", "'"); + ADD_PREDEFINED("quot", "\""); +#undef ADD_PREDEFINED } void QXmlStreamReaderPrivate::init() @@ -1558,7 +1564,7 @@ QStringRef QXmlStreamReaderPrivate::namespaceForPrefix(const QStringRef &prefix) #if 1 if (namespaceProcessing && !prefix.isEmpty()) - raiseWellFormedError(QXmlStream::tr("Namespace prefix '%1' not declared").arg(prefix.toString())); + raiseWellFormedError(QXmlStream::tr("Namespace prefix '%1' not declared").arg(prefix)); #endif return QStringRef(); @@ -1636,7 +1642,7 @@ void QXmlStreamReaderPrivate::resolveTag() if (attributes[j].name() == attribute.name() && attributes[j].namespaceUri() == attribute.namespaceUri() && (namespaceProcessing || attributes[j].qualifiedName() == attribute.qualifiedName())) - raiseWellFormedError(QXmlStream::tr("Attribute '%1' redefined.").arg(attribute.qualifiedName().toString())); + raiseWellFormedError(QXmlStream::tr("Attribute '%1' redefined.").arg(attribute.qualifiedName())); } } @@ -1798,20 +1804,19 @@ void QXmlStreamReaderPrivate::startDocument() QStringRef value(symString(attrib.value)); if (prefix.isEmpty() && key == QLatin1String("encoding")) { - const QString name(value.toString()); documentEncoding = value; if(hasStandalone) err = QXmlStream::tr("The standalone pseudo attribute must appear after the encoding."); - if(!QXmlUtils::isEncName(name)) - err = QXmlStream::tr("%1 is an invalid encoding name.").arg(name); + if (!QXmlUtils::isEncName(value)) + err = QXmlStream::tr("%1 is an invalid encoding name.").arg(value); else { #ifdef QT_NO_TEXTCODEC readBuffer = QString::fromLatin1(rawReadBuffer.data(), nbytesread); #else - QTextCodec *const newCodec = QTextCodec::codecForName(name.toLatin1()); + QTextCodec *const newCodec = QTextCodec::codecForName(value.toLatin1()); if (!newCodec) - err = QXmlStream::tr("Encoding %1 is unsupported").arg(name); + err = QXmlStream::tr("Encoding %1 is unsupported").arg(value); else if (newCodec != codec && !lockEncoding) { codec = newCodec; delete decoder; @@ -1881,32 +1886,25 @@ void QXmlStreamReaderPrivate::parseError() } } - error_message.clear (); if (nexpected && nexpected < nmax) { - bool first = true; - - for (int s = 0; s < nexpected; ++s) { - if (first) - error_message += QXmlStream::tr ("Expected "); - else if (s == nexpected - 1) - error_message += QLatin1String (nexpected > 2 ? ", or " : " or "); - else - error_message += QLatin1String (", "); - - first = false; - error_message += QLatin1String("\'"); - error_message += QLatin1String (spell [expected[s]]); - error_message += QLatin1String("\'"); + //: '<first option>' + QString exp_str = QXmlStream::tr("'%1'", "expected").arg(QLatin1String(spell[expected[0]])); + if (nexpected == 2) { + //: <first option>, '<second option>' + exp_str = QXmlStream::tr("%1 or '%2'", "expected").arg(exp_str, QLatin1String(spell[expected[1]])); + } else if (nexpected > 2) { + int s = 1; + for (; s < nexpected - 1; ++s) { + //: <options so far>, '<next option>' + exp_str = QXmlStream::tr("%1, '%2'", "expected").arg(exp_str, QLatin1String(spell[expected[s]])); + } + //: <options so far>, or '<final option>' + exp_str = QXmlStream::tr("%1, or '%2'", "expected").arg(exp_str, QLatin1String(spell[expected[s]])); } - error_message += QXmlStream::tr(", but got \'"); - error_message += QLatin1String(spell [token]); - error_message += QLatin1String("\'"); + error_message = QXmlStream::tr("Expected %1, but got '%2'.").arg(exp_str, QLatin1String(spell[token])); } else { - error_message += QXmlStream::tr("Unexpected \'"); - error_message += QLatin1String(spell [token]); - error_message += QLatin1String("\'"); + error_message = QXmlStream::tr("Unexpected '%1'.").arg(QLatin1String(spell[token])); } - error_message += QLatin1Char('.'); raiseWellFormedError(error_message); } diff --git a/src/corelib/xml/qxmlstream.g b/src/corelib/xml/qxmlstream.g index 567d36d4b9..fd69a6e4af 100644 --- a/src/corelib/xml/qxmlstream.g +++ b/src/corelib/xml/qxmlstream.g @@ -201,23 +201,22 @@ public: QXmlStreamSimpleStack<NamespaceDeclaration> namespaceDeclarations; QString tagStackStringStorage; int tagStackStringStorageSize; + int initialTagStackStringStorageSize; bool tagsDone; inline QStringRef addToStringStorage(const QStringRef &s) { - int pos = tagStackStringStorageSize; - int sz = s.size(); - if (pos != tagStackStringStorage.size()) - tagStackStringStorage.resize(pos); - tagStackStringStorage.insert(pos, s.unicode(), sz); - tagStackStringStorageSize += sz; - return QStringRef(&tagStackStringStorage, pos, sz); + return addToStringStorage(qToStringViewIgnoringNull(s)); } inline QStringRef addToStringStorage(const QString &s) { + return addToStringStorage(qToStringViewIgnoringNull(s)); + } + QStringRef addToStringStorage(QStringView s) + { int pos = tagStackStringStorageSize; int sz = s.size(); if (pos != tagStackStringStorage.size()) tagStackStringStorage.resize(pos); - tagStackStringStorage.insert(pos, s.unicode(), sz); + tagStackStringStorage.append(s.data(), sz); tagStackStringStorageSize += sz; return QStringRef(&tagStackStringStorage, pos, sz); } @@ -259,20 +258,24 @@ public: int readBufferPos; QXmlStreamSimpleStack<uint> putStack; struct Entity { - Entity(const QString& str = QString()) - :value(str), external(false), unparsed(false), literal(false), + Entity() = default; + Entity(const QString &name, const QString &value) + : name(name), value(value), external(false), unparsed(false), literal(false), hasBeenParsed(false), isCurrentlyReferenced(false){} - static inline Entity createLiteral(const QString &entity) - { Entity result(entity); result.literal = result.hasBeenParsed = true; return result; } - QString value; + static inline Entity createLiteral(QLatin1String name, QLatin1String value) + { Entity result(name, value); result.literal = result.hasBeenParsed = true; return result; } + QString name, value; uint external : 1; uint unparsed : 1; uint literal : 1; uint hasBeenParsed : 1; uint isCurrentlyReferenced : 1; }; - QHash<QString, Entity> entityHash; - QHash<QString, Entity> parameterEntityHash; + // these hash tables use a QStringView as a key to avoid creating QStrings + // just for lookup. The keys are usually views into Entity::name and thus + // are guaranteed to have the same lifetime as the referenced data: + QHash<QStringView, Entity> entityHash; + QHash<QStringView, Entity> parameterEntityHash; QXmlStreamSimpleStack<Entity *>entityReferenceStack; inline bool referenceEntity(Entity &entity) { if (entity.isCurrentlyReferenced) { @@ -425,6 +428,11 @@ public: const Value &symbol = sym(index); return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix); } + QStringView symView(int index) const + { + const Value &symbol = sym(index); + return QStringView(textBuffer.data() + symbol.pos, symbol.len).mid(symbol.prefix); + } inline QStringRef symName(int index) { const Value &symbol = sym(index); return QStringRef(&textBuffer, symbol.pos, symbol.len); @@ -455,7 +463,7 @@ public: short token; - ushort token_char; + uint token_char; uint filterCarriageReturn(); inline uint getChar(); @@ -466,7 +474,7 @@ public: void putStringLiteral(const QString &s); void putReplacement(const QString &s); void putReplacementInAttributeValue(const QString &s); - ushort getChar_helper(); + uint getChar_helper(); bool scanUntil(const char *str, short tokenToInject = -1); bool scanString(const char *str, short tokenToInject, bool requireSpace = true); @@ -525,10 +533,8 @@ bool QXmlStreamReaderPrivate::parse() prefix.clear(); qualifiedName.clear(); namespaceUri.clear(); - if (publicNamespaceDeclarations.size()) - publicNamespaceDeclarations.clear(); - if (attributes.size()) - attributes.resize(0); + publicNamespaceDeclarations.clear(); + attributes.clear(); if (isEmptyElement) { setType(QXmlStreamReader::EndElement); Tag &tag = tagStack_pop(); @@ -553,7 +559,7 @@ bool QXmlStreamReaderPrivate::parse() dtdName.clear(); dtdPublicId.clear(); dtdSystemId.clear(); - // fall through + Q_FALLTHROUGH(); case QXmlStreamReader::Comment: case QXmlStreamReader::Characters: isCDATA = false; @@ -579,13 +585,13 @@ bool QXmlStreamReaderPrivate::parse() documentVersion.clear(); documentEncoding.clear(); #ifndef QT_NO_TEXTCODEC - if (decoder->hasFailure()) { + if (decoder && decoder->hasFailure()) { raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content.")); readBuffer.clear(); return false; } #endif - // fall through + Q_FALLTHROUGH(); default: clearTextBuffer(); ; @@ -610,8 +616,8 @@ bool QXmlStreamReaderPrivate::parse() if (token == -1 && - TERMINAL_COUNT != action_index[act]) { uint cu = getChar(); token = NOTOKEN; - token_char = cu; - if (cu & 0xff0000) { + token_char = cu == ~0U ? cu : ushort(cu); + if ((cu != ~0U) && (cu & 0xff0000)) { token = cu >> 16; } else switch (token_char) { case 0xfffe: @@ -629,8 +635,8 @@ bool QXmlStreamReaderPrivate::parse() } else { break; } - // fall through - case '\0': { + Q_FALLTHROUGH(); + case ~0U: { token = EOF_SYMBOL; if (!tagsDone && !inParseEntity) { int a = t_action(act, token); @@ -644,6 +650,7 @@ bool QXmlStreamReaderPrivate::parse() case '\n': ++lineNumber; lastLineStart = characterOffset + readBufferPos; + Q_FALLTHROUGH(); case ' ': case '\t': token = SPACE; @@ -1127,7 +1134,7 @@ entity_decl ::= entity_decl_external NDATA name space_opt RANGLE; if (entityDeclaration.parameter) raiseWellFormedError(QXmlStream::tr("NDATA in parameter entity declaration.")); } - //fall through + Q_FALLTHROUGH(); ./ entity_decl ::= entity_decl_external space_opt RANGLE; @@ -1144,13 +1151,13 @@ entity_decl ::= entity_decl_start entity_value space_opt RANGLE; EntityDeclaration &entityDeclaration = entityDeclarations.top(); if (!entityDeclaration.external) entityDeclaration.value = symString(2); - QString entityName = entityDeclaration.name.toString(); - QHash<QString, Entity> &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash; - if (!hash.contains(entityName)) { - Entity entity(entityDeclaration.value.toString()); + 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(entityName, entity); + hash.insert(qToStringViewIgnoringNull(entity.name), entity); } } break; ./ @@ -1164,12 +1171,12 @@ processing_instruction ::= LANGLE QUESTIONMARK name space; processingInstructionTarget = symString(3); if (scanUntil("?>")) { processingInstructionData = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 2); - const QString piTarget(processingInstructionTarget.toString()); - if (!piTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) { + if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) { raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document.")); } - else if(!QXmlUtils::isNCName(piTarget)) - raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.").arg(piTarget)); + else if (!QXmlUtils::isNCName(processingInstructionTarget)) + raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.") + .arg(processingInstructionTarget)); } else if (type != QXmlStreamReader::Invalid){ resume($rule_number); return false; @@ -1182,7 +1189,7 @@ processing_instruction ::= LANGLE QUESTIONMARK name QUESTIONMARK RANGLE; case $rule_number: setType(QXmlStreamReader::ProcessingInstruction); processingInstructionTarget = symString(3); - if (!processingInstructionTarget.toString().compare(QLatin1String("xml"), Qt::CaseInsensitive)) + if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) raiseWellFormedError(QXmlStream::tr("Invalid processing instruction name.")); break; ./ @@ -1281,7 +1288,7 @@ scan_content_char ::= content_char; /. case $rule_number: isWhitespace = false; - // fall through + Q_FALLTHROUGH(); ./ scan_content_char ::= SPACE; @@ -1379,8 +1386,8 @@ literal_content ::= literal_content_start; public_literal ::= literal; /. case $rule_number: { - if (!QXmlUtils::isPublicID(symString(1).toString())) { - raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1).toString())); + if (!QXmlUtils::isPublicID(symString(1))) { + raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1))); resume($rule_number); return false; } @@ -1567,7 +1574,7 @@ empty_element_tag ::= stag_start attribute_list_opt SLASH RANGLE; /. case $rule_number: isEmptyElement = true; - // fall through + Q_FALLTHROUGH(); ./ @@ -1614,7 +1621,7 @@ entity_ref ::= AMPERSAND name SEMICOLON; /. case $rule_number: { sym(1).len += sym(2).len + 1; - QString reference = symString(2).toString(); + QStringView reference = symView(2); if (entityHash.contains(reference)) { Entity &entity = entityHash[reference]; if (entity.unparsed) { @@ -1635,7 +1642,7 @@ entity_ref ::= AMPERSAND name SEMICOLON; } if (entityResolver) { - QString replacementText = resolveUndeclaredEntity(reference); + QString replacementText = resolveUndeclaredEntity(reference.toString()); if (!replacementText.isNull()) { putReplacement(replacementText); textBuffer.chop(2 + sym(2).len); @@ -1656,7 +1663,7 @@ pereference ::= PERCENT name SEMICOLON; /. case $rule_number: { sym(1).len += sym(2).len + 1; - QString reference = symString(2).toString(); + QStringView reference = symView(2); if (parameterEntityHash.contains(reference)) { referenceToParameterEntityDetected = true; Entity &entity = parameterEntityHash[reference]; @@ -1669,7 +1676,7 @@ pereference ::= PERCENT name SEMICOLON; clearSym(); } } else if (entitiesMustBeDeclared()) { - raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(symString(2).toString())); + raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(symString(2))); } } break; ./ @@ -1687,7 +1694,7 @@ entity_ref_in_attribute_value ::= AMPERSAND name SEMICOLON; /. case $rule_number: { sym(1).len += sym(2).len + 1; - QString reference = symString(2).toString(); + QStringView reference = symView(2); if (entityHash.contains(reference)) { Entity &entity = entityHash[reference]; if (entity.unparsed || entity.value.isNull()) { @@ -1708,7 +1715,7 @@ entity_ref_in_attribute_value ::= AMPERSAND name SEMICOLON; } if (entityResolver) { - QString replacementText = resolveUndeclaredEntity(reference); + QString replacementText = resolveUndeclaredEntity(reference.toString()); if (!replacementText.isNull()) { putReplacement(replacementText); textBuffer.chop(2 + sym(2).len); diff --git a/src/corelib/xml/qxmlstream_p.h b/src/corelib/xml/qxmlstream_p.h index 9ef95c1fbe..5645d812eb 100644 --- a/src/corelib/xml/qxmlstream_p.h +++ b/src/corelib/xml/qxmlstream_p.h @@ -701,20 +701,18 @@ public: bool tagsDone; inline QStringRef addToStringStorage(const QStringRef &s) { - int pos = tagStackStringStorageSize; - int sz = s.size(); - if (pos != tagStackStringStorage.size()) - tagStackStringStorage.resize(pos); - tagStackStringStorage.insert(pos, s.unicode(), sz); - tagStackStringStorageSize += sz; - return QStringRef(&tagStackStringStorage, pos, sz); + return addToStringStorage(qToStringViewIgnoringNull(s)); } inline QStringRef addToStringStorage(const QString &s) { + return addToStringStorage(qToStringViewIgnoringNull(s)); + } + QStringRef addToStringStorage(QStringView s) + { int pos = tagStackStringStorageSize; int sz = s.size(); if (pos != tagStackStringStorage.size()) tagStackStringStorage.resize(pos); - tagStackStringStorage.insert(pos, s.unicode(), sz); + tagStackStringStorage.append(s.data(), sz); tagStackStringStorageSize += sz; return QStringRef(&tagStackStringStorage, pos, sz); } @@ -756,20 +754,24 @@ public: int readBufferPos; QXmlStreamSimpleStack<uint> putStack; struct Entity { - Entity(const QString& str = QString()) - :value(str), external(false), unparsed(false), literal(false), + Entity() = default; + Entity(const QString &name, const QString &value) + : name(name), value(value), external(false), unparsed(false), literal(false), hasBeenParsed(false), isCurrentlyReferenced(false){} - static inline Entity createLiteral(const QString &entity) - { Entity result(entity); result.literal = result.hasBeenParsed = true; return result; } - QString value; + static inline Entity createLiteral(QLatin1String name, QLatin1String value) + { Entity result(name, value); result.literal = result.hasBeenParsed = true; return result; } + QString name, value; uint external : 1; uint unparsed : 1; uint literal : 1; uint hasBeenParsed : 1; uint isCurrentlyReferenced : 1; }; - QHash<QString, Entity> entityHash; - QHash<QString, Entity> parameterEntityHash; + // these hash tables use a QStringView as a key to avoid creating QStrings + // just for lookup. The keys are usually views into Entity::name and thus + // are guaranteed to have the same lifetime as the referenced data: + QHash<QStringView, Entity> entityHash; + QHash<QStringView, Entity> parameterEntityHash; QXmlStreamSimpleStack<Entity *>entityReferenceStack; inline bool referenceEntity(Entity &entity) { if (entity.isCurrentlyReferenced) { @@ -922,6 +924,11 @@ public: const Value &symbol = sym(index); return QStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix); } + QStringView symView(int index) const + { + const Value &symbol = sym(index); + return QStringView(textBuffer.data() + symbol.pos, symbol.len).mid(symbol.prefix); + } inline QStringRef symName(int index) { const Value &symbol = sym(index); return QStringRef(&textBuffer, symbol.pos, symbol.len); @@ -1492,13 +1499,13 @@ bool QXmlStreamReaderPrivate::parse() EntityDeclaration &entityDeclaration = entityDeclarations.top(); if (!entityDeclaration.external) entityDeclaration.value = symString(2); - QString entityName = entityDeclaration.name.toString(); - QHash<QString, Entity> &hash = entityDeclaration.parameter ? parameterEntityHash : entityHash; - if (!hash.contains(entityName)) { - Entity entity(entityDeclaration.value.toString()); + 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(entityName, entity); + hash.insert(qToStringViewIgnoringNull(entity.name), entity); } } break; @@ -1508,12 +1515,12 @@ bool QXmlStreamReaderPrivate::parse() processingInstructionTarget = symString(3); if (scanUntil("?>")) { processingInstructionData = QStringRef(&textBuffer, pos, textBuffer.size() - pos - 2); - const QString piTarget(processingInstructionTarget.toString()); - if (!piTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) { + if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) { raiseWellFormedError(QXmlStream::tr("XML declaration not at start of document.")); } - else if(!QXmlUtils::isNCName(piTarget)) - raiseWellFormedError(QXmlStream::tr("%1 is an invalid processing instruction name.").arg(piTarget)); + 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; @@ -1523,7 +1530,7 @@ bool QXmlStreamReaderPrivate::parse() case 97: setType(QXmlStreamReader::ProcessingInstruction); processingInstructionTarget = symString(3); - if (!processingInstructionTarget.toString().compare(QLatin1String("xml"), Qt::CaseInsensitive)) + if (!processingInstructionTarget.compare(QLatin1String("xml"), Qt::CaseInsensitive)) raiseWellFormedError(QXmlStream::tr("Invalid processing instruction name.")); break; @@ -1637,8 +1644,8 @@ bool QXmlStreamReaderPrivate::parse() break; case 175: { - if (!QXmlUtils::isPublicID(symString(1).toString())) { - raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1).toString())); + if (!QXmlUtils::isPublicID(symString(1))) { + raiseWellFormedError(QXmlStream::tr("%1 is an invalid PUBLIC identifier.").arg(symString(1))); resume(175); return false; } @@ -1793,7 +1800,7 @@ bool QXmlStreamReaderPrivate::parse() case 240: { sym(1).len += sym(2).len + 1; - QString reference = symString(2).toString(); + QStringView reference = symView(2); if (entityHash.contains(reference)) { Entity &entity = entityHash[reference]; if (entity.unparsed) { @@ -1814,7 +1821,7 @@ bool QXmlStreamReaderPrivate::parse() } if (entityResolver) { - QString replacementText = resolveUndeclaredEntity(reference); + QString replacementText = resolveUndeclaredEntity(reference.toString()); if (!replacementText.isNull()) { putReplacement(replacementText); textBuffer.chop(2 + sym(2).len); @@ -1832,7 +1839,7 @@ bool QXmlStreamReaderPrivate::parse() case 241: { sym(1).len += sym(2).len + 1; - QString reference = symString(2).toString(); + QStringView reference = symView(2); if (parameterEntityHash.contains(reference)) { referenceToParameterEntityDetected = true; Entity &entity = parameterEntityHash[reference]; @@ -1845,7 +1852,7 @@ bool QXmlStreamReaderPrivate::parse() clearSym(); } } else if (entitiesMustBeDeclared()) { - raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(symString(2).toString())); + raiseWellFormedError(QXmlStream::tr("Entity '%1' not declared.").arg(symString(2))); } } break; @@ -1855,7 +1862,7 @@ bool QXmlStreamReaderPrivate::parse() case 243: { sym(1).len += sym(2).len + 1; - QString reference = symString(2).toString(); + QStringView reference = symView(2); if (entityHash.contains(reference)) { Entity &entity = entityHash[reference]; if (entity.unparsed || entity.value.isNull()) { @@ -1876,7 +1883,7 @@ bool QXmlStreamReaderPrivate::parse() } if (entityResolver) { - QString replacementText = resolveUndeclaredEntity(reference); + QString replacementText = resolveUndeclaredEntity(reference.toString()); if (!replacementText.isNull()) { putReplacement(replacementText); textBuffer.chop(2 + sym(2).len); diff --git a/src/corelib/xml/qxmlutils.cpp b/src/corelib/xml/qxmlutils.cpp index 23caae2935..01c84251fd 100644 --- a/src/corelib/xml/qxmlutils.cpp +++ b/src/corelib/xml/qxmlutils.cpp @@ -227,19 +227,22 @@ bool QXmlUtils::isBaseChar(const QChar c) \sa {http://www.w3.org/TR/REC-xml/#NT-EncName}, {Extensible Markup Language (XML) 1.0 (Fourth Edition), [81] EncName} */ -bool QXmlUtils::isEncName(const QString &encName) +bool QXmlUtils::isEncName(QStringView encName) { // Valid encoding names are given by "[A-Za-z][A-Za-z0-9._\\-]*" - const ushort *c = encName.utf16(); - int l = encName.length(); - if (l < 1 || !((c[0] >= 'a' && c[0] <= 'z') || (c[0] >= 'A' && c[0] <= 'Z'))) + if (encName.isEmpty()) return false; - for (int i = 1; i < l; ++i) { - if ((c[i] >= 'a' && c[i] <= 'z') - || (c[i] >= 'A' && c[i] <= 'Z') - || (c[i] >= '0' && c[i] <= '9') - || c[i] == '.' || c[i] == '_' || c[i] == '-') + const auto first = encName.front().unicode(); + if (!((first >= 'a' && first <= 'z') || (first >= 'A' && first <= 'Z'))) + return false; + for (QChar ch : encName.mid(1)) { + const auto cp = ch.unicode(); + if ((cp >= 'a' && cp <= 'z') + || (cp >= 'A' && cp <= 'Z') + || (cp >= '0' && cp <= '9') + || cp == '.' || cp == '_' || cp == '-') { continue; + } return false; } return true; @@ -310,13 +313,10 @@ bool QXmlUtils::isNameChar(const QChar c) \sa {http://www.w3.org/TR/REC-xml/#NT-PubidLiteral}, {Extensible Markup Language (XML) 1.0 (Fourth Edition), [12] PubidLiteral} */ -bool QXmlUtils::isPublicID(const QString &candidate) +bool QXmlUtils::isPublicID(QStringView candidate) { - const int len = candidate.length(); - - for(int i = 0; i < len; ++i) - { - const ushort cp = candidate.at(i).unicode(); + for (QChar ch : candidate) { + const ushort cp = ch.unicode(); if ((cp >= 'a' && cp <= 'z') || (cp >= 'A' && cp <= 'Z') @@ -369,7 +369,7 @@ bool QXmlUtils::isPublicID(const QString &candidate) \sa {http://www.w3.org/TR/REC-xml-names/#NT-NCName}, {W3CNamespaces in XML 1.0 (Second Edition), [4] NCName} */ -bool QXmlUtils::isNCName(const QStringRef &ncName) +bool QXmlUtils::isNCName(QStringView ncName) { if(ncName.isEmpty()) return false; @@ -379,10 +379,7 @@ bool QXmlUtils::isNCName(const QStringRef &ncName) if(!QXmlUtils::isLetter(first) && first.unicode() != '_' && first.unicode() != ':') return false; - const int len = ncName.size(); - for(int i = 0; i < len; ++i) - { - const QChar at = ncName.at(i); + for (QChar at : ncName) { if(!QXmlUtils::isNameChar(at) || at == QLatin1Char(':')) return false; } diff --git a/src/corelib/xml/qxmlutils_p.h b/src/corelib/xml/qxmlutils_p.h index 6db347b3ee..db6bddd5be 100644 --- a/src/corelib/xml/qxmlutils_p.h +++ b/src/corelib/xml/qxmlutils_p.h @@ -68,13 +68,12 @@ class QXmlCharRange; class Q_CORE_EXPORT QXmlUtils { public: - static bool isEncName(const QString &encName); + static bool isEncName(QStringView encName); static bool isChar(const QChar c); static bool isNameChar(const QChar c); static bool isLetter(const QChar c); - static bool isNCName(const QStringRef &ncName); - static inline bool isNCName(const QString &ncName) { return isNCName(QStringRef(&ncName)); } - static bool isPublicID(const QString &candidate); + static bool isNCName(QStringView ncName); + static bool isPublicID(QStringView candidate); private: typedef const QXmlCharRange *RangeIter; |