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(); }
203 qsizetype pos = tagStackStringStorageSize;
204 if (pos != tagStackStringStorage.size())
205 tagStackStringStorage.resize(pos);
206 s.visit([&](
auto s) { tagStackStringStorage.append(s); });
207 qsizetype sz = (tagStackStringStorage.size() - pos);
208 tagStackStringStorageSize += sz;
209 return XmlStringRef(&tagStackStringStorage, pos, sz);
216 Tag tag = tagStack.pop();
217 tagStackStringStorageSize = tag.tagStackStringStorageSize;
218 namespaceDeclarations.resize(tag.namespaceDeclarationsSize);
219 tagsDone = tagStack.isEmpty();
223 Tag &tag = tagStack.push();
224 tag.tagStackStringStorageSize = tagStackStringStorageSize;
225 tag.namespaceDeclarationsSize = namespaceDeclarations.size();
230#if QT_CONFIG(xmlstreamreader)
231class QXmlStreamEntityResolver;
232class QXmlStreamReaderPrivate :
public QXmlStreamGrammar,
public QXmlStreamPrivateTagStack
234 QXmlStreamReader *q_ptr;
235 Q_DECLARE_PUBLIC(QXmlStreamReader)
237 QXmlStreamReaderPrivate(QXmlStreamReader *q);
238 ~QXmlStreamReaderPrivate();
241 struct BufferAndEncoding
245 QStringDecoder::Encoding encoding;
248 : buffer(), encoding(QStringDecoder::System)
250 BufferAndEncoding(
const QByteArray &b, QStringDecoder::Encoding e)
251 : buffer(b), encoding(e)
254 QList<BufferAndEncoding> dataInfo;
255 QStringDecoder chunkDecoder;
256 void appendDataWithEncoding(
const QByteArray &data, QStringDecoder::Encoding enc);
257 void addData(
const QByteArray &data, QStringDecoder::Encoding enc);
259 QByteArray rawReadBuffer;
263 qsizetype readBufferPos;
264 QXmlStreamSimpleStack<uint> putStack;
267 Entity(
const QString &name,
const QString &value)
268 : name(name), value(value), external(
false), unparsed(
false), literal(
false),
269 hasBeenParsed(
false), isCurrentlyReferenced(
false){}
270 static inline Entity createLiteral(QLatin1StringView name, QLatin1StringView value)
271 { Entity result(name, value); result.literal = result.hasBeenParsed =
true;
return result; }
276 uint hasBeenParsed : 1;
277 uint isCurrentlyReferenced : 1;
282 QHash<QStringView, Entity> entityHash;
283 QHash<QStringView, Entity> parameterEntityHash;
284 struct QEntityReference
286 QHash<QStringView, Entity> *hash;
289 QXmlStreamSimpleStack<QEntityReference> entityReferenceStack;
290 int entityExpansionLimit = 4096;
291 int entityLength = 0;
292 inline bool referenceEntity(QHash<QStringView, Entity> *hash, Entity &entity)
295 if (entity.isCurrentlyReferenced) {
296 raiseWellFormedError(QXmlStream::tr(
"Self-referencing entity detected."));
302 entityLength += entity.value.size() - entity.name.size() - 2;
303 if (entityLength > entityExpansionLimit) {
304 raiseWellFormedError(QXmlStream::tr(
"Entity expands to more characters than the entity expansion limit."));
307 entity.isCurrentlyReferenced =
true;
308 entityReferenceStack.push() = { hash, entity.name };
309 injectToken(ENTITY_DONE);
316 QStringDecoder decoder;
319 enum class XmlContext
325 XmlContext currentContext = XmlContext::Prolog;
326 bool foundDTD =
false;
327 bool isValidToken(QXmlStreamReader::TokenType type);
331
332
333 QXmlStreamReader::TokenType type;
334 QXmlStreamReader::Error error;
336 QString unresolvedEntity;
338 qint64 lineNumber, lastLineStart, characterOffset;
341 void write(
const QString &);
342 void write(
const char *);
345 QXmlStreamAttributes attributes;
346 XmlStringRef namespaceForPrefix(QStringView prefix);
348 void resolvePublicNamespaces();
350 uint resolveCharRef(
int symbolIndex);
351 bool checkStartDocument();
352 void startDocument();
354 void checkPublicLiteral(QStringView publicId);
357 XmlStringRef lastAttributeValue;
358 bool lastAttributeIsCData;
359 struct DtdAttribute {
360 XmlStringRef tagName;
361 XmlStringRef attributeQualifiedName;
362 XmlStringRef attributePrefix;
363 XmlStringRef attributeName;
364 XmlStringRef defaultValue;
366 bool isNamespaceAttribute;
368 QXmlStreamSimpleStack<DtdAttribute> dtdAttributes;
369 struct NotationDeclaration {
371 XmlStringRef publicId;
372 XmlStringRef systemId;
374 QXmlStreamSimpleStack<NotationDeclaration> notationDeclarations;
375 QXmlStreamNotationDeclarations publicNotationDeclarations;
376 QXmlStreamNamespaceDeclarations publicNamespaceDeclarations;
378 struct EntityDeclaration {
380 XmlStringRef notationName;
381 XmlStringRef publicId;
382 XmlStringRef systemId;
386 inline void clear() {
388 notationName.clear();
392 parameter = external =
false;
395 QXmlStreamSimpleStack<EntityDeclaration> entityDeclarations;
396 QXmlStreamEntityDeclarations publicEntityDeclarations;
400 XmlStringRef prefix, namespaceUri, qualifiedName, name;
401 XmlStringRef processingInstructionTarget, processingInstructionData;
402 XmlStringRef dtdName, dtdPublicId, dtdSystemId;
403 XmlStringRef documentVersion, documentEncoding;
404 uint isEmptyElement : 1;
405 uint isWhitespace : 1;
408 uint hasCheckedStartDocument : 1;
409 uint normalizeLiterals : 1;
411 uint inParseEntity : 1;
412 uint referenceToUnparsedEntityDetected : 1;
413 uint referenceToParameterEntityDetected : 1;
414 uint hasExternalDtdSubset : 1;
415 uint lockEncoding : 1;
416 uint namespaceProcessing : 1;
417 uint hasStandalone : 1;
420 void resume(
int rule);
422 inline bool entitiesMustBeDeclared()
const {
423 return (!inParseEntity
425 || (!referenceToUnparsedEntityDetected
426 && !referenceToParameterEntityDetected
427 && !hasExternalDtdSubset)));
442 inline void reallocateStack();
443 inline Value &sym(
int index)
const
444 {
return sym_stack[tos + index - 1]; }
446 inline void clearTextBuffer() {
448 textBuffer.resize(0);
449 textBuffer.reserve(256);
456 QXmlStreamSimpleStack<Attribute> attributeStack;
458 inline XmlStringRef symString(
int index) {
459 return symString(sym(index));
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 return symName(sym(index));
469 inline XmlStringRef symPrefix(
int index) {
470 return symPrefix(sym(index));
472 inline XmlStringRef symString(
const Value &symbol) {
473 return XmlStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
475 inline XmlStringRef symName(
const Value &symbol) {
476 return XmlStringRef(&textBuffer, symbol.pos, symbol.len);
478 inline XmlStringRef symPrefix(
const Value &symbol) {
480 return XmlStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
481 return XmlStringRef();
484 inline void clearSym() { Value &val = sym(1); val.pos = textBuffer.size(); val.len = 0; }
490 uint filterCarriageReturn();
491 inline uint getChar();
492 inline uint peekChar();
493 inline void putChar(uint c) { putStack.push() = c; }
494 inline void putChar(QChar c) { putStack.push() = c.unicode(); }
495 void putString(QStringView s, qsizetype from = 0);
496 void putStringLiteral(QStringView s);
497 void putReplacement(QStringView s);
498 void putReplacementInAttributeValue(QStringView s);
499 uint getChar_helper();
501 bool scanUntil(
const char *str,
short tokenToInject = -1);
502 bool scanString(
const char *str,
short tokenToInject,
bool requireSpace =
true);
503 inline void injectToken(ushort tokenToInject) {
504 putChar(
int(tokenToInject) << 16);
507 QString resolveUndeclaredEntity(
const QString &name);
508 void parseEntity(
const QString &value);
509 std::unique_ptr<QXmlStreamReaderPrivate> entityParser;
511 bool scanAfterLangleBang();
512 bool scanPublicOrSystem();
514 bool scanAfterDefaultDecl();
520 qsizetype fastScanLiteralContent();
521 qsizetype fastScanSpace();
522 qsizetype fastScanContentCharList();
523 std::optional<qsizetype> fastScanName(Value *val =
nullptr);
524 inline qsizetype fastScanNMTOKEN();
528 inline void consumeRule(
int);
530 void raiseError(QXmlStreamReader::Error error,
const QString& message = QString());
531 void raiseWellFormedError(
const QString &message);
532 void raiseNamePrefixTooLongError();
534 QXmlStreamEntityResolver *entityResolver;
538
539
540
541
542 inline void setType(
const QXmlStreamReader::TokenType t)
544 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)