16#include <QtCore/private/qglobal_p.h>
17#include <qstringconverter.h>
18#include <qxmlstream.h>
20#include <QtCore/qhash.h>
21#include <QCoreApplication>
22#include <QtCore/private/qtools_p.h>
45 constexpr inline XmlStringRef(
const QString *string, qsizetype pos, qsizetype length)
92#define MAKE_MEMBER(name)
93 auto name () const noexcept { return view(). name (); }
108 friend auto operator
op(const XmlStringRef &lhs, const XmlStringRef &rhs) noexcept { return lhs.view() op rhs.view(); }
118 friend auto operator
op(const XmlStringRef &lhs, QStringView rhs) noexcept { return lhs.view() op rhs; }
119 friend auto operator
op(QStringView lhs, const XmlStringRef &rhs) noexcept { return lhs op rhs.view(); }
131 void verify([[maybe_unused]] qsizetype pos = 0,
132 [[maybe_unused]] qsizetype n = 1)
const
135 Q_PRE(pos <= size());
137 Q_PRE(n <= size() - pos);
146 static_assert(
sizeof(
T) > 1,
"some operations may overflow with such small types");
152 : data(
nullptr),
tos(-1),
cap(0)
157 std::destroy_n(data, size());
164 auto needed = extraCapacity;
165 if (add_overflow(needed, tos + 1, &needed))
171 needed = (
std::max)(needed, cap * 2);
172 void *ptr = qt_reallocarray(
static_cast<
void *>(data), needed,
sizeof(T));
174 data =
reinterpret_cast<T *>(ptr);
180 inline T &
rawPush() {
return *
new (data + (++tos)) T; }
181 inline const T &
top()
const {
return data[tos]; }
182 inline T &
top() {
return data[tos]; }
183 inline T
pop() { T t =
std::move(data[tos]);
std::destroy_at(data + tos); --tos;
return t; }
184 inline T &
operator[](qsizetype index) {
return data[index]; }
185 inline const T &
at(qsizetype index)
const {
return data[index]; }
187 inline void resize(qsizetype s) { tos = s - 1; }
188 inline bool isEmpty()
const {
return tos < 0; }
194 const T *
begin()
const {
return data; }
195 const T *
cbegin()
const {
return begin(); }
196 T *
end() {
return data + size(); }
197 const T *
end()
const {
return data + size(); }
198 const T *
cend()
const {
return end(); }
235 qsizetype pos = tagStackStringStorageSize;
236 if (pos != tagStackStringStorage.size())
237 tagStackStringStorage.resize(pos);
238 s.visit([&](
auto s) { tagStackStringStorage.append(s); });
239 qsizetype sz = (tagStackStringStorage.size() - pos);
240 tagStackStringStorageSize += sz;
241 return XmlStringRef(&tagStackStringStorage, pos, sz);
248 Tag tag = tagStack.pop();
249 tagStackStringStorageSize = tag.tagStackStringStorageSize;
250 namespaceDeclarations.resize(tag.namespaceDeclarationsSize);
251 tagsDone = tagStack.isEmpty();
255 Tag &tag = tagStack.push();
256 tag.tagStackStringStorageSize = tagStackStringStorageSize;
257 tag.namespaceDeclarationsSize = namespaceDeclarations.size();
262#if QT_CONFIG(xmlstreamreader)
263class QXmlStreamEntityResolver;
264class QXmlStreamReaderPrivate :
public QXmlStreamGrammar,
public QXmlStreamPrivateTagStack
266 QXmlStreamReader *q_ptr;
267 Q_DECLARE_PUBLIC(QXmlStreamReader)
268 using XmlStringRef = QtPrivate::XmlStringRef;
270 QXmlStreamReaderPrivate(QXmlStreamReader *q);
271 ~QXmlStreamReaderPrivate();
274 struct BufferAndEncoding
278 QStringDecoder::Encoding encoding;
281 : buffer(), encoding(QStringDecoder::System)
283 BufferAndEncoding(
const QByteArray &b, QStringDecoder::Encoding e)
284 : buffer(b), encoding(e)
287 QList<BufferAndEncoding> dataInfo;
288 QStringDecoder chunkDecoder;
289 void appendDataWithEncoding(
const QByteArray &data, QStringDecoder::Encoding enc);
290 bool tryAppendViewWithEncoding(QByteArrayView data, QStringDecoder::Encoding enc);
291 void appendViewWithEncoding(QByteArrayView data, QStringDecoder::Encoding enc);
293 QByteArray rawReadBuffer;
296 qsizetype readBufferPos;
297 QXmlStreamSimpleStack<uint> putStack;
300 Entity(
const QString &name,
const QString &value)
301 : name(name), value(value), external(
false), unparsed(
false), literal(
false),
302 hasBeenParsed(
false), isCurrentlyReferenced(
false){}
303 static inline Entity createLiteral(QLatin1StringView name, QLatin1StringView value)
304 { Entity result(name, value); result.literal = result.hasBeenParsed =
true;
return result; }
309 uint hasBeenParsed : 1;
310 uint isCurrentlyReferenced : 1;
315 QHash<QStringView, Entity> entityHash;
316 QHash<QStringView, Entity> parameterEntityHash;
317 struct QEntityReference
319 QHash<QStringView, Entity> *hash;
322 QXmlStreamSimpleStack<QEntityReference> entityReferenceStack;
323 int entityExpansionLimit = 4096;
324 qsizetype entityLength = 0;
325 inline bool referenceEntity(QHash<QStringView, Entity> *hash, Entity &entity)
328 if (entity.isCurrentlyReferenced) {
329 raiseWellFormedError(QXmlStream::tr(
"Self-referencing entity detected."));
332 const auto valLen = entity.value.size();
333 const auto refLen = entity.name.size() + 2;
335 const auto effectiveRefLen = entityReferenceStack.isEmpty() ? 0 : refLen;
336 entityLength += valLen - effectiveRefLen;
337 if (entityLength > entityExpansionLimit) {
338 raiseWellFormedError(QXmlStream::tr(
"Entity expands to more characters than the entity expansion limit."));
341 entity.isCurrentlyReferenced =
true;
342 entityReferenceStack.push() = { hash, entity.name };
343 injectToken(ENTITY_DONE);
350 QStringDecoder decoder;
353 enum class XmlContext
359 XmlContext currentContext = XmlContext::Prolog;
360 bool foundDTD =
false;
361 bool isValidToken(QXmlStreamReader::TokenType type);
365
366
367 QXmlStreamReader::TokenType type;
368 QXmlStreamReader::Error error;
370 QString unresolvedEntity;
372 qint64 lineNumber, lastLineStart, characterOffset;
375 void write(
const QString &);
376 void write(
const char *);
379 QXmlStreamAttributes attributes;
380 XmlStringRef namespaceForPrefix(QStringView prefix);
382 void resolvePublicNamespaces();
384 uint resolveCharRef(
int symbolIndex);
385 bool checkStartDocument();
386 void startDocument();
388 void checkPublicLiteral(QStringView publicId);
391 XmlStringRef lastAttributeValue;
392 bool lastAttributeIsCData;
393 struct DtdAttribute {
394 XmlStringRef tagName;
395 XmlStringRef attributeQualifiedName;
396 XmlStringRef attributePrefix;
397 XmlStringRef attributeName;
398 XmlStringRef defaultValue;
400 bool isNamespaceAttribute;
402 QXmlStreamSimpleStack<DtdAttribute> dtdAttributes;
403 struct NotationDeclaration {
405 XmlStringRef publicId;
406 XmlStringRef systemId;
408 QXmlStreamSimpleStack<NotationDeclaration> notationDeclarations;
409 QXmlStreamNotationDeclarations publicNotationDeclarations;
410 QXmlStreamNamespaceDeclarations publicNamespaceDeclarations;
412 struct EntityDeclaration {
414 XmlStringRef notationName;
415 XmlStringRef publicId;
416 XmlStringRef systemId;
420 inline void clear() {
422 notationName.clear();
426 parameter = external =
false;
429 QXmlStreamSimpleStack<EntityDeclaration> entityDeclarations;
430 QXmlStreamEntityDeclarations publicEntityDeclarations;
434 XmlStringRef prefix, namespaceUri, qualifiedName, name;
435 XmlStringRef processingInstructionTarget, processingInstructionData;
436 XmlStringRef dtdName, dtdPublicId, dtdSystemId;
437 XmlStringRef documentVersion, documentEncoding;
438 uint isEmptyElement : 1;
439 uint isWhitespace : 1;
442 uint hasCheckedStartDocument : 1;
443 uint normalizeLiterals : 1;
445 uint inParseEntity : 1;
446 uint referenceToUnparsedEntityDetected : 1;
447 uint referenceToParameterEntityDetected : 1;
448 uint hasExternalDtdSubset : 1;
449 uint lockEncoding : 1;
450 uint namespaceProcessing : 1;
451 uint hasStandalone : 1;
454 void resume(
int rule);
456 inline bool entitiesMustBeDeclared()
const {
457 return (!inParseEntity
459 || (!referenceToUnparsedEntityDetected
460 && !referenceToParameterEntityDetected
461 && !hasExternalDtdSubset)));
466 qsizetype stack_size;
476 inline void reallocateStack();
477 inline Value &sym(
int index)
const
478 {
return sym_stack[tos + index - 1]; }
480 inline void clearTextBuffer() {
482 textBuffer.resize(0);
483 textBuffer.reserve(256);
490 QXmlStreamSimpleStack<Attribute> attributeStack;
492 inline XmlStringRef symString(
int index) {
493 return symString(sym(index));
495 QStringView symView(
int index)
const
497 const Value &symbol = sym(index);
498 return QStringView(textBuffer.data() + symbol.pos, symbol.len).mid(symbol.prefix);
500 inline XmlStringRef symName(
int index) {
501 return symName(sym(index));
503 inline XmlStringRef symPrefix(
int index) {
504 return symPrefix(sym(index));
506 auto symQName(
int index) {
511 XmlStringRef all()
const {
return m_data; }
512 XmlStringRef qname()
const {
return m_data; }
513 XmlStringRef prefix()
const
514 {
return m_prefix ? m_data.sliced(0, m_prefix - 1) : XmlStringRef(); }
515 XmlStringRef localPart()
const {
return m_data.sliced(m_prefix); }
517 void resetBackingStorage(XmlStringRef newData) { m_data = newData; }
519 const Value &symbol = sym(index);
520 return R{{&textBuffer, symbol.pos, symbol.len}, symbol.prefix};
522 inline XmlStringRef symString(
const Value &symbol) {
523 return XmlStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
525 inline XmlStringRef symName(
const Value &symbol) {
526 return XmlStringRef(&textBuffer, symbol.pos, symbol.len);
528 inline XmlStringRef symPrefix(
const Value &symbol) {
530 return XmlStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
531 return XmlStringRef();
534 inline void clearSym() { Value &val = sym(1); val.pos = textBuffer.size(); val.len = 0; }
540 uint filterCarriageReturn();
541 inline uint getChar();
542 inline uint peekChar();
543 inline void putChar(uint c) { putStack.push() = c; }
544 inline void putChar(QChar c) { putStack.push() = c.unicode(); }
545 void putString(QStringView s, qsizetype from = 0);
546 void putStringLiteral(QStringView s);
547 void putReplacement(QStringView s);
548 void putReplacementInAttributeValue(QStringView s);
549 uint getChar_helper();
551 bool scanUntil(
const char *str,
short tokenToInject = -1);
552 bool scanString(
const char *str,
short tokenToInject,
bool requireSpace =
true);
553 inline void injectToken(ushort tokenToInject) {
554 putChar(
int(tokenToInject) << 16);
557 QString resolveUndeclaredEntity(
const QString &name);
558 void parseEntity(
const QString &value);
559 std::unique_ptr<QXmlStreamReaderPrivate> entityParser;
561 bool scanAfterLangleBang();
562 bool scanPublicOrSystem();
564 bool scanAfterDefaultDecl();
570 qsizetype fastScanLiteralContent();
571 qsizetype fastScanSpace();
572 qsizetype fastScanContentCharList();
573 std::optional<qsizetype> fastScanName(Value *val =
nullptr);
574 inline qsizetype fastScanNMTOKEN();
578 inline void consumeRule(
int);
580 void raiseError(QXmlStreamReader::Error error,
const QString& message = QString());
581 void raiseWellFormedError(
const QString &message);
582 void raiseNamePrefixTooLongError();
584 QXmlStreamEntityResolver *entityResolver;
588
589
590
591
592 inline void setType(
const QXmlStreamReader::TokenType t)
594 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)