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)
89#define MAKE_MEMBER(name)
90 auto name () const noexcept { return view(). name (); }
105 friend auto operator
op(const XmlStringRef &lhs, const XmlStringRef &rhs) noexcept { return lhs.view() op rhs.view(); }
115 friend auto operator
op(const XmlStringRef &lhs, QStringView rhs) noexcept { return lhs.view() op rhs; }
116 friend auto operator
op(QStringView lhs, const XmlStringRef &rhs) noexcept { return lhs op rhs.view(); }
128 void verify([[maybe_unused]] qsizetype pos = 0,
129 [[maybe_unused]] qsizetype n = 1)
const
132 Q_PRE(pos <= size());
134 Q_PRE(n <= size() - pos);
155 std::destroy_n(data, size());
162 if (tos + extraCapacity + 1 > cap) {
163 cap = qMax(tos + extraCapacity + 1, cap << 1 );
164 void *ptr = realloc(
static_cast<
void *>(data), cap *
sizeof(T));
166 data =
reinterpret_cast<T *>(ptr);
171 inline T &
rawPush() {
return *
new (data + (++tos)) T; }
172 inline const T &
top()
const {
return data[tos]; }
173 inline T &
top() {
return data[tos]; }
174 inline T
pop() { T t =
std::move(data[tos]);
std::destroy_at(data + tos); --tos;
return t; }
175 inline T &
operator[](qsizetype index) {
return data[index]; }
176 inline const T &
at(qsizetype index)
const {
return data[index]; }
178 inline void resize(qsizetype s) { tos = s - 1; }
179 inline bool isEmpty()
const {
return tos < 0; }
185 const T *
begin()
const {
return data; }
186 const T *
cbegin()
const {
return begin(); }
187 T *
end() {
return data + size(); }
188 const T *
end()
const {
return data + size(); }
189 const T *
cend()
const {
return end(); }
225 qsizetype pos = tagStackStringStorageSize;
226 if (pos != tagStackStringStorage.size())
227 tagStackStringStorage.resize(pos);
228 s.visit([&](
auto s) { tagStackStringStorage.append(s); });
229 qsizetype sz = (tagStackStringStorage.size() - pos);
230 tagStackStringStorageSize += sz;
231 return XmlStringRef(&tagStackStringStorage, pos, sz);
238 Tag tag = tagStack.pop();
239 tagStackStringStorageSize = tag.tagStackStringStorageSize;
240 namespaceDeclarations.resize(tag.namespaceDeclarationsSize);
241 tagsDone = tagStack.isEmpty();
245 Tag &tag = tagStack.push();
246 tag.tagStackStringStorageSize = tagStackStringStorageSize;
247 tag.namespaceDeclarationsSize = namespaceDeclarations.size();
252#if QT_CONFIG(xmlstreamreader)
253class QXmlStreamEntityResolver;
254class QXmlStreamReaderPrivate :
public QXmlStreamGrammar,
public QXmlStreamPrivateTagStack
256 QXmlStreamReader *q_ptr;
257 Q_DECLARE_PUBLIC(QXmlStreamReader)
259 QXmlStreamReaderPrivate(QXmlStreamReader *q);
260 ~QXmlStreamReaderPrivate();
263 struct BufferAndEncoding
267 QStringDecoder::Encoding encoding;
270 : buffer(), encoding(QStringDecoder::System)
272 BufferAndEncoding(
const QByteArray &b, QStringDecoder::Encoding e)
273 : buffer(b), encoding(e)
276 QList<BufferAndEncoding> dataInfo;
277 QStringDecoder chunkDecoder;
278 void appendDataWithEncoding(
const QByteArray &data, QStringDecoder::Encoding enc);
279 void addData(
const QByteArray &data, QStringDecoder::Encoding enc);
281 QByteArray rawReadBuffer;
285 qsizetype readBufferPos;
286 QXmlStreamSimpleStack<uint> putStack;
289 Entity(
const QString &name,
const QString &value)
290 : name(name), value(value), external(
false), unparsed(
false), literal(
false),
291 hasBeenParsed(
false), isCurrentlyReferenced(
false){}
292 static inline Entity createLiteral(QLatin1StringView name, QLatin1StringView value)
293 { Entity result(name, value); result.literal = result.hasBeenParsed =
true;
return result; }
298 uint hasBeenParsed : 1;
299 uint isCurrentlyReferenced : 1;
304 QHash<QStringView, Entity> entityHash;
305 QHash<QStringView, Entity> parameterEntityHash;
306 struct QEntityReference
308 QHash<QStringView, Entity> *hash;
311 QXmlStreamSimpleStack<QEntityReference> entityReferenceStack;
312 int entityExpansionLimit = 4096;
313 int entityLength = 0;
314 inline bool referenceEntity(QHash<QStringView, Entity> *hash, Entity &entity)
317 if (entity.isCurrentlyReferenced) {
318 raiseWellFormedError(QXmlStream::tr(
"Self-referencing entity detected."));
324 entityLength += entity.value.size() - entity.name.size() - 2;
325 if (entityLength > entityExpansionLimit) {
326 raiseWellFormedError(QXmlStream::tr(
"Entity expands to more characters than the entity expansion limit."));
329 entity.isCurrentlyReferenced =
true;
330 entityReferenceStack.push() = { hash, entity.name };
331 injectToken(ENTITY_DONE);
338 QStringDecoder decoder;
341 enum class XmlContext
347 XmlContext currentContext = XmlContext::Prolog;
348 bool foundDTD =
false;
349 bool isValidToken(QXmlStreamReader::TokenType type);
353
354
355 QXmlStreamReader::TokenType type;
356 QXmlStreamReader::Error error;
358 QString unresolvedEntity;
360 qint64 lineNumber, lastLineStart, characterOffset;
363 void write(
const QString &);
364 void write(
const char *);
367 QXmlStreamAttributes attributes;
368 XmlStringRef namespaceForPrefix(QStringView prefix);
370 void resolvePublicNamespaces();
372 uint resolveCharRef(
int symbolIndex);
373 bool checkStartDocument();
374 void startDocument();
376 void checkPublicLiteral(QStringView publicId);
379 XmlStringRef lastAttributeValue;
380 bool lastAttributeIsCData;
381 struct DtdAttribute {
382 XmlStringRef tagName;
383 XmlStringRef attributeQualifiedName;
384 XmlStringRef attributePrefix;
385 XmlStringRef attributeName;
386 XmlStringRef defaultValue;
388 bool isNamespaceAttribute;
390 QXmlStreamSimpleStack<DtdAttribute> dtdAttributes;
391 struct NotationDeclaration {
393 XmlStringRef publicId;
394 XmlStringRef systemId;
396 QXmlStreamSimpleStack<NotationDeclaration> notationDeclarations;
397 QXmlStreamNotationDeclarations publicNotationDeclarations;
398 QXmlStreamNamespaceDeclarations publicNamespaceDeclarations;
400 struct EntityDeclaration {
402 XmlStringRef notationName;
403 XmlStringRef publicId;
404 XmlStringRef systemId;
408 inline void clear() {
410 notationName.clear();
414 parameter = external =
false;
417 QXmlStreamSimpleStack<EntityDeclaration> entityDeclarations;
418 QXmlStreamEntityDeclarations publicEntityDeclarations;
422 XmlStringRef prefix, namespaceUri, qualifiedName, name;
423 XmlStringRef processingInstructionTarget, processingInstructionData;
424 XmlStringRef dtdName, dtdPublicId, dtdSystemId;
425 XmlStringRef documentVersion, documentEncoding;
426 uint isEmptyElement : 1;
427 uint isWhitespace : 1;
430 uint hasCheckedStartDocument : 1;
431 uint normalizeLiterals : 1;
433 uint inParseEntity : 1;
434 uint referenceToUnparsedEntityDetected : 1;
435 uint referenceToParameterEntityDetected : 1;
436 uint hasExternalDtdSubset : 1;
437 uint lockEncoding : 1;
438 uint namespaceProcessing : 1;
439 uint hasStandalone : 1;
442 void resume(
int rule);
444 inline bool entitiesMustBeDeclared()
const {
445 return (!inParseEntity
447 || (!referenceToUnparsedEntityDetected
448 && !referenceToParameterEntityDetected
449 && !hasExternalDtdSubset)));
464 inline void reallocateStack();
465 inline Value &sym(
int index)
const
466 {
return sym_stack[tos + index - 1]; }
468 inline void clearTextBuffer() {
470 textBuffer.resize(0);
471 textBuffer.reserve(256);
478 QXmlStreamSimpleStack<Attribute> attributeStack;
480 inline XmlStringRef symString(
int index) {
481 return symString(sym(index));
483 QStringView symView(
int index)
const
485 const Value &symbol = sym(index);
486 return QStringView(textBuffer.data() + symbol.pos, symbol.len).mid(symbol.prefix);
488 inline XmlStringRef symName(
int index) {
489 return symName(sym(index));
491 inline XmlStringRef symPrefix(
int index) {
492 return symPrefix(sym(index));
494 auto symQName(
int index) {
499 XmlStringRef all()
const {
return m_data; }
500 XmlStringRef qname()
const {
return m_data; }
501 XmlStringRef prefix()
const
502 {
return m_prefix ? m_data.sliced(0, m_prefix - 1) : XmlStringRef(); }
503 XmlStringRef localPart()
const {
return m_data.sliced(m_prefix); }
505 void resetBackingStorage(XmlStringRef newData) { m_data = newData; }
507 const Value &symbol = sym(index);
508 return R{{&textBuffer, symbol.pos, symbol.len}, symbol.prefix};
510 inline XmlStringRef symString(
const Value &symbol) {
511 return XmlStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
513 inline XmlStringRef symName(
const Value &symbol) {
514 return XmlStringRef(&textBuffer, symbol.pos, symbol.len);
516 inline XmlStringRef symPrefix(
const Value &symbol) {
518 return XmlStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
519 return XmlStringRef();
522 inline void clearSym() { Value &val = sym(1); val.pos = textBuffer.size(); val.len = 0; }
528 uint filterCarriageReturn();
529 inline uint getChar();
530 inline uint peekChar();
531 inline void putChar(uint c) { putStack.push() = c; }
532 inline void putChar(QChar c) { putStack.push() = c.unicode(); }
533 void putString(QStringView s, qsizetype from = 0);
534 void putStringLiteral(QStringView s);
535 void putReplacement(QStringView s);
536 void putReplacementInAttributeValue(QStringView s);
537 uint getChar_helper();
539 bool scanUntil(
const char *str,
short tokenToInject = -1);
540 bool scanString(
const char *str,
short tokenToInject,
bool requireSpace =
true);
541 inline void injectToken(ushort tokenToInject) {
542 putChar(
int(tokenToInject) << 16);
545 QString resolveUndeclaredEntity(
const QString &name);
546 void parseEntity(
const QString &value);
547 std::unique_ptr<QXmlStreamReaderPrivate> entityParser;
549 bool scanAfterLangleBang();
550 bool scanPublicOrSystem();
552 bool scanAfterDefaultDecl();
558 qsizetype fastScanLiteralContent();
559 qsizetype fastScanSpace();
560 qsizetype fastScanContentCharList();
561 std::optional<qsizetype> fastScanName(Value *val =
nullptr);
562 inline qsizetype fastScanNMTOKEN();
566 inline void consumeRule(
int);
568 void raiseError(QXmlStreamReader::Error error,
const QString& message = QString());
569 void raiseWellFormedError(
const QString &message);
570 void raiseNamePrefixTooLongError();
572 QXmlStreamEntityResolver *entityResolver;
576
577
578
579
580 inline void setType(
const QXmlStreamReader::TokenType t)
582 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)