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