1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtCore module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #ifndef QXMLSTREAM_H
41 #define QXMLSTREAM_H
42 
43 #include <QtCore/qiodevice.h>
44 
45 #ifndef QT_NO_XMLSTREAM
46 
47 #include <QtCore/qstring.h>
48 #include <QtCore/qvector.h>
49 #include <QtCore/qscopedpointer.h>
50 
51 QT_BEGIN_NAMESPACE
52 
53 
54 class Q_CORE_EXPORT QXmlStreamStringRef {
55     QString m_string;
56     int m_position, m_size;
57 public:
QXmlStreamStringRef()58     inline QXmlStreamStringRef():m_position(0), m_size(0){}
QXmlStreamStringRef(const QStringRef & aString)59     inline QXmlStreamStringRef(const QStringRef &aString)
60         :m_string(aString.string()?*aString.string():QString()), m_position(aString.position()), m_size(aString.size()){}
QXmlStreamStringRef(const QString & aString)61     QXmlStreamStringRef(const QString &aString) : m_string(aString), m_position(0), m_size(m_string.size()) {}
QXmlStreamStringRef(QString && aString)62     QXmlStreamStringRef(QString &&aString) noexcept : m_string(std::move(aString)), m_position(0), m_size(m_string.size()) {}
63 
64 #if QT_VERSION < QT_VERSION_CHECK(6,0,0)
QXmlStreamStringRef(const QXmlStreamStringRef & other)65     QXmlStreamStringRef(const QXmlStreamStringRef &other) // = default
66         : m_string(other.m_string), m_position(other.m_position), m_size(other.m_size) {}
QXmlStreamStringRef(QXmlStreamStringRef && other)67     QXmlStreamStringRef(QXmlStreamStringRef &&other) noexcept // = default
68         : m_string(std::move(other.m_string)), m_position(other.m_position), m_size(other.m_size) {}
69     QXmlStreamStringRef &operator=(QXmlStreamStringRef &&other) noexcept // = default
70     { swap(other); return *this; }
71     QXmlStreamStringRef &operator=(const QXmlStreamStringRef &other) // = default
72     { m_string = other.m_string; m_position = other.m_position; m_size = other.m_size; return *this; }
~QXmlStreamStringRef()73     inline ~QXmlStreamStringRef() {} // ### this prevents (or deprecates) all the move/copy special member functions,
74                                      // ### that's why we need to provide them by hand above. We can't remove it in
75                                      // ### Qt 5, since that would change the way its passed to functions. In Qt 6, remove all.
76 #endif // Qt < 6.0
77 
swap(QXmlStreamStringRef & other)78     void swap(QXmlStreamStringRef &other) noexcept
79     {
80         qSwap(m_string, other.m_string);
81         qSwap(m_position, other.m_position);
82         qSwap(m_size, other.m_size);
83     }
84 
clear()85     inline void clear() { m_string.clear(); m_position = m_size = 0; }
QStringRef()86     inline operator QStringRef() const { return QStringRef(&m_string, m_position, m_size); }
string()87     inline const QString *string() const { return &m_string; }
position()88     inline int position() const { return m_position; }
size()89     inline int size() const { return m_size; }
90 };
91 Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QXmlStreamStringRef)
92 
93 
94 class QXmlStreamReaderPrivate;
95 class QXmlStreamAttributes;
96 class Q_CORE_EXPORT QXmlStreamAttribute {
97     QXmlStreamStringRef m_name, m_namespaceUri, m_qualifiedName, m_value;
98 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
99     void *reserved;
100 #endif
101     uint m_isDefault : 1;
102     friend class QXmlStreamReaderPrivate;
103     friend class QXmlStreamAttributes;
104 public:
105     QXmlStreamAttribute();
106     QXmlStreamAttribute(const QString &qualifiedName, const QString &value);
107     QXmlStreamAttribute(const QString &namespaceUri, const QString &name, const QString &value);
108 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
109     QXmlStreamAttribute(const QXmlStreamAttribute &);
QXmlStreamAttribute(QXmlStreamAttribute && other)110     QXmlStreamAttribute(QXmlStreamAttribute &&other) noexcept // = default;
111         : m_name(std::move(other.m_name)),
112           m_namespaceUri(std::move(other.m_namespaceUri)),
113           m_qualifiedName(std::move(other.m_qualifiedName)),
114           m_value(std::move(other.m_value)),
115           reserved(other.reserved),
116           m_isDefault(other.m_isDefault)
117     {
118         other.reserved = nullptr;
119     }
120     QXmlStreamAttribute &operator=(QXmlStreamAttribute &&other) noexcept // = default;
121     {
122         m_name = std::move(other.m_name);
123         m_namespaceUri = std::move(other.m_namespaceUri);
124         m_qualifiedName = std::move(other.m_qualifiedName);
125         m_value = std::move(other.m_value);
126         qSwap(reserved, other.reserved);
127         m_isDefault = other.m_isDefault;
128         return *this;
129     }
130     QXmlStreamAttribute& operator=(const QXmlStreamAttribute &);
131     ~QXmlStreamAttribute();
132 #endif // < Qt 6
133 
namespaceUri()134     inline QStringRef namespaceUri() const { return m_namespaceUri; }
name()135     inline QStringRef name() const { return m_name; }
qualifiedName()136     inline QStringRef qualifiedName() const { return m_qualifiedName; }
prefix()137     inline QStringRef prefix() const {
138         return QStringRef(m_qualifiedName.string(),
139                           m_qualifiedName.position(),
140                           qMax(0, m_qualifiedName.size() - m_name.size() - 1));
141     }
value()142     inline QStringRef value() const { return m_value; }
isDefault()143     inline bool isDefault() const { return m_isDefault; }
144     inline bool operator==(const QXmlStreamAttribute &other) const {
145         return (value() == other.value()
146                 && (namespaceUri().isNull() ? (qualifiedName() == other.qualifiedName())
147                     : (namespaceUri() == other.namespaceUri() && name() == other.name())));
148     }
149     inline bool operator!=(const QXmlStreamAttribute &other) const
150         { return !operator==(other); }
151 };
152 
153 Q_DECLARE_TYPEINFO(QXmlStreamAttribute, Q_MOVABLE_TYPE);
154 
155 class Q_CORE_EXPORT QXmlStreamAttributes : public QVector<QXmlStreamAttribute>
156 {
157 public:
QXmlStreamAttributes()158     inline QXmlStreamAttributes() {}
159     QStringRef value(const QString &namespaceUri, const QString &name) const;
160     QStringRef value(const QString &namespaceUri, QLatin1String name) const;
161     QStringRef value(QLatin1String namespaceUri, QLatin1String name) const;
162     QStringRef value(const QString &qualifiedName) const;
163     QStringRef value(QLatin1String qualifiedName) const;
164     void append(const QString &namespaceUri, const QString &name, const QString &value);
165     void append(const QString &qualifiedName, const QString &value);
166 
hasAttribute(const QString & qualifiedName)167     inline bool hasAttribute(const QString &qualifiedName) const
168     {
169         return !value(qualifiedName).isNull();
170     }
171 
hasAttribute(QLatin1String qualifiedName)172     inline bool hasAttribute(QLatin1String qualifiedName) const
173     {
174         return !value(qualifiedName).isNull();
175     }
176 
hasAttribute(const QString & namespaceUri,const QString & name)177     inline bool hasAttribute(const QString &namespaceUri, const QString &name) const
178     {
179         return !value(namespaceUri, name).isNull();
180     }
181 
182     using QVector<QXmlStreamAttribute>::append;
183 };
184 
185 class Q_CORE_EXPORT QXmlStreamNamespaceDeclaration {
186     QXmlStreamStringRef m_prefix, m_namespaceUri;
187 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
188     void *reserved;
189 #endif
190 
191     friend class QXmlStreamReaderPrivate;
192 public:
193     QXmlStreamNamespaceDeclaration();
194     QXmlStreamNamespaceDeclaration(const QString &prefix, const QString &namespaceUri);
195 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
196     QXmlStreamNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &);
QXmlStreamNamespaceDeclaration(QXmlStreamNamespaceDeclaration && other)197     QXmlStreamNamespaceDeclaration(QXmlStreamNamespaceDeclaration &&other) noexcept // = default
198         : m_prefix(std::move(other.m_prefix)),
199           m_namespaceUri(std::move(other.m_namespaceUri)),
200           reserved(other.reserved)
201     {
202         other.reserved = nullptr;
203     }
204     QXmlStreamNamespaceDeclaration &operator=(QXmlStreamNamespaceDeclaration &&other) noexcept // = default
205     {
206         m_prefix = std::move(other.m_prefix);
207         m_namespaceUri = std::move(other.m_namespaceUri);
208         qSwap(reserved, other.reserved);
209         return *this;
210     }
211     ~QXmlStreamNamespaceDeclaration();
212     QXmlStreamNamespaceDeclaration& operator=(const QXmlStreamNamespaceDeclaration &);
213 #endif // < Qt 6
214 
prefix()215     inline QStringRef prefix() const { return m_prefix; }
namespaceUri()216     inline QStringRef namespaceUri() const { return m_namespaceUri; }
217     inline bool operator==(const QXmlStreamNamespaceDeclaration &other) const {
218         return (prefix() == other.prefix() && namespaceUri() == other.namespaceUri());
219     }
220     inline bool operator!=(const QXmlStreamNamespaceDeclaration &other) const
221         { return !operator==(other); }
222 };
223 
224 Q_DECLARE_TYPEINFO(QXmlStreamNamespaceDeclaration, Q_MOVABLE_TYPE);
225 typedef QVector<QXmlStreamNamespaceDeclaration> QXmlStreamNamespaceDeclarations;
226 
227 class Q_CORE_EXPORT QXmlStreamNotationDeclaration {
228     QXmlStreamStringRef m_name, m_systemId, m_publicId;
229 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
230     void *reserved;
231 #endif
232 
233     friend class QXmlStreamReaderPrivate;
234 public:
235     QXmlStreamNotationDeclaration();
236 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
237     ~QXmlStreamNotationDeclaration();
238     QXmlStreamNotationDeclaration(const QXmlStreamNotationDeclaration &);
QXmlStreamNotationDeclaration(QXmlStreamNotationDeclaration && other)239     QXmlStreamNotationDeclaration(QXmlStreamNotationDeclaration &&other) noexcept // = default
240         : m_name(std::move(other.m_name)),
241           m_systemId(std::move(other.m_systemId)),
242           m_publicId(std::move(other.m_publicId)),
243           reserved(other.reserved)
244     {
245         other.reserved = nullptr;
246     }
247     QXmlStreamNotationDeclaration& operator=(const QXmlStreamNotationDeclaration &);
248     QXmlStreamNotationDeclaration &operator=(QXmlStreamNotationDeclaration &&other) noexcept // = default
249     {
250         m_name = std::move(other.m_name);
251         m_systemId = std::move(other.m_systemId);
252         m_publicId = std::move(other.m_publicId);
253         qSwap(reserved, other.reserved);
254         return *this;
255     }
256 #endif // < Qt 6
257 
name()258     inline QStringRef name() const { return m_name; }
systemId()259     inline QStringRef systemId() const { return m_systemId; }
publicId()260     inline QStringRef publicId() const { return m_publicId; }
261     inline bool operator==(const QXmlStreamNotationDeclaration &other) const {
262         return (name() == other.name() && systemId() == other.systemId()
263                 && publicId() == other.publicId());
264     }
265     inline bool operator!=(const QXmlStreamNotationDeclaration &other) const
266         { return !operator==(other); }
267 };
268 
269 Q_DECLARE_TYPEINFO(QXmlStreamNotationDeclaration, Q_MOVABLE_TYPE);
270 typedef QVector<QXmlStreamNotationDeclaration> QXmlStreamNotationDeclarations;
271 
272 class Q_CORE_EXPORT QXmlStreamEntityDeclaration {
273     QXmlStreamStringRef m_name, m_notationName, m_systemId, m_publicId, m_value;
274 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
275     void *reserved;
276 #endif
277 
278     friend class QXmlStreamReaderPrivate;
279 public:
280     QXmlStreamEntityDeclaration();
281 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
282     ~QXmlStreamEntityDeclaration();
283     QXmlStreamEntityDeclaration(const QXmlStreamEntityDeclaration &);
QXmlStreamEntityDeclaration(QXmlStreamEntityDeclaration && other)284     QXmlStreamEntityDeclaration(QXmlStreamEntityDeclaration &&other) noexcept // = default
285         : m_name(std::move(other.m_name)),
286           m_notationName(std::move(other.m_notationName)),
287           m_systemId(std::move(other.m_systemId)),
288           m_publicId(std::move(other.m_publicId)),
289           m_value(std::move(other.m_value)),
290           reserved(other.reserved)
291     {
292         other.reserved = nullptr;
293     }
294     QXmlStreamEntityDeclaration& operator=(const QXmlStreamEntityDeclaration &);
295     QXmlStreamEntityDeclaration &operator=(QXmlStreamEntityDeclaration &&other) noexcept // = default
296     {
297         m_name = std::move(other.m_name);
298         m_notationName = std::move(other.m_notationName);
299         m_systemId = std::move(other.m_systemId);
300         m_publicId = std::move(other.m_publicId);
301         m_value = std::move(other.m_value);
302         qSwap(reserved, other.reserved);
303         return *this;
304     }
305 #endif // < Qt 6
306 
name()307     inline QStringRef name() const { return m_name; }
notationName()308     inline QStringRef notationName() const { return m_notationName; }
systemId()309     inline QStringRef systemId() const { return m_systemId; }
publicId()310     inline QStringRef publicId() const { return m_publicId; }
value()311     inline QStringRef value() const { return m_value; }
312     inline bool operator==(const QXmlStreamEntityDeclaration &other) const {
313         return (name() == other.name()
314                 && notationName() == other.notationName()
315                 && systemId() == other.systemId()
316                 && publicId() == other.publicId()
317                 && value() == other.value());
318     }
319     inline bool operator!=(const QXmlStreamEntityDeclaration &other) const
320         { return !operator==(other); }
321 };
322 
323 Q_DECLARE_TYPEINFO(QXmlStreamEntityDeclaration, Q_MOVABLE_TYPE);
324 typedef QVector<QXmlStreamEntityDeclaration> QXmlStreamEntityDeclarations;
325 
326 
327 class Q_CORE_EXPORT QXmlStreamEntityResolver
328 {
329 public:
330     virtual ~QXmlStreamEntityResolver();
331     virtual QString resolveEntity(const QString& publicId, const QString& systemId);
332     virtual QString resolveUndeclaredEntity(const QString &name);
333 };
334 
335 #ifndef QT_NO_XMLSTREAMREADER
336 class Q_CORE_EXPORT QXmlStreamReader {
337     QDOC_PROPERTY(bool namespaceProcessing READ namespaceProcessing WRITE setNamespaceProcessing)
338 public:
339     enum TokenType {
340         NoToken = 0,
341         Invalid,
342         StartDocument,
343         EndDocument,
344         StartElement,
345         EndElement,
346         Characters,
347         Comment,
348         DTD,
349         EntityReference,
350         ProcessingInstruction
351     };
352 
353 
354     QXmlStreamReader();
355     explicit QXmlStreamReader(QIODevice *device);
356     explicit QXmlStreamReader(const QByteArray &data);
357     explicit QXmlStreamReader(const QString &data);
358     explicit QXmlStreamReader(const char * data);
359     ~QXmlStreamReader();
360 
361     void setDevice(QIODevice *device);
362     QIODevice *device() const;
363     void addData(const QByteArray &data);
364     void addData(const QString &data);
365     void addData(const char *data);
366     void clear();
367 
368 
369     bool atEnd() const;
370     TokenType readNext();
371 
372     bool readNextStartElement();
373     void skipCurrentElement();
374 
375     TokenType tokenType() const;
376     QString tokenString() const;
377 
378     void setNamespaceProcessing(bool);
379     bool namespaceProcessing() const;
380 
isStartDocument()381     inline bool isStartDocument() const { return tokenType() == StartDocument; }
isEndDocument()382     inline bool isEndDocument() const { return tokenType() == EndDocument; }
isStartElement()383     inline bool isStartElement() const { return tokenType() == StartElement; }
isEndElement()384     inline bool isEndElement() const { return tokenType() == EndElement; }
isCharacters()385     inline bool isCharacters() const { return tokenType() == Characters; }
386     bool isWhitespace() const;
387     bool isCDATA() const;
isComment()388     inline bool isComment() const { return tokenType() == Comment; }
isDTD()389     inline bool isDTD() const { return tokenType() == DTD; }
isEntityReference()390     inline bool isEntityReference() const { return tokenType() == EntityReference; }
isProcessingInstruction()391     inline bool isProcessingInstruction() const { return tokenType() == ProcessingInstruction; }
392 
393     bool isStandaloneDocument() const;
394     QStringRef documentVersion() const;
395     QStringRef documentEncoding() const;
396 
397     qint64 lineNumber() const;
398     qint64 columnNumber() const;
399     qint64 characterOffset() const;
400 
401     QXmlStreamAttributes attributes() const;
402 
403     enum ReadElementTextBehaviour {
404         ErrorOnUnexpectedElement,
405         IncludeChildElements,
406         SkipChildElements
407     };
408     QString readElementText(ReadElementTextBehaviour behaviour = ErrorOnUnexpectedElement);
409 
410     QStringRef name() const;
411     QStringRef namespaceUri() const;
412     QStringRef qualifiedName() const;
413     QStringRef prefix() const;
414 
415     QStringRef processingInstructionTarget() const;
416     QStringRef processingInstructionData() const;
417 
418     QStringRef text() const;
419 
420     QXmlStreamNamespaceDeclarations namespaceDeclarations() const;
421     void addExtraNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &extraNamespaceDeclaraction);
422     void addExtraNamespaceDeclarations(const QXmlStreamNamespaceDeclarations &extraNamespaceDeclaractions);
423     QXmlStreamNotationDeclarations notationDeclarations() const;
424     QXmlStreamEntityDeclarations entityDeclarations() const;
425     QStringRef dtdName() const;
426     QStringRef dtdPublicId() const;
427     QStringRef dtdSystemId() const;
428 
429     int entityExpansionLimit() const;
430     void setEntityExpansionLimit(int limit);
431 
432     enum Error {
433         NoError,
434         UnexpectedElementError,
435         CustomError,
436         NotWellFormedError,
437         PrematureEndOfDocumentError
438     };
439     void raiseError(const QString& message = QString());
440     QString errorString() const;
441     Error error() const;
442 
hasError()443     inline bool hasError() const
444     {
445         return error() != NoError;
446     }
447 
448     void setEntityResolver(QXmlStreamEntityResolver *resolver);
449     QXmlStreamEntityResolver *entityResolver() const;
450 
451 private:
452     Q_DISABLE_COPY(QXmlStreamReader)
453     Q_DECLARE_PRIVATE(QXmlStreamReader)
454     QScopedPointer<QXmlStreamReaderPrivate> d_ptr;
455 
456 };
457 #endif // QT_NO_XMLSTREAMREADER
458 
459 #ifndef QT_NO_XMLSTREAMWRITER
460 
461 class QXmlStreamWriterPrivate;
462 
463 class Q_CORE_EXPORT QXmlStreamWriter
464 {
465     QDOC_PROPERTY(bool autoFormatting READ autoFormatting WRITE setAutoFormatting)
466     QDOC_PROPERTY(int autoFormattingIndent READ autoFormattingIndent WRITE setAutoFormattingIndent)
467 public:
468     QXmlStreamWriter();
469     explicit QXmlStreamWriter(QIODevice *device);
470     explicit QXmlStreamWriter(QByteArray *array);
471     explicit QXmlStreamWriter(QString *string);
472     ~QXmlStreamWriter();
473 
474     void setDevice(QIODevice *device);
475     QIODevice *device() const;
476 
477 #if QT_CONFIG(textcodec)
478     void setCodec(QTextCodec *codec);
479     void setCodec(const char *codecName);
480     QTextCodec *codec() const;
481 #endif
482 
483     void setAutoFormatting(bool);
484     bool autoFormatting() const;
485 
486     void setAutoFormattingIndent(int spacesOrTabs);
487     int autoFormattingIndent() const;
488 
489     void writeAttribute(const QString &qualifiedName, const QString &value);
490     void writeAttribute(const QString &namespaceUri, const QString &name, const QString &value);
491     void writeAttribute(const QXmlStreamAttribute& attribute);
492     void writeAttributes(const QXmlStreamAttributes& attributes);
493 
494     void writeCDATA(const QString &text);
495     void writeCharacters(const QString &text);
496     void writeComment(const QString &text);
497 
498     void writeDTD(const QString &dtd);
499 
500     void writeEmptyElement(const QString &qualifiedName);
501     void writeEmptyElement(const QString &namespaceUri, const QString &name);
502 
503     void writeTextElement(const QString &qualifiedName, const QString &text);
504     void writeTextElement(const QString &namespaceUri, const QString &name, const QString &text);
505 
506     void writeEndDocument();
507     void writeEndElement();
508 
509     void writeEntityReference(const QString &name);
510     void writeNamespace(const QString &namespaceUri, const QString &prefix = QString());
511     void writeDefaultNamespace(const QString &namespaceUri);
512     void writeProcessingInstruction(const QString &target, const QString &data = QString());
513 
514     void writeStartDocument();
515     void writeStartDocument(const QString &version);
516     void writeStartDocument(const QString &version, bool standalone);
517     void writeStartElement(const QString &qualifiedName);
518     void writeStartElement(const QString &namespaceUri, const QString &name);
519 
520 #ifndef QT_NO_XMLSTREAMREADER
521     void writeCurrentToken(const QXmlStreamReader &reader);
522 #endif
523 
524     bool hasError() const;
525 
526 private:
527     Q_DISABLE_COPY(QXmlStreamWriter)
528     Q_DECLARE_PRIVATE(QXmlStreamWriter)
529     QScopedPointer<QXmlStreamWriterPrivate> d_ptr;
530 };
531 #endif // QT_NO_XMLSTREAMWRITER
532 
533 QT_END_NAMESPACE
534 
535 #endif // QT_NO_XMLSTREAM
536 #endif // QXMLSTREAM_H
537