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;
284 qsizetype readBufferPos;
285 QXmlStreamSimpleStack<uint> putStack;
288 Entity(
const QString &name,
const QString &value)
289 : name(name), value(value), external(
false), unparsed(
false), literal(
false),
290 hasBeenParsed(
false), isCurrentlyReferenced(
false){}
291 static inline Entity createLiteral(QLatin1StringView name, QLatin1StringView value)
292 { Entity result(name, value); result.literal = result.hasBeenParsed =
true;
return result; }
297 uint hasBeenParsed : 1;
298 uint isCurrentlyReferenced : 1;
303 QHash<QStringView, Entity> entityHash;
304 QHash<QStringView, Entity> parameterEntityHash;
305 struct QEntityReference
307 QHash<QStringView, Entity> *hash;
310 QXmlStreamSimpleStack<QEntityReference> entityReferenceStack;
311 int entityExpansionLimit = 4096;
312 int entityLength = 0;
313 inline bool referenceEntity(QHash<QStringView, Entity> *hash, Entity &entity)
316 if (entity.isCurrentlyReferenced) {
317 raiseWellFormedError(QXmlStream::tr(
"Self-referencing entity detected."));
323 entityLength += entity.value.size() - entity.name.size() - 2;
324 if (entityLength > entityExpansionLimit) {
325 raiseWellFormedError(QXmlStream::tr(
"Entity expands to more characters than the entity expansion limit."));
328 entity.isCurrentlyReferenced =
true;
329 entityReferenceStack.push() = { hash, entity.name };
330 injectToken(ENTITY_DONE);
337 QStringDecoder decoder;
340 enum class XmlContext
346 XmlContext currentContext = XmlContext::Prolog;
347 bool foundDTD =
false;
348 bool isValidToken(QXmlStreamReader::TokenType type);
352
353
354 QXmlStreamReader::TokenType type;
355 QXmlStreamReader::Error error;
357 QString unresolvedEntity;
359 qint64 lineNumber, lastLineStart, characterOffset;
362 void write(
const QString &);
363 void write(
const char *);
366 QXmlStreamAttributes attributes;
367 XmlStringRef namespaceForPrefix(QStringView prefix);
369 void resolvePublicNamespaces();
371 uint resolveCharRef(
int symbolIndex);
372 bool checkStartDocument();
373 void startDocument();
375 void checkPublicLiteral(QStringView publicId);
378 XmlStringRef lastAttributeValue;
379 bool lastAttributeIsCData;
380 struct DtdAttribute {
381 XmlStringRef tagName;
382 XmlStringRef attributeQualifiedName;
383 XmlStringRef attributePrefix;
384 XmlStringRef attributeName;
385 XmlStringRef defaultValue;
387 bool isNamespaceAttribute;
389 QXmlStreamSimpleStack<DtdAttribute> dtdAttributes;
390 struct NotationDeclaration {
392 XmlStringRef publicId;
393 XmlStringRef systemId;
395 QXmlStreamSimpleStack<NotationDeclaration> notationDeclarations;
396 QXmlStreamNotationDeclarations publicNotationDeclarations;
397 QXmlStreamNamespaceDeclarations publicNamespaceDeclarations;
399 struct EntityDeclaration {
401 XmlStringRef notationName;
402 XmlStringRef publicId;
403 XmlStringRef systemId;
407 inline void clear() {
409 notationName.clear();
413 parameter = external =
false;
416 QXmlStreamSimpleStack<EntityDeclaration> entityDeclarations;
417 QXmlStreamEntityDeclarations publicEntityDeclarations;
421 XmlStringRef prefix, namespaceUri, qualifiedName, name;
422 XmlStringRef processingInstructionTarget, processingInstructionData;
423 XmlStringRef dtdName, dtdPublicId, dtdSystemId;
424 XmlStringRef documentVersion, documentEncoding;
425 uint isEmptyElement : 1;
426 uint isWhitespace : 1;
429 uint hasCheckedStartDocument : 1;
430 uint normalizeLiterals : 1;
432 uint inParseEntity : 1;
433 uint referenceToUnparsedEntityDetected : 1;
434 uint referenceToParameterEntityDetected : 1;
435 uint hasExternalDtdSubset : 1;
436 uint lockEncoding : 1;
437 uint namespaceProcessing : 1;
438 uint hasStandalone : 1;
441 void resume(
int rule);
443 inline bool entitiesMustBeDeclared()
const {
444 return (!inParseEntity
446 || (!referenceToUnparsedEntityDetected
447 && !referenceToParameterEntityDetected
448 && !hasExternalDtdSubset)));
463 inline void reallocateStack();
464 inline Value &sym(
int index)
const
465 {
return sym_stack[tos + index - 1]; }
467 inline void clearTextBuffer() {
469 textBuffer.resize(0);
470 textBuffer.reserve(256);
477 QXmlStreamSimpleStack<Attribute> attributeStack;
479 inline XmlStringRef symString(
int index) {
480 return symString(sym(index));
482 QStringView symView(
int index)
const
484 const Value &symbol = sym(index);
485 return QStringView(textBuffer.data() + symbol.pos, symbol.len).mid(symbol.prefix);
487 inline XmlStringRef symName(
int index) {
488 return symName(sym(index));
490 inline XmlStringRef symPrefix(
int index) {
491 return symPrefix(sym(index));
493 auto symQName(
int index) {
498 XmlStringRef all()
const {
return m_data; }
499 XmlStringRef qname()
const {
return m_data; }
500 XmlStringRef prefix()
const
501 {
return m_prefix ? m_data.sliced(0, m_prefix - 1) : XmlStringRef(); }
502 XmlStringRef localPart()
const {
return m_data.sliced(m_prefix); }
504 void resetBackingStorage(XmlStringRef newData) { m_data = newData; }
506 const Value &symbol = sym(index);
507 return R{{&textBuffer, symbol.pos, symbol.len}, symbol.prefix};
509 inline XmlStringRef symString(
const Value &symbol) {
510 return XmlStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
512 inline XmlStringRef symName(
const Value &symbol) {
513 return XmlStringRef(&textBuffer, symbol.pos, symbol.len);
515 inline XmlStringRef symPrefix(
const Value &symbol) {
517 return XmlStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
518 return XmlStringRef();
521 inline void clearSym() { Value &val = sym(1); val.pos = textBuffer.size(); val.len = 0; }
527 uint filterCarriageReturn();
528 inline uint getChar();
529 inline uint peekChar();
530 inline void putChar(uint c) { putStack.push() = c; }
531 inline void putChar(QChar c) { putStack.push() = c.unicode(); }
532 void putString(QStringView s, qsizetype from = 0);
533 void putStringLiteral(QStringView s);
534 void putReplacement(QStringView s);
535 void putReplacementInAttributeValue(QStringView s);
536 uint getChar_helper();
538 bool scanUntil(
const char *str,
short tokenToInject = -1);
539 bool scanString(
const char *str,
short tokenToInject,
bool requireSpace =
true);
540 inline void injectToken(ushort tokenToInject) {
541 putChar(
int(tokenToInject) << 16);
544 QString resolveUndeclaredEntity(
const QString &name);
545 void parseEntity(
const QString &value);
546 std::unique_ptr<QXmlStreamReaderPrivate> entityParser;
548 bool scanAfterLangleBang();
549 bool scanPublicOrSystem();
551 bool scanAfterDefaultDecl();
557 qsizetype fastScanLiteralContent();
558 qsizetype fastScanSpace();
559 qsizetype fastScanContentCharList();
560 std::optional<qsizetype> fastScanName(Value *val =
nullptr);
561 inline qsizetype fastScanNMTOKEN();
565 inline void consumeRule(
int);
567 void raiseError(QXmlStreamReader::Error error,
const QString& message = QString());
568 void raiseWellFormedError(
const QString &message);
569 void raiseNamePrefixTooLongError();
571 QXmlStreamEntityResolver *entityResolver;
575
576
577
578
579 inline void setType(
const QXmlStreamReader::TokenType t)
581 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)