16#include <QtCore/private/qglobal_p.h>
17#include <qstringconverter.h>
18#include <qxmlstream.h>
20#include <QtCore/qhash.h>
21#include <QCoreApplication>
42 constexpr inline XmlStringRef(
const QString *string, qsizetype pos, qsizetype length)
78#define MAKE_MEMBER(name)
79 auto name () const noexcept { return view(). name (); }
94 friend auto operator
op(const XmlStringRef &lhs, const XmlStringRef &rhs) noexcept { return lhs.view() op rhs.view(); }
104 friend auto operator
op(const XmlStringRef &lhs, QStringView rhs) noexcept { return lhs.view() op rhs; }
105 friend auto operator
op(QStringView lhs, const XmlStringRef &rhs) noexcept { return lhs op rhs.view(); }
133 std::destroy_n(data, size());
140 if (tos + extraCapacity + 1 > cap) {
141 cap = qMax(tos + extraCapacity + 1, cap << 1 );
142 void *ptr = realloc(
static_cast<
void *>(data), cap *
sizeof(T));
144 data =
reinterpret_cast<T *>(ptr);
149 inline T &
rawPush() {
return *
new (data + (++tos)) T; }
150 inline const T &
top()
const {
return data[tos]; }
151 inline T &
top() {
return data[tos]; }
152 inline T
pop() { T t = std::move(data[tos]); std::destroy_at(data + tos); --tos;
return t; }
153 inline T &
operator[](qsizetype index) {
return data[index]; }
154 inline const T &
at(qsizetype index)
const {
return data[index]; }
156 inline void resize(qsizetype s) { tos = s - 1; }
157 inline bool isEmpty()
const {
return tos < 0; }
163 const T *
begin()
const {
return data; }
164 const T *
cbegin()
const {
return begin(); }
165 T *
end() {
return data + size(); }
166 const T *
end()
const {
return data + size(); }
167 const T *
cend()
const {
return end(); }
202 qsizetype pos = tagStackStringStorageSize;
203 if (pos != tagStackStringStorage.size())
204 tagStackStringStorage.resize(pos);
205 s.visit([&](
auto s) { tagStackStringStorage.append(s); });
206 qsizetype sz = (tagStackStringStorage.size() - pos);
207 tagStackStringStorageSize += sz;
208 return XmlStringRef(&tagStackStringStorage, pos, sz);
215 Tag tag = tagStack.pop();
216 tagStackStringStorageSize = tag.tagStackStringStorageSize;
217 namespaceDeclarations.resize(tag.namespaceDeclarationsSize);
218 tagsDone = tagStack.isEmpty();
222 Tag &tag = tagStack.push();
223 tag.tagStackStringStorageSize = tagStackStringStorageSize;
224 tag.namespaceDeclarationsSize = namespaceDeclarations.size();
229#if QT_CONFIG(xmlstreamreader)
230class QXmlStreamEntityResolver;
231class QXmlStreamReaderPrivate :
public QXmlStreamGrammar,
public QXmlStreamPrivateTagStack
233 QXmlStreamReader *q_ptr;
234 Q_DECLARE_PUBLIC(QXmlStreamReader)
236 QXmlStreamReaderPrivate(QXmlStreamReader *q);
237 ~QXmlStreamReaderPrivate();
240 struct BufferAndEncoding
244 QStringDecoder::Encoding encoding;
247 : buffer(), encoding(QStringDecoder::System)
249 BufferAndEncoding(
const QByteArray &b, QStringDecoder::Encoding e)
250 : buffer(b), encoding(e)
253 QList<BufferAndEncoding> dataInfo;
254 QStringDecoder chunkDecoder;
255 void appendDataWithEncoding(
const QByteArray &data, QStringDecoder::Encoding enc);
256 void addData(
const QByteArray &data, QStringDecoder::Encoding enc);
258 QByteArray rawReadBuffer;
262 qsizetype readBufferPos;
263 QXmlStreamSimpleStack<uint> putStack;
266 Entity(
const QString &name,
const QString &value)
267 : name(name), value(value), external(
false), unparsed(
false), literal(
false),
268 hasBeenParsed(
false), isCurrentlyReferenced(
false){}
269 static inline Entity createLiteral(QLatin1StringView name, QLatin1StringView value)
270 { Entity result(name, value); result.literal = result.hasBeenParsed =
true;
return result; }
275 uint hasBeenParsed : 1;
276 uint isCurrentlyReferenced : 1;
281 QHash<QStringView, Entity> entityHash;
282 QHash<QStringView, Entity> parameterEntityHash;
283 struct QEntityReference
285 QHash<QStringView, Entity> *hash;
288 QXmlStreamSimpleStack<QEntityReference> entityReferenceStack;
289 int entityExpansionLimit = 4096;
290 int entityLength = 0;
291 inline bool referenceEntity(QHash<QStringView, Entity> *hash, Entity &entity)
294 if (entity.isCurrentlyReferenced) {
295 raiseWellFormedError(QXmlStream::tr(
"Self-referencing entity detected."));
301 entityLength += entity.value.size() - entity.name.size() - 2;
302 if (entityLength > entityExpansionLimit) {
303 raiseWellFormedError(QXmlStream::tr(
"Entity expands to more characters than the entity expansion limit."));
306 entity.isCurrentlyReferenced =
true;
307 entityReferenceStack.push() = { hash, entity.name };
308 injectToken(ENTITY_DONE);
315 QStringDecoder decoder;
318 enum class XmlContext
324 XmlContext currentContext = XmlContext::Prolog;
325 bool foundDTD =
false;
326 bool isValidToken(QXmlStreamReader::TokenType type);
330
331
332 QXmlStreamReader::TokenType type;
333 QXmlStreamReader::Error error;
335 QString unresolvedEntity;
337 qint64 lineNumber, lastLineStart, characterOffset;
340 void write(
const QString &);
341 void write(
const char *);
344 QXmlStreamAttributes attributes;
345 XmlStringRef namespaceForPrefix(QStringView prefix);
347 void resolvePublicNamespaces();
349 uint resolveCharRef(
int symbolIndex);
350 bool checkStartDocument();
351 void startDocument();
353 void checkPublicLiteral(QStringView publicId);
356 XmlStringRef lastAttributeValue;
357 bool lastAttributeIsCData;
358 struct DtdAttribute {
359 XmlStringRef tagName;
360 XmlStringRef attributeQualifiedName;
361 XmlStringRef attributePrefix;
362 XmlStringRef attributeName;
363 XmlStringRef defaultValue;
365 bool isNamespaceAttribute;
367 QXmlStreamSimpleStack<DtdAttribute> dtdAttributes;
368 struct NotationDeclaration {
370 XmlStringRef publicId;
371 XmlStringRef systemId;
373 QXmlStreamSimpleStack<NotationDeclaration> notationDeclarations;
374 QXmlStreamNotationDeclarations publicNotationDeclarations;
375 QXmlStreamNamespaceDeclarations publicNamespaceDeclarations;
377 struct EntityDeclaration {
379 XmlStringRef notationName;
380 XmlStringRef publicId;
381 XmlStringRef systemId;
385 inline void clear() {
387 notationName.clear();
391 parameter = external =
false;
394 QXmlStreamSimpleStack<EntityDeclaration> entityDeclarations;
395 QXmlStreamEntityDeclarations publicEntityDeclarations;
399 XmlStringRef prefix, namespaceUri, qualifiedName, name;
400 XmlStringRef processingInstructionTarget, processingInstructionData;
401 XmlStringRef dtdName, dtdPublicId, dtdSystemId;
402 XmlStringRef documentVersion, documentEncoding;
403 uint isEmptyElement : 1;
404 uint isWhitespace : 1;
407 uint hasCheckedStartDocument : 1;
408 uint normalizeLiterals : 1;
410 uint inParseEntity : 1;
411 uint referenceToUnparsedEntityDetected : 1;
412 uint referenceToParameterEntityDetected : 1;
413 uint hasExternalDtdSubset : 1;
414 uint lockEncoding : 1;
415 uint namespaceProcessing : 1;
416 uint hasStandalone : 1;
419 void resume(
int rule);
421 inline bool entitiesMustBeDeclared()
const {
422 return (!inParseEntity
424 || (!referenceToUnparsedEntityDetected
425 && !referenceToParameterEntityDetected
426 && !hasExternalDtdSubset)));
441 inline void reallocateStack();
442 inline Value &sym(
int index)
const
443 {
return sym_stack[tos + index - 1]; }
445 inline void clearTextBuffer() {
447 textBuffer.resize(0);
448 textBuffer.reserve(256);
455 QXmlStreamSimpleStack<Attribute> attributeStack;
457 inline XmlStringRef symString(
int index) {
458 const Value &symbol = sym(index);
459 return XmlStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
461 QStringView symView(
int index)
const
463 const Value &symbol = sym(index);
464 return QStringView(textBuffer.data() + symbol.pos, symbol.len).mid(symbol.prefix);
466 inline XmlStringRef symName(
int index) {
467 const Value &symbol = sym(index);
468 return XmlStringRef(&textBuffer, symbol.pos, symbol.len);
470 inline XmlStringRef symString(
int index,
int offset) {
471 const Value &symbol = sym(index);
472 return XmlStringRef(&textBuffer, symbol.pos + symbol.prefix + offset, symbol.len - symbol.prefix - offset);
474 inline XmlStringRef symPrefix(
int index) {
475 const Value &symbol = sym(index);
477 return XmlStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
478 return XmlStringRef();
480 inline XmlStringRef symString(
const Value &symbol) {
481 return XmlStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
483 inline XmlStringRef symName(
const Value &symbol) {
484 return XmlStringRef(&textBuffer, symbol.pos, symbol.len);
486 inline XmlStringRef symPrefix(
const Value &symbol) {
488 return XmlStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
489 return XmlStringRef();
492 inline void clearSym() { Value &val = sym(1); val.pos = textBuffer.size(); val.len = 0; }
498 uint filterCarriageReturn();
499 inline uint getChar();
500 inline uint peekChar();
501 inline void putChar(uint c) { putStack.push() = c; }
502 inline void putChar(QChar c) { putStack.push() = c.unicode(); }
503 void putString(QStringView s, qsizetype from = 0);
504 void putStringLiteral(QStringView s);
505 void putReplacement(QStringView s);
506 void putReplacementInAttributeValue(QStringView s);
507 uint getChar_helper();
509 bool scanUntil(
const char *str,
short tokenToInject = -1);
510 bool scanString(
const char *str,
short tokenToInject,
bool requireSpace =
true);
511 inline void injectToken(ushort tokenToInject) {
512 putChar(
int(tokenToInject) << 16);
515 QString resolveUndeclaredEntity(
const QString &name);
516 void parseEntity(
const QString &value);
517 std::unique_ptr<QXmlStreamReaderPrivate> entityParser;
519 bool scanAfterLangleBang();
520 bool scanPublicOrSystem();
522 bool scanAfterDefaultDecl();
528 qsizetype fastScanLiteralContent();
529 qsizetype fastScanSpace();
530 qsizetype fastScanContentCharList();
531 std::optional<qsizetype> fastScanName(Value *val =
nullptr);
532 inline qsizetype fastScanNMTOKEN();
536 inline void consumeRule(
int);
538 void raiseError(QXmlStreamReader::Error error,
const QString& message = QString());
539 void raiseWellFormedError(
const QString &message);
540 void raiseNamePrefixTooLongError();
542 QXmlStreamEntityResolver *entityResolver;
546
547
548
549
550 inline void setType(
const QXmlStreamReader::TokenType t)
552 if (type != QXmlStreamReader::Invalid)
void reserve(qsizetype extraCapacity)
const T & at(qsizetype index) const
T & operator[](qsizetype index)
XmlStringRef(const QString *string)
constexpr XmlStringRef()=default
constexpr XmlStringRef(const QString *string, qsizetype pos, qsizetype length)
#define MAKE_MEMBER(name)