Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qxmlstream_p.h
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4//
5// W A R N I N G
6// -------------
7//
8// This file is not part of the Qt API. It exists for the convenience
9// of other Qt classes. This header file may change from version to
10// version without notice, or even be removed.
11//
12// We mean it.
13//
14
15#include <QtCore/private/qglobal_p.h>
16#include <qstringconverter.h>
17#include <qxmlstream.h>
18#include "qxmlstreamgrammar_p.h"
19#include <QtCore/qhash.h>
20#include <QCoreApplication> // Q_DECLARE_TR_FUNCTIONS
21
22
23#include <memory>
24#include <optional>
25
26#ifndef QXMLSTREAM_P_H
27#define QXMLSTREAM_P_H
28
30
31namespace QtPrivate {
32
34{
35public:
36 const QString *m_string = nullptr;
39
40 constexpr XmlStringRef() = default;
41 constexpr inline XmlStringRef(const QString *string, qsizetype pos, qsizetype length)
43 {
44 }
45 XmlStringRef(const QString *string)
47 {
48 }
49
50 operator QXmlString() const {
51 if (!m_string)
52 return QXmlString();
54 d.setBegin(d.data() + m_pos);
55 d.size = m_size;
56 return QXmlString(std::move(d));
57 }
58
59 void clear() { m_string = nullptr; m_pos = 0; m_size= 0; }
61 bool isEmpty() const { return m_size == 0; }
62 bool isNull() const { return !m_string; }
63 QString toString() const { return view().toString(); }
64
76
77#define MAKE_MEMBER(name) \
78 auto name () const noexcept { return view(). name (); }
81 MAKE_MEMBER(empty)
84 MAKE_MEMBER(cbegin)
85 MAKE_MEMBER(cend)
86 MAKE_MEMBER(rbegin)
87 MAKE_MEMBER(rend)
88 MAKE_MEMBER(crbegin)
89 MAKE_MEMBER(crend)
90#undef MAKE_MEMBER
91
92#define MAKE_OP(op) \
93 friend auto operator op(const XmlStringRef &lhs, const XmlStringRef &rhs) noexcept { return lhs.view() op rhs.view(); } \
94 /*end*/
95 MAKE_OP(==)
96 MAKE_OP(!=)
97 MAKE_OP(<=)
98 MAKE_OP(>=)
99 MAKE_OP(<)
100 MAKE_OP(>)
101#undef MAKE_OP
102#define MAKE_OP(op) \
103 friend auto operator op(const XmlStringRef &lhs, QStringView rhs) noexcept { return lhs.view() op rhs; } \
104 friend auto operator op(QStringView lhs, const XmlStringRef &rhs) noexcept { return lhs op rhs.view(); } \
105 /*end*/
106 MAKE_OP(==)
107 MAKE_OP(!=)
108 MAKE_OP(<=)
109 MAKE_OP(>=)
110 MAKE_OP(<)
111 MAKE_OP(>)
112#undef MAKE_OP
113};
114
115}
116
117using namespace QtPrivate;
118
119template <typename T> class QXmlStreamSimpleStack
120{
121 Q_DISABLE_COPY_MOVE(QXmlStreamSimpleStack)
122
123 T *data;
124 qsizetype tos, cap;
125public:
127 : data(nullptr), tos(-1), cap(0)
128 {}
130 {
131 if (data) {
132 std::destroy_n(data, size());
133 free(data);
134 }
135 }
136
137 inline void reserve(qsizetype extraCapacity)
138 {
139 if (tos + extraCapacity + 1 > cap) {
140 cap = qMax(tos + extraCapacity + 1, cap << 1 );
141 void *ptr = realloc(static_cast<void *>(data), cap * sizeof(T));
142 data = reinterpret_cast<T *>(ptr);
144 }
145 }
146
147 inline T &push() { reserve(1); return rawPush(); }
148 inline T &rawPush() { return *new (data + (++tos)) T; }
149 inline const T &top() const { return data[tos]; }
150 inline T &top() { return data[tos]; }
151 inline T pop() { T t = std::move(data[tos]); std::destroy_at(data + tos); --tos; return t; }
152 inline T &operator[](qsizetype index) { return data[index]; }
153 inline const T &at(qsizetype index) const { return data[index]; }
154 inline qsizetype size() const { return tos + 1; }
155 inline void resize(qsizetype s) { tos = s - 1; }
156 inline bool isEmpty() const { return tos < 0; }
157 inline void clear() { tos = -1; }
158
159 using const_iterator = const T*;
160 using iterator = T*;
161 T *begin() { return data; }
162 const T *begin() const { return data; }
163 const T *cbegin() const { return begin(); }
164 T *end() { return data + size(); }
165 const T *end() const { return data + size(); }
166 const T *cend() const { return end(); }
167};
168
173
175public:
181
190
191
193 QXmlStreamSimpleStack<NamespaceDeclaration> namespaceDeclarations;
198
209
210 QXmlStreamSimpleStack<Tag> tagStack;
211
212
213 inline Tag tagStack_pop() {
214 Tag tag = tagStack.pop();
215 tagStackStringStorageSize = tag.tagStackStringStorageSize;
216 namespaceDeclarations.resize(tag.namespaceDeclarationsSize);
217 tagsDone = tagStack.isEmpty();
218 return tag;
219 }
220 inline Tag &tagStack_push() {
221 Tag &tag = tagStack.push();
222 tag.tagStackStringStorageSize = tagStackStringStorageSize;
223 tag.namespaceDeclarationsSize = namespaceDeclarations.size();
224 return tag;
225 }
226};
227
228
229class QXmlStreamEntityResolver;
231{
232 QXmlStreamReader *q_ptr;
233 Q_DECLARE_PUBLIC(QXmlStreamReader)
234public:
235 QXmlStreamReaderPrivate(QXmlStreamReader *q);
237 void init();
238
245 QXmlStreamSimpleStack<uint> putStack;
260 // these hash tables use a QStringView as a key to avoid creating QStrings
261 // just for lookup. The keys are usually views into Entity::name and thus
262 // are guaranteed to have the same lifetime as the referenced data:
263 QHash<QStringView, Entity> entityHash;
264 QHash<QStringView, Entity> parameterEntityHash;
266 {
267 QHash<QStringView, Entity> *hash;
269 };
270 QXmlStreamSimpleStack<QEntityReference> entityReferenceStack;
273 inline bool referenceEntity(QHash<QStringView, Entity> *hash, Entity &entity)
274 {
275 Q_ASSERT(hash);
276 if (entity.isCurrentlyReferenced) {
277 raiseWellFormedError(QXmlStream::tr("Self-referencing entity detected."));
278 return false;
279 }
280 // entityLength represents the amount of additional characters the
281 // entity expands into (can be negative for e.g. &amp;). It's used to
282 // avoid DoS attacks through recursive entity expansions
283 entityLength += entity.value.size() - entity.name.size() - 2;
285 raiseWellFormedError(QXmlStream::tr("Entity expands to more characters than the entity expansion limit."));
286 return false;
287 }
288 entity.isCurrentlyReferenced = true;
289 entityReferenceStack.push() = { hash, entity.name };
291 return true;
292 }
293
294
298 bool atEnd;
299
300 enum class XmlContext
301 {
302 Prolog,
303 Body,
304 };
305
307 bool foundDTD = false;
308 bool isValidToken(QXmlStreamReader::TokenType type);
310
314 QXmlStreamReader::TokenType type;
315 QXmlStreamReader::Error error;
318
320
321
322 void write(const QString &);
323 void write(const char *);
324
325
326 QXmlStreamAttributes attributes;
331 uint resolveCharRef(int symbolIndex);
336
349 QXmlStreamSimpleStack<DtdAttribute> dtdAttributes;
355 QXmlStreamSimpleStack<NotationDeclaration> notationDeclarations;
356 QXmlStreamNotationDeclarations publicNotationDeclarations;
357 QXmlStreamNamespaceDeclarations publicNamespaceDeclarations;
358
376 QXmlStreamSimpleStack<EntityDeclaration> entityDeclarations;
377 QXmlStreamEntityDeclarations publicEntityDeclarations;
378
380
398 uint hasStandalone : 1; // TODO: expose in public API
399
401 void resume(int rule);
402
403 inline bool entitiesMustBeDeclared() const {
404 return (!inParseEntity
405 && (standalone
407 && !referenceToParameterEntityDetected // Errata 13 as of 2006-04-25
409 }
410
411 // qlalr parser
412 int tos;
414 struct Value {
415 qsizetype pos; // offset into textBuffer
416 qsizetype len; // length incl. prefix (if any)
417 qint16 prefix; // prefix of a name (as in "prefix:name") limited to 4k in fastScanName()
419 };
420
423 inline void reallocateStack();
424 inline Value &sym(int index) const
425 { return sym_stack[tos + index - 1]; }
427 inline void clearTextBuffer() {
428 if (!scanDtd) {
430 textBuffer.reserve(256);
431 }
432 }
437 QXmlStreamSimpleStack<Attribute> attributeStack;
438
440 const Value &symbol = sym(index);
441 return XmlStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
442 }
444 {
445 const Value &symbol = sym(index);
446 return QStringView(textBuffer.data() + symbol.pos, symbol.len).mid(symbol.prefix);
447 }
449 const Value &symbol = sym(index);
450 return XmlStringRef(&textBuffer, symbol.pos, symbol.len);
451 }
453 const Value &symbol = sym(index);
454 return XmlStringRef(&textBuffer, symbol.pos + symbol.prefix + offset, symbol.len - symbol.prefix - offset);
455 }
457 const Value &symbol = sym(index);
458 if (symbol.prefix)
459 return XmlStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
460 return XmlStringRef();
461 }
462 inline XmlStringRef symString(const Value &symbol) {
463 return XmlStringRef(&textBuffer, symbol.pos + symbol.prefix, symbol.len - symbol.prefix);
464 }
465 inline XmlStringRef symName(const Value &symbol) {
466 return XmlStringRef(&textBuffer, symbol.pos, symbol.len);
467 }
468 inline XmlStringRef symPrefix(const Value &symbol) {
469 if (symbol.prefix)
470 return XmlStringRef(&textBuffer, symbol.pos, symbol.prefix - 1);
471 return XmlStringRef();
472 }
473
474 inline void clearSym() { Value &val = sym(1); val.pos = textBuffer.size(); val.len = 0; }
475
476
477 short token;
479
481 inline uint getChar();
482 inline uint peekChar();
483 inline void putChar(uint c) { putStack.push() = c; }
484 inline void putChar(QChar c) { putStack.push() = c.unicode(); }
490
491 bool scanUntil(const char *str, short tokenToInject = -1);
492 bool scanString(const char *str, short tokenToInject, bool requireSpace = true);
493 inline void injectToken(ushort tokenToInject) {
494 putChar(int(tokenToInject) << 16);
495 }
496
499 std::unique_ptr<QXmlStreamReaderPrivate> entityParser;
500
503 bool scanNData();
506
507
508 // scan optimization functions. Not strictly necessary but LALR is
509 // not very well suited for scanning fast
513 std::optional<qsizetype> fastScanName(Value *val = nullptr);
515
516
517 bool parse();
518 inline void consumeRule(int);
519
520 void raiseError(QXmlStreamReader::Error error, const QString& message = QString());
523
524 QXmlStreamEntityResolver *entityResolver;
525
526private:
532 inline void setType(const QXmlStreamReader::TokenType t)
533 {
534 if (type != QXmlStreamReader::Invalid)
535 type = t;
536 }
537};
538
540
541#endif // QXMLSTREAM_P_H
542
\inmodule QtCore
\inmodule QtCore
Definition qbytearray.h:57
\inmodule QtCore
\inmodule QtCore \reentrant
Definition qiodevice.h:34
\inmodule QtCore
\inmodule QtCore
Definition qstringview.h:78
value_type & reference
Alias for {value_type &}.
Definition qstringview.h:84
const QChar value_type
Alias for {const QChar}.
Definition qstringview.h:81
const_pointer const_iterator
This typedef provides an STL-style const iterator for QStringView.
Definition qstringview.h:90
value_type & const_reference
Alias for {value_type &}.
Definition qstringview.h:85
pointer iterator
This typedef provides an STL-style const iterator for QStringView.
Definition qstringview.h:89
std::ptrdiff_t difference_type
Alias for {std::ptrdiff_t}.
Definition qstringview.h:82
QString toString() const
Returns a deep copy of this string view's data as a QString.
Definition qstring.h:1121
std::reverse_iterator< const_iterator > const_reverse_iterator
This typedef provides an STL-style const reverse iterator for QStringView.
Definition qstringview.h:92
value_type * pointer
Alias for {value_type *}.
Definition qstringview.h:86
constexpr QStringView mid(qsizetype pos, qsizetype n=-1) const noexcept
Returns the substring of length length starting at position start in this object.
value_type * const_pointer
Alias for {value_type *}.
Definition qstringview.h:87
std::reverse_iterator< iterator > reverse_iterator
This typedef provides an STL-style const reverse iterator for QStringView.
Definition qstringview.h:91
qsizetype size_type
Alias for qsizetype.
Definition qstringview.h:83
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
void reserve(qsizetype size)
Ensures the string has space for at least size characters.
Definition qstring.h:1325
qsizetype size() const noexcept
Returns the number of characters in this string.
Definition qstring.h:186
DataPointer & data_ptr()
Definition qstring.h:1093
QChar * data()
Returns a pointer to the data stored in the QString.
Definition qstring.h:1240
QString & append(QChar c)
Definition qstring.cpp:3252
void resize(qsizetype size)
Sets the size of the string to size characters.
Definition qstring.cpp:2668
qsizetype initialTagStackStringStorageSize
XmlStringRef addToStringStorage(QAnyStringView s)
QXmlStreamSimpleStack< NamespaceDeclaration > namespaceDeclarations
QXmlStreamSimpleStack< Tag > tagStack
QXmlStreamReaderPrivate(QXmlStreamReader *q)
XmlStringRef symName(const Value &symbol)
void parseEntity(const QString &value)
void raiseError(QXmlStreamReader::Error error, const QString &message=QString())
XmlStringRef documentVersion
void resume(int rule)
bool scanUntil(const char *str, short tokenToInject=-1)
XmlStringRef symPrefix(int index)
bool referenceEntity(QHash< QStringView, Entity > *hash, Entity &entity)
void checkPublicLiteral(QStringView publicId)
QHash< QStringView, Entity > entityHash
bool entitiesMustBeDeclared() const
bool isValidToken(QXmlStreamReader::TokenType type)
XmlStringRef symString(int index, int offset)
qsizetype fastScanLiteralContent()
QXmlStreamEntityDeclarations publicEntityDeclarations
QString resolveUndeclaredEntity(const QString &name)
XmlStringRef symString(const Value &symbol)
std::optional< qsizetype > fastScanName(Value *val=nullptr)
QXmlStreamAttributes attributes
void putString(QStringView s, qsizetype from=0)
Value & sym(int index) const
void write(const QString &)
uint resolveCharRef(int symbolIndex)
QXmlStreamSimpleStack< EntityDeclaration > entityDeclarations
qsizetype fastScanNMTOKEN()
void putStringLiteral(QStringView s)
void putReplacement(QStringView s)
std::unique_ptr< QXmlStreamReaderPrivate > entityParser
XmlStringRef symName(int index)
QXmlStreamReader::TokenType type
XmlStringRef processingInstructionData
void putReplacementInAttributeValue(QStringView s)
QXmlStreamSimpleStack< Attribute > attributeStack
XmlStringRef namespaceForPrefix(QStringView prefix)
XmlStringRef symPrefix(const Value &symbol)
QXmlStreamSimpleStack< uint > putStack
QHash< QStringView, Entity > parameterEntityHash
void raiseWellFormedError(const QString &message)
QXmlStreamNotationDeclarations publicNotationDeclarations
XmlStringRef documentEncoding
QXmlStreamNamespaceDeclarations publicNamespaceDeclarations
QXmlStreamEntityResolver * entityResolver
QXmlStreamSimpleStack< DtdAttribute > dtdAttributes
qsizetype fastScanContentCharList()
XmlStringRef processingInstructionTarget
void injectToken(ushort tokenToInject)
XmlStringRef lastAttributeValue
void write(const char *)
XmlStringRef symString(int index)
QXmlStreamReader::Error error
QXmlStreamSimpleStack< NotationDeclaration > notationDeclarations
bool scanString(const char *str, short tokenToInject, bool requireSpace=true)
QXmlStreamSimpleStack< QEntityReference > entityReferenceStack
QStringView symView(int index) const
void resize(qsizetype s)
const T * cbegin() const
const T & top() const
void reserve(qsizetype extraCapacity)
const T * cend() const
const T * begin() const
const T & at(qsizetype index) const
T & operator[](qsizetype index)
qsizetype size() const
const T * end() const
QStringView::reverse_iterator reverse_iterator
QStringView view() const
QStringView::difference_type difference_type
XmlStringRef(const QString *string)
QStringView::size_type size_type
constexpr XmlStringRef()=default
const QString * m_string
QString toString() const
constexpr XmlStringRef(const QString *string, qsizetype pos, qsizetype length)
QStringView::const_reverse_iterator const_reverse_iterator
QHash< int, QWidget * > hash
[35multi]
QString str
[2]
Combined button and popup list for selecting options.
\macro QT_NO_KEYWORDS >
#define Q_DECLARE_TR_FUNCTIONS(context)
AudioChannelLayoutTag tag
DBusConnection const char * rule
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
static ControlElement< T > * ptr(QWidget *widget)
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLuint GLuint end
GLenum GLuint GLenum GLsizei length
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum type
GLuint GLsizei const GLchar * message
GLenum GLuint GLintptr offset
GLuint name
GLdouble s
[6]
Definition qopenglext.h:235
const GLubyte * c
GLdouble GLdouble t
Definition qopenglext.h:243
GLdouble GLdouble GLdouble GLdouble q
Definition qopenglext.h:259
GLuint64EXT * result
[6]
GLenum cap
GLsizei const GLchar *const * string
[0]
Definition qopenglext.h:694
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
QtPrivate::QRegularExpressionMatchIteratorRangeBasedForIterator begin(const QRegularExpressionMatchIterator &iterator)
unsigned char uchar
Definition qtypes.h:32
short qint16
Definition qtypes.h:47
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
long long qint64
Definition qtypes.h:60
unsigned short ushort
Definition qtypes.h:33
#define MAKE_MEMBER(name)
#define MAKE_OP(op)
Q_CHECK_PTR(a=new int[80])
QObject::connect nullptr
void setBegin(T *begin) noexcept
NamespaceDeclaration namespaceDeclaration
static Entity createLiteral(QLatin1StringView name, QLatin1StringView value)
Entity(const QString &name, const QString &value)
QHash< QStringView, Entity > * hash