src/corelib/xml/qxmlstream.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtCore module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "QtCore/qxmlstream.h"
       
    43 
       
    44 #if defined(QT_BUILD_XML_LIB) && defined(Q_OS_MAC64)
       
    45 // No need to define this in the 64-bit Mac libraries.
       
    46 // Since Qt 4.4 and previous weren't supported in 64-bit, there are
       
    47 // no QXmlStream* symbols to keep compatibility with
       
    48 # define QT_NO_XMLSTREAM
       
    49 #endif
       
    50 
       
    51 #ifndef QT_NO_XMLSTREAM
       
    52 
       
    53 #include "qxmlutils_p.h"
       
    54 #include <qdebug.h>
       
    55 #include <qfile.h>
       
    56 #include <stdio.h>
       
    57 #include <qtextcodec.h>
       
    58 #include <qstack.h>
       
    59 #include <qbuffer.h>
       
    60 #ifndef QT_BOOTSTRAPPED
       
    61 #include <qcoreapplication.h>
       
    62 #else
       
    63 // This specialization of Q_DECLARE_TR_FUNCTIONS is not in qcoreapplication.h,
       
    64 // because that header depends on QObject being available, which is not the
       
    65 // case for most bootstrapped applications.
       
    66 #define Q_DECLARE_TR_FUNCTIONS(context) \
       
    67 public: \
       
    68     static inline QString tr(const char *sourceText, const char *comment = 0) \
       
    69         { Q_UNUSED(comment); return QString::fromLatin1(sourceText); } \
       
    70     static inline QString trUtf8(const char *sourceText, const char *comment = 0) \
       
    71         { Q_UNUSED(comment); return QString::fromLatin1(sourceText); } \
       
    72     static inline QString tr(const char *sourceText, const char*, int) \
       
    73         { return QString::fromLatin1(sourceText); } \
       
    74     static inline QString trUtf8(const char *sourceText, const char*, int) \
       
    75         { return QString::fromLatin1(sourceText); } \
       
    76 private:
       
    77 #endif
       
    78 QT_BEGIN_NAMESPACE
       
    79 
       
    80 #include "qxmlstream_p.h"
       
    81 
       
    82 /*!
       
    83     \enum QXmlStreamReader::TokenType
       
    84 
       
    85     This enum specifies the type of token the reader just read.
       
    86 
       
    87     \value NoToken The reader has not yet read anything.
       
    88 
       
    89     \value Invalid An error has occurred, reported in error() and
       
    90     errorString().
       
    91 
       
    92     \value StartDocument The reader reports the XML version number in
       
    93     documentVersion(), and the encoding as specified in the XML
       
    94     document in documentEncoding().  If the document is declared
       
    95     standalone, isStandaloneDocument() returns true; otherwise it
       
    96     returns false.
       
    97 
       
    98     \value EndDocument The reader reports the end of the document.
       
    99 
       
   100     \value StartElement The reader reports the start of an element
       
   101     with namespaceUri() and name(). Empty elements are also reported
       
   102     as StartElement, followed directly by EndElement. The convenience
       
   103     function readElementText() can be called to concatenate all
       
   104     content until the corresponding EndElement. Attributes are
       
   105     reported in attributes(), namespace declarations in
       
   106     namespaceDeclarations().
       
   107 
       
   108     \value EndElement The reader reports the end of an element with
       
   109     namespaceUri() and name().
       
   110 
       
   111     \value Characters The reader reports characters in text(). If the
       
   112     characters are all white-space, isWhitespace() returns true. If
       
   113     the characters stem from a CDATA section, isCDATA() returns true.
       
   114 
       
   115     \value Comment The reader reports a comment in text().
       
   116 
       
   117     \value DTD The reader reports a DTD in text(), notation
       
   118     declarations in notationDeclarations(), and entity declarations in
       
   119     entityDeclarations(). Details of the DTD declaration are reported
       
   120     in in dtdName(), dtdPublicId(), and dtdSystemId().
       
   121 
       
   122     \value EntityReference The reader reports an entity reference that
       
   123     could not be resolved.  The name of the reference is reported in
       
   124     name(), the replacement text in text().
       
   125 
       
   126     \value ProcessingInstruction The reader reports a processing
       
   127     instruction in processingInstructionTarget() and
       
   128     processingInstructionData().
       
   129 */
       
   130 
       
   131 /*!
       
   132     \enum QXmlStreamReader::ReadElementTextBehaviour
       
   133 
       
   134     This enum specifies the different behaviours of readElementText().
       
   135 
       
   136     \value ErrorOnUnexpectedElement Raise an UnexpectedElementError and return
       
   137     what was read so far when a child element is encountered.
       
   138 
       
   139     \value IncludeChildElements Recursively include the text from child elements.
       
   140 
       
   141     \value SkipChildElements Skip child elements.
       
   142 
       
   143     \since 4.6
       
   144 */
       
   145 
       
   146 /*!
       
   147     \enum QXmlStreamReader::Error
       
   148 
       
   149     This enum specifies different error cases
       
   150 
       
   151     \value NoError No error has occurred.
       
   152 
       
   153     \value CustomError A custom error has been raised with
       
   154     raiseError()
       
   155 
       
   156     \value NotWellFormedError The parser internally raised an error
       
   157     due to the read XML not being well-formed.
       
   158 
       
   159     \value PrematureEndOfDocumentError The input stream ended before a
       
   160     well-formed XML document was parsed. Recovery from this error is
       
   161     possible if more XML arrives in the stream, either by calling
       
   162     addData() or by waiting for it to arrive on the device().
       
   163 
       
   164     \value UnexpectedElementError The parser encountered an element
       
   165     that was different to those it expected.
       
   166 
       
   167 */
       
   168 
       
   169 /*!
       
   170   \class QXmlStreamEntityResolver
       
   171   \reentrant
       
   172   \since 4.4
       
   173 
       
   174   \brief The QXmlStreamEntityResolver class provides an entity
       
   175   resolver for a QXmlStreamReader.
       
   176 
       
   177   \ingroup xml-tools
       
   178  */
       
   179 
       
   180 /*!
       
   181   Destroys the entity resolver.
       
   182  */
       
   183 QXmlStreamEntityResolver::~QXmlStreamEntityResolver()
       
   184 {
       
   185 }
       
   186 
       
   187 /*! \internal
       
   188 
       
   189 This function is a stub for later functionality.
       
   190 */
       
   191 QString QXmlStreamEntityResolver::resolveEntity(const QString& /*publicId*/, const QString& /*systemId*/)
       
   192 {
       
   193     return QString();
       
   194 }
       
   195 
       
   196 
       
   197 /*!
       
   198   Resolves the undeclared entity \a name and returns its replacement
       
   199   text. If the entity is also unknown to the entity resolver, it
       
   200   returns an empty string.
       
   201 
       
   202   The default implementation always returns an empty string.
       
   203 */
       
   204 
       
   205 QString QXmlStreamEntityResolver::resolveUndeclaredEntity(const QString &/*name*/)
       
   206 {
       
   207     return QString();
       
   208 }
       
   209 
       
   210 #ifndef QT_NO_XMLSTREAMREADER
       
   211 
       
   212 QString QXmlStreamReaderPrivate::resolveUndeclaredEntity(const QString &name)
       
   213 {
       
   214     if (entityResolver)
       
   215         return entityResolver->resolveUndeclaredEntity(name);
       
   216     return QString();
       
   217 }
       
   218 
       
   219 
       
   220 
       
   221 /*!
       
   222    \since 4.4
       
   223 
       
   224    Makes \a resolver the new entityResolver().
       
   225 
       
   226    The stream reader does \e not take ownership of the resolver. It's
       
   227    the callers responsibility to ensure that the resolver is valid
       
   228    during the entire life-time of the stream reader object, or until
       
   229    another resolver or 0 is set.
       
   230 
       
   231    \sa entityResolver()
       
   232  */
       
   233 void QXmlStreamReader::setEntityResolver(QXmlStreamEntityResolver *resolver)
       
   234 {
       
   235     Q_D(QXmlStreamReader);
       
   236     d->entityResolver = resolver;
       
   237 }
       
   238 
       
   239 /*!
       
   240   \since 4.4
       
   241 
       
   242   Returns the entity resolver, or 0 if there is no entity resolver.
       
   243 
       
   244   \sa setEntityResolver()
       
   245  */
       
   246 QXmlStreamEntityResolver *QXmlStreamReader::entityResolver() const
       
   247 {
       
   248     Q_D(const QXmlStreamReader);
       
   249     return d->entityResolver;
       
   250 }
       
   251 
       
   252 
       
   253 
       
   254 /*!
       
   255   \class QXmlStreamReader
       
   256   \reentrant
       
   257   \since 4.3
       
   258 
       
   259   \brief The QXmlStreamReader class provides a fast parser for reading
       
   260   well-formed XML via a simple streaming API.
       
   261 
       
   262 
       
   263   \ingroup xml-tools
       
   264 
       
   265   QXmlStreamReader is a faster and more convenient replacement for
       
   266   Qt's own SAX parser (see QXmlSimpleReader). In some cases it might
       
   267   also be a faster and more convenient alternative for use in
       
   268   applications that would otherwise use a DOM tree (see QDomDocument).
       
   269   QXmlStreamReader reads data either from a QIODevice (see
       
   270   setDevice()), or from a raw QByteArray (see addData()).
       
   271 
       
   272   Qt provides QXmlStreamWriter for writing XML.
       
   273 
       
   274   The basic concept of a stream reader is to report an XML document as
       
   275   a stream of tokens, similar to SAX. The main difference between
       
   276   QXmlStreamReader and SAX is \e how these XML tokens are reported.
       
   277   With SAX, the application must provide handlers (callback functions)
       
   278   that receive so-called XML \e events from the parser at the parser's
       
   279   convenience.  With QXmlStreamReader, the application code itself
       
   280   drives the loop and pulls \e tokens from the reader, one after
       
   281   another, as it needs them. This is done by calling readNext(), where
       
   282   the reader reads from the input stream until it completes the next
       
   283   token, at which point it returns the tokenType(). A set of
       
   284   convenient functions including isStartElement() and text() can then
       
   285   be used to examine the token to obtain information about what has
       
   286   been read. The big advantage of this \e pulling approach is the
       
   287   possibility to build recursive descent parsers with it, meaning you
       
   288   can split your XML parsing code easily into different methods or
       
   289   classes. This makes it easy to keep track of the application's own
       
   290   state when parsing XML.
       
   291 
       
   292   A typical loop with QXmlStreamReader looks like this:
       
   293 
       
   294   \snippet doc/src/snippets/code/src_corelib_xml_qxmlstream.cpp 0
       
   295 
       
   296 
       
   297   QXmlStreamReader is a well-formed XML 1.0 parser that does \e not
       
   298   include external parsed entities. As long as no error occurs, the
       
   299   application code can thus be assured that the data provided by the
       
   300   stream reader satisfies the W3C's criteria for well-formed XML. For
       
   301   example, you can be certain that all tags are indeed nested and
       
   302   closed properly, that references to internal entities have been
       
   303   replaced with the correct replacement text, and that attributes have
       
   304   been normalized or added according to the internal subset of the
       
   305   DTD.
       
   306 
       
   307   If an error occurs while parsing, atEnd() and hasError() return
       
   308   true, and error() returns the error that occurred. The functions
       
   309   errorString(), lineNumber(), columnNumber(), and characterOffset()
       
   310   are for constructing an appropriate error or warning message. To
       
   311   simplify application code, QXmlStreamReader contains a raiseError()
       
   312   mechanism that lets you raise custom errors that trigger the same
       
   313   error handling described.
       
   314 
       
   315   The \l{QXmlStream Bookmarks Example} illustrates how to use the
       
   316   recursive descent technique to read an XML bookmark file (XBEL) with
       
   317   a stream reader.
       
   318 
       
   319   \section1 Namespaces
       
   320 
       
   321   QXmlStream understands and resolves XML namespaces. E.g. in case of
       
   322   a StartElement, namespaceUri() returns the namespace the element is
       
   323   in, and name() returns the element's \e local name. The combination
       
   324   of namespaceUri and name uniquely identifies an element. If a
       
   325   namespace prefix was not declared in the XML entities parsed by the
       
   326   reader, the namespaceUri is empty.
       
   327 
       
   328   If you parse XML data that does not utilize namespaces according to
       
   329   the XML specification or doesn't use namespaces at all, you can use
       
   330   the element's qualifiedName() instead. A qualified name is the
       
   331   element's prefix() followed by colon followed by the element's local
       
   332   name() - exactly like the element appears in the raw XML data. Since
       
   333   the mapping namespaceUri to prefix is neither unique nor universal,
       
   334   qualifiedName() should be avoided for namespace-compliant XML data.
       
   335 
       
   336   In order to parse standalone documents that do use undeclared
       
   337   namespace prefixes, you can turn off namespace processing completely
       
   338   with the \l namespaceProcessing property.
       
   339 
       
   340   \section1 Incremental parsing
       
   341 
       
   342   QXmlStreamReader is an incremental parser. It can handle the case
       
   343   where the document can't be parsed all at once because it arrives in
       
   344   chunks (e.g. from multiple files, or over a network connection).
       
   345   When the reader runs out of data before the complete document has
       
   346   been parsed, it reports a PrematureEndOfDocumentError. When more
       
   347   data arrives, either because of a call to addData() or because more
       
   348   data is available through the network device(), the reader recovers
       
   349   from the PrematureEndOfDocumentError error and continues parsing the
       
   350   new data with the next call to readNext().
       
   351 
       
   352   For example, if your application reads data from the network using a
       
   353   \l{QNetworkAccessManager} {network access manager}, you would issue
       
   354   a \l{QNetworkRequest} {network request} to the manager and receive a
       
   355   \l{QNetworkReply} {network reply} in return. Since a QNetworkReply
       
   356   is a QIODevice, you connect its \l{QNetworkReply::readyRead()}
       
   357   {readyRead()} signal to a custom slot, e.g. \c{slotReadyRead()} in
       
   358   the code snippet shown in the discussion for QNetworkAccessManager.
       
   359   In this slot, you read all available data with
       
   360   \l{QNetworkReply::readAll()} {readAll()} and pass it to the XML
       
   361   stream reader using addData(). Then you call your custom parsing
       
   362   function that reads the XML events from the reader.
       
   363 
       
   364   \section1 Performance and memory consumption
       
   365 
       
   366   QXmlStreamReader is memory-conservative by design, since it doesn't
       
   367   store the entire XML document tree in memory, but only the current
       
   368   token at the time it is reported. In addition, QXmlStreamReader
       
   369   avoids the many small string allocations that it normally takes to
       
   370   map an XML document to a convenient and Qt-ish API. It does this by
       
   371   reporting all string data as QStringRef rather than real QString
       
   372   objects. QStringRef is a thin wrapper around QString substrings that
       
   373   provides a subset of the QString API without the memory allocation
       
   374   and reference-counting overhead. Calling
       
   375   \l{QStringRef::toString()}{toString()} on any of those objects
       
   376   returns an equivalent real QString object.
       
   377 
       
   378 */
       
   379 
       
   380 
       
   381 /*!
       
   382   Constructs a stream reader.
       
   383 
       
   384   \sa setDevice(), addData()
       
   385  */
       
   386 QXmlStreamReader::QXmlStreamReader()
       
   387     : d_ptr(new QXmlStreamReaderPrivate(this))
       
   388 {
       
   389 }
       
   390 
       
   391 /*!  Creates a new stream reader that reads from \a device.
       
   392 
       
   393 \sa setDevice(), clear()
       
   394  */
       
   395 QXmlStreamReader::QXmlStreamReader(QIODevice *device)
       
   396     : d_ptr(new QXmlStreamReaderPrivate(this))
       
   397 {
       
   398     setDevice(device);
       
   399 }
       
   400 
       
   401 /*!
       
   402   Creates a new stream reader that reads from \a data.
       
   403 
       
   404   \sa addData(), clear(), setDevice()
       
   405  */
       
   406 QXmlStreamReader::QXmlStreamReader(const QByteArray &data)
       
   407     : d_ptr(new QXmlStreamReaderPrivate(this))
       
   408 {
       
   409     Q_D(QXmlStreamReader);
       
   410     d->dataBuffer = data;
       
   411 }
       
   412 
       
   413 /*!
       
   414   Creates a new stream reader that reads from \a data.
       
   415 
       
   416   \sa addData(), clear(), setDevice()
       
   417  */
       
   418 QXmlStreamReader::QXmlStreamReader(const QString &data)
       
   419     : d_ptr(new QXmlStreamReaderPrivate(this))
       
   420 {
       
   421     Q_D(QXmlStreamReader);
       
   422 #ifdef QT_NO_TEXTCODEC
       
   423     d->dataBuffer = data.toLatin1();
       
   424 #else
       
   425     d->dataBuffer = d->codec->fromUnicode(data);
       
   426     d->decoder = d->codec->makeDecoder();
       
   427 #endif
       
   428     d->lockEncoding = true;
       
   429 
       
   430 }
       
   431 
       
   432 /*!
       
   433   Creates a new stream reader that reads from \a data.
       
   434 
       
   435   \sa addData(), clear(), setDevice()
       
   436  */
       
   437 QXmlStreamReader::QXmlStreamReader(const char *data)
       
   438     : d_ptr(new QXmlStreamReaderPrivate(this))
       
   439 {
       
   440     Q_D(QXmlStreamReader);
       
   441     d->dataBuffer = QByteArray(data);
       
   442 }
       
   443 
       
   444 /*!
       
   445   Destructs the reader.
       
   446  */
       
   447 QXmlStreamReader::~QXmlStreamReader()
       
   448 {
       
   449     Q_D(QXmlStreamReader);
       
   450     if (d->deleteDevice)
       
   451         delete d->device;
       
   452 }
       
   453 
       
   454 /*! \fn bool QXmlStreamReader::hasError() const
       
   455     Returns \c true if an error has occurred, otherwise \c false.
       
   456 
       
   457     \sa errorString(), error()
       
   458  */
       
   459 
       
   460 /*!
       
   461     Sets the current device to \a device. Setting the device resets
       
   462     the stream to its initial state.
       
   463 
       
   464     \sa device(), clear()
       
   465 */
       
   466 void QXmlStreamReader::setDevice(QIODevice *device)
       
   467 {
       
   468     Q_D(QXmlStreamReader);
       
   469     if (d->deleteDevice) {
       
   470         delete d->device;
       
   471         d->deleteDevice = false;
       
   472     }
       
   473     d->device = device;
       
   474     d->init();
       
   475 
       
   476 }
       
   477 
       
   478 /*!
       
   479     Returns the current device associated with the QXmlStreamReader,
       
   480     or 0 if no device has been assigned.
       
   481 
       
   482     \sa setDevice()
       
   483 */
       
   484 QIODevice *QXmlStreamReader::device() const
       
   485 {
       
   486     Q_D(const QXmlStreamReader);
       
   487     return d->device;
       
   488 }
       
   489 
       
   490 
       
   491 /*!
       
   492   Adds more \a data for the reader to read. This function does
       
   493   nothing if the reader has a device().
       
   494 
       
   495   \sa readNext(), clear()
       
   496  */
       
   497 void QXmlStreamReader::addData(const QByteArray &data)
       
   498 {
       
   499     Q_D(QXmlStreamReader);
       
   500     if (d->device) {
       
   501         qWarning("QXmlStreamReader: addData() with device()");
       
   502         return;
       
   503     }
       
   504     d->dataBuffer += data;
       
   505 }
       
   506 
       
   507 /*!
       
   508   Adds more \a data for the reader to read. This function does
       
   509   nothing if the reader has a device().
       
   510 
       
   511   \sa readNext(), clear()
       
   512  */
       
   513 void QXmlStreamReader::addData(const QString &data)
       
   514 {
       
   515     Q_D(QXmlStreamReader);
       
   516     d->lockEncoding = true;
       
   517 #ifdef QT_NO_TEXTCODEC
       
   518     addData(data.toLatin1());
       
   519 #else
       
   520     addData(d->codec->fromUnicode(data));
       
   521 #endif
       
   522 }
       
   523 
       
   524 /*!
       
   525   Adds more \a data for the reader to read. This function does
       
   526   nothing if the reader has a device().
       
   527 
       
   528   \sa readNext(), clear()
       
   529  */
       
   530 void QXmlStreamReader::addData(const char *data)
       
   531 {
       
   532     addData(QByteArray(data));
       
   533 }
       
   534 
       
   535 /*!
       
   536     Removes any device() or data from the reader and resets its
       
   537     internal state to the initial state.
       
   538 
       
   539     \sa addData()
       
   540  */
       
   541 void QXmlStreamReader::clear()
       
   542 {
       
   543     Q_D(QXmlStreamReader);
       
   544     d->init();
       
   545     if (d->device) {
       
   546         if (d->deleteDevice)
       
   547             delete d->device;
       
   548         d->device = 0;
       
   549     }
       
   550 }
       
   551 
       
   552 /*!
       
   553     Returns true if the reader has read until the end of the XML
       
   554     document, or if an error() has occurred and reading has been
       
   555     aborted. Otherwise, it returns false.
       
   556 
       
   557     When atEnd() and hasError() return true and error() returns
       
   558     PrematureEndOfDocumentError, it means the XML has been well-formed
       
   559     so far, but a complete XML document has not been parsed. The next
       
   560     chunk of XML can be added with addData(), if the XML is being read
       
   561     from a QByteArray, or by waiting for more data to arrive if the
       
   562     XML is being read from a QIODevice. Either way, atEnd() will
       
   563     return false once more adata is available.
       
   564 
       
   565     \sa hasError(), error(), device(), QIODevice::atEnd()
       
   566  */
       
   567 bool QXmlStreamReader::atEnd() const
       
   568 {
       
   569     Q_D(const QXmlStreamReader);
       
   570     if (d->atEnd
       
   571         && ((d->type == QXmlStreamReader::Invalid && d->error == PrematureEndOfDocumentError)
       
   572             || (d->type == QXmlStreamReader::EndDocument))) {
       
   573         if (d->device)
       
   574             return d->device->atEnd();
       
   575         else
       
   576             return !d->dataBuffer.size();
       
   577     }
       
   578     return (d->atEnd || d->type == QXmlStreamReader::Invalid);
       
   579 }
       
   580 
       
   581 
       
   582 /*!
       
   583   Reads the next token and returns its type.
       
   584 
       
   585   With one exception, once an error() is reported by readNext(),
       
   586   further reading of the XML stream is not possible. Then atEnd()
       
   587   returns true, hasError() returns true, and this function returns
       
   588   QXmlStreamReader::Invalid.
       
   589 
       
   590   The exception is when error() returns PrematureEndOfDocumentError.
       
   591   This error is reported when the end of an otherwise well-formed
       
   592   chunk of XML is reached, but the chunk doesn't represent a complete
       
   593   XML document.  In that case, parsing \e can be resumed by calling
       
   594   addData() to add the next chunk of XML, when the stream is being
       
   595   read from a QByteArray, or by waiting for more data to arrive when
       
   596   the stream is being read from a device().
       
   597 
       
   598   \sa tokenType(), tokenString()
       
   599  */
       
   600 QXmlStreamReader::TokenType QXmlStreamReader::readNext()
       
   601 {
       
   602     Q_D(QXmlStreamReader);
       
   603     if (d->type != Invalid) {
       
   604         if (!d->hasCheckedStartDocument)
       
   605             if (!d->checkStartDocument())
       
   606                 return d->type; // synthetic StartDocument or error
       
   607         d->parse();
       
   608         if (d->atEnd && d->type != EndDocument && d->type != Invalid)
       
   609             d->raiseError(PrematureEndOfDocumentError);
       
   610         else if (!d->atEnd && d->type == EndDocument)
       
   611             d->raiseWellFormedError(QXmlStream::tr("Extra content at end of document."));
       
   612     } else if (d->error == PrematureEndOfDocumentError) {
       
   613         // resume error
       
   614         d->type = NoToken;
       
   615         d->atEnd = false;
       
   616         d->token = -1;
       
   617         return readNext();
       
   618     }
       
   619     return d->type;
       
   620 }
       
   621 
       
   622 
       
   623 /*!
       
   624   Returns the type of the current token.
       
   625 
       
   626   The current token can also be queried with the convenience functions
       
   627   isStartDocument(), isEndDocument(), isStartElement(),
       
   628   isEndElement(), isCharacters(), isComment(), isDTD(),
       
   629   isEntityReference(), and isProcessingInstruction().
       
   630 
       
   631   \sa tokenString()
       
   632  */
       
   633 QXmlStreamReader::TokenType QXmlStreamReader::tokenType() const
       
   634 {
       
   635     Q_D(const QXmlStreamReader);
       
   636     return d->type;
       
   637 }
       
   638 
       
   639 /*!
       
   640   Reads until the next start element within the current element. Returns true
       
   641   when a start element was reached. When the end element was reached, or when
       
   642   an error occurred, false is returned.
       
   643 
       
   644   The current element is the element matching the most recently parsed start
       
   645   element of which a matching end element has not yet been reached. When the
       
   646   parser has reached the end element, the current element becomes the parent
       
   647   element.
       
   648 
       
   649   This is a convenience function for when you're only concerned with parsing
       
   650   XML elements. The \l{QXmlStream Bookmarks Example} makes extensive use of
       
   651   this function.
       
   652 
       
   653   \since 4.6
       
   654   \sa readNext()
       
   655  */
       
   656 bool QXmlStreamReader::readNextStartElement()
       
   657 {
       
   658     while (readNext() != Invalid) {
       
   659         if (isEndElement())
       
   660             return false;
       
   661         else if (isStartElement())
       
   662             return true;
       
   663     }
       
   664     return false;
       
   665 }
       
   666 
       
   667 /*!
       
   668   Reads until the end of the current element, skipping any child nodes.
       
   669   This function is useful for skipping unknown elements.
       
   670 
       
   671   The current element is the element matching the most recently parsed start
       
   672   element of which a matching end element has not yet been reached. When the
       
   673   parser has reached the end element, the current element becomes the parent
       
   674   element.
       
   675 
       
   676   \since 4.6
       
   677  */
       
   678 void QXmlStreamReader::skipCurrentElement()
       
   679 {
       
   680     int depth = 1;
       
   681     while (depth && readNext() != Invalid) {
       
   682         if (isEndElement())
       
   683             --depth;
       
   684         else if (isStartElement())
       
   685             ++depth;
       
   686     }
       
   687 }
       
   688 
       
   689 /*
       
   690  * Use the following Perl script to generate the error string index list:
       
   691 ===== PERL SCRIPT ====
       
   692 print "static const char QXmlStreamReader_tokenTypeString_string[] =\n";
       
   693 $counter = 0;
       
   694 $i = 0;
       
   695 while (<STDIN>) {
       
   696     chomp;
       
   697     print "    \"$_\\0\"\n";
       
   698     $sizes[$i++] = $counter;
       
   699     $counter += length 1 + $_;
       
   700 }
       
   701 print "    \"\\0\";\n\nstatic const short QXmlStreamReader_tokenTypeString_indices[] = {\n    ";
       
   702 for ($j = 0; $j < $i; ++$j) {
       
   703     printf "$sizes[$j], ";
       
   704 }
       
   705 print "0\n};\n";
       
   706 ===== PERL SCRIPT ====
       
   707 
       
   708  * The input data is as follows (copied from qxmlstream.h):
       
   709 NoToken
       
   710 Invalid
       
   711 StartDocument
       
   712 EndDocument
       
   713 StartElement
       
   714 EndElement
       
   715 Characters
       
   716 Comment
       
   717 DTD
       
   718 EntityReference
       
   719 ProcessingInstruction
       
   720 */
       
   721 static const char QXmlStreamReader_tokenTypeString_string[] =
       
   722     "NoToken\0"
       
   723     "Invalid\0"
       
   724     "StartDocument\0"
       
   725     "EndDocument\0"
       
   726     "StartElement\0"
       
   727     "EndElement\0"
       
   728     "Characters\0"
       
   729     "Comment\0"
       
   730     "DTD\0"
       
   731     "EntityReference\0"
       
   732     "ProcessingInstruction\0";
       
   733 
       
   734 static const short QXmlStreamReader_tokenTypeString_indices[] = {
       
   735     0, 8, 16, 30, 42, 55, 66, 77, 85, 89, 105, 0
       
   736 };
       
   737 
       
   738 
       
   739 /*!
       
   740     \property  QXmlStreamReader::namespaceProcessing
       
   741     the namespace-processing flag of the stream reader
       
   742 
       
   743     This property controls whether or not the stream reader processes
       
   744     namespaces. If enabled, the reader processes namespaces, otherwise
       
   745     it does not.
       
   746 
       
   747     By default, namespace-processing is enabled.
       
   748 */
       
   749 
       
   750 
       
   751 void QXmlStreamReader::setNamespaceProcessing(bool enable)
       
   752 {
       
   753     Q_D(QXmlStreamReader);
       
   754     d->namespaceProcessing = enable;
       
   755 }
       
   756 
       
   757 bool QXmlStreamReader::namespaceProcessing() const
       
   758 {
       
   759     Q_D(const QXmlStreamReader);
       
   760     return d->namespaceProcessing;
       
   761 }
       
   762 
       
   763 /*! Returns the reader's current token as string.
       
   764 
       
   765 \sa tokenType()
       
   766 */
       
   767 QString QXmlStreamReader::tokenString() const
       
   768 {
       
   769     Q_D(const QXmlStreamReader);
       
   770     return QLatin1String(QXmlStreamReader_tokenTypeString_string +
       
   771                          QXmlStreamReader_tokenTypeString_indices[d->type]);
       
   772 }
       
   773 
       
   774 #endif // QT_NO_XMLSTREAMREADER
       
   775 
       
   776 QXmlStreamPrivateTagStack::QXmlStreamPrivateTagStack()
       
   777 {
       
   778     tagStack.reserve(16);
       
   779     tagStackStringStorage.reserve(32);
       
   780     tagStackStringStorageSize = 0;
       
   781     NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
       
   782     namespaceDeclaration.prefix = addToStringStorage(QLatin1String("xml"));
       
   783     namespaceDeclaration.namespaceUri = addToStringStorage(QLatin1String("http://www.w3.org/XML/1998/namespace"));
       
   784 }
       
   785 
       
   786 #ifndef QT_NO_XMLSTREAMREADER
       
   787 
       
   788 QXmlStreamReaderPrivate::QXmlStreamReaderPrivate(QXmlStreamReader *q)
       
   789     :q_ptr(q)
       
   790 {
       
   791     device = 0;
       
   792     deleteDevice = false;
       
   793 #ifndef QT_NO_TEXTCODEC
       
   794     decoder = 0;
       
   795 #endif
       
   796     stack_size = 64;
       
   797     sym_stack = 0;
       
   798     state_stack = 0;
       
   799     reallocateStack();
       
   800     entityResolver = 0;
       
   801     init();
       
   802     entityHash.insert(QLatin1String("lt"), Entity::createLiteral(QLatin1String("<")));
       
   803     entityHash.insert(QLatin1String("gt"), Entity::createLiteral(QLatin1String(">")));
       
   804     entityHash.insert(QLatin1String("amp"), Entity::createLiteral(QLatin1String("&")));
       
   805     entityHash.insert(QLatin1String("apos"), Entity::createLiteral(QLatin1String("'")));
       
   806     entityHash.insert(QLatin1String("quot"), Entity::createLiteral(QLatin1String("\"")));
       
   807 }
       
   808 
       
   809 void QXmlStreamReaderPrivate::init()
       
   810 {
       
   811     tos = 0;
       
   812     scanDtd = false;
       
   813     token = -1;
       
   814     token_char = 0;
       
   815     isEmptyElement = false;
       
   816     isWhitespace = true;
       
   817     isCDATA = false;
       
   818     standalone = false;
       
   819     tos = 0;
       
   820     resumeReduction = 0;
       
   821     state_stack[tos++] = 0;
       
   822     state_stack[tos] = 0;
       
   823     putStack.clear();
       
   824     putStack.reserve(32);
       
   825     textBuffer.clear();
       
   826     textBuffer.reserve(256);
       
   827     tagStack.clear();
       
   828     tagsDone = false;
       
   829     attributes.clear();
       
   830     attributes.reserve(16);
       
   831     lineNumber = lastLineStart = characterOffset = 0;
       
   832     readBufferPos = 0;
       
   833     nbytesread = 0;
       
   834 #ifndef QT_NO_TEXTCODEC
       
   835     codec = QTextCodec::codecForMib(106); // utf8
       
   836     delete decoder;
       
   837     decoder = 0;
       
   838 #endif
       
   839     attributeStack.clear();
       
   840     attributeStack.reserve(16);
       
   841     entityParser = 0;
       
   842     hasCheckedStartDocument = false;
       
   843     normalizeLiterals = false;
       
   844     hasSeenTag = false;
       
   845     atEnd = false;
       
   846     inParseEntity = false;
       
   847     referenceToUnparsedEntityDetected = false;
       
   848     referenceToParameterEntityDetected = false;
       
   849     hasExternalDtdSubset = false;
       
   850     lockEncoding = false;
       
   851     namespaceProcessing = true;
       
   852     rawReadBuffer.clear();
       
   853     dataBuffer.clear();
       
   854     readBuffer.clear();
       
   855 
       
   856     type = QXmlStreamReader::NoToken;
       
   857     error = QXmlStreamReader::NoError;
       
   858 }
       
   859 
       
   860 /*
       
   861   Well-formed requires that we verify entity values. We do this with a
       
   862   standard parser.
       
   863  */
       
   864 void QXmlStreamReaderPrivate::parseEntity(const QString &value)
       
   865 {
       
   866     Q_Q(QXmlStreamReader);
       
   867 
       
   868     if (value.isEmpty())
       
   869         return;
       
   870 
       
   871 
       
   872     if (!entityParser)
       
   873         entityParser = new QXmlStreamReaderPrivate(q);
       
   874     else
       
   875         entityParser->init();
       
   876     entityParser->inParseEntity = true;
       
   877     entityParser->readBuffer = value;
       
   878     entityParser->injectToken(PARSE_ENTITY);
       
   879     while (!entityParser->atEnd && entityParser->type != QXmlStreamReader::Invalid)
       
   880         entityParser->parse();
       
   881     if (entityParser->type == QXmlStreamReader::Invalid || entityParser->tagStack.size())
       
   882         raiseWellFormedError(QXmlStream::tr("Invalid entity value."));
       
   883 
       
   884 }
       
   885 
       
   886 inline void QXmlStreamReaderPrivate::reallocateStack()
       
   887 {
       
   888     stack_size <<= 1;
       
   889     sym_stack = reinterpret_cast<Value*> (qRealloc(sym_stack, stack_size * sizeof(Value)));
       
   890     Q_CHECK_PTR(sym_stack);
       
   891     state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int)));
       
   892     Q_CHECK_PTR(sym_stack);
       
   893 }
       
   894 
       
   895 
       
   896 QXmlStreamReaderPrivate::~QXmlStreamReaderPrivate()
       
   897 {
       
   898 #ifndef QT_NO_TEXTCODEC
       
   899     delete decoder;
       
   900 #endif
       
   901     qFree(sym_stack);
       
   902     qFree(state_stack);
       
   903     delete entityParser;
       
   904 }
       
   905 
       
   906 
       
   907 inline uint QXmlStreamReaderPrivate::filterCarriageReturn()
       
   908 {
       
   909     uint peekc = peekChar();
       
   910     if (peekc == '\n') {
       
   911         if (putStack.size())
       
   912             putStack.pop();
       
   913         else
       
   914             ++readBufferPos;
       
   915         return peekc;
       
   916     }
       
   917     if (peekc == 0) {
       
   918         putChar('\r');
       
   919         return 0;
       
   920     }
       
   921     return '\n';
       
   922 }
       
   923 
       
   924 /*!
       
   925  \internal
       
   926  If the end of the file is encountered, 0 is returned.
       
   927  */
       
   928 inline uint QXmlStreamReaderPrivate::getChar()
       
   929 {
       
   930     uint c;
       
   931     if (putStack.size()) {
       
   932         c = atEnd ? 0 : putStack.pop();
       
   933     } else {
       
   934         if (readBufferPos < readBuffer.size())
       
   935             c = readBuffer.at(readBufferPos++).unicode();
       
   936         else
       
   937             c = getChar_helper();
       
   938     }
       
   939 
       
   940     return c;
       
   941 }
       
   942 
       
   943 inline uint QXmlStreamReaderPrivate::peekChar()
       
   944 {
       
   945     uint c;
       
   946     if (putStack.size()) {
       
   947         c = putStack.top();
       
   948     } else if (readBufferPos < readBuffer.size()) {
       
   949         c = readBuffer.at(readBufferPos).unicode();
       
   950     } else {
       
   951         if ((c = getChar_helper()))
       
   952             --readBufferPos;
       
   953     }
       
   954 
       
   955     return c;
       
   956 }
       
   957 
       
   958 /*!
       
   959   \internal
       
   960 
       
   961   Scans characters until \a str is encountered, and validates the characters
       
   962   as according to the Char[2] production and do the line-ending normalization.
       
   963   If any character is invalid, false is returned, otherwise true upon success.
       
   964 
       
   965   If \a tokenToInject is not less than zero, injectToken() is called with
       
   966   \a tokenToInject when \a str is found.
       
   967 
       
   968   If any error occurred, false is returned, otherwise true.
       
   969   */
       
   970 bool QXmlStreamReaderPrivate::scanUntil(const char *str, short tokenToInject)
       
   971 {
       
   972     int pos = textBuffer.size();
       
   973     int oldLineNumber = lineNumber;
       
   974 
       
   975     while (uint c = getChar()) {
       
   976         /* First, we do the validation & normalization. */
       
   977         switch (c) {
       
   978         case '\r':
       
   979             if ((c = filterCarriageReturn()) == 0)
       
   980                 break;
       
   981             // fall through
       
   982         case '\n':
       
   983             ++lineNumber;
       
   984             lastLineStart = characterOffset + readBufferPos;
       
   985             // fall through
       
   986         case '\t':
       
   987             textBuffer += QChar(c);
       
   988             continue;
       
   989         default:
       
   990             if(c < 0x20 || (c > 0xFFFD && c < 0x10000) || c > 0x10FFFF ) {
       
   991                 raiseWellFormedError(QXmlStream::tr("Invalid XML character."));
       
   992                 lineNumber = oldLineNumber;
       
   993                 return false;
       
   994             }
       
   995             textBuffer += QChar(c);
       
   996         }
       
   997 
       
   998 
       
   999         /* Second, attempt to lookup str. */
       
  1000         if (c == uint(*str)) {
       
  1001             if (!*(str + 1)) {
       
  1002                 if (tokenToInject >= 0)
       
  1003                     injectToken(tokenToInject);
       
  1004                 return true;
       
  1005             } else {
       
  1006                 if (scanString(str + 1, tokenToInject, false))
       
  1007                     return true;
       
  1008             }
       
  1009         }
       
  1010     }
       
  1011     putString(textBuffer, pos);
       
  1012     textBuffer.resize(pos);
       
  1013     lineNumber = oldLineNumber;
       
  1014     return false;
       
  1015 }
       
  1016 
       
  1017 bool QXmlStreamReaderPrivate::scanString(const char *str, short tokenToInject, bool requireSpace)
       
  1018 {
       
  1019     int n = 0;
       
  1020     while (str[n]) {
       
  1021         ushort c = getChar();
       
  1022         if (c != ushort(str[n])) {
       
  1023             if (c)
       
  1024                 putChar(c);
       
  1025             while (n--) {
       
  1026                 putChar(ushort(str[n]));
       
  1027             }
       
  1028             return false;
       
  1029         }
       
  1030         ++n;
       
  1031     }
       
  1032     for (int i = 0; i < n; ++i)
       
  1033         textBuffer += QChar(ushort(str[i]));
       
  1034     if (requireSpace) {
       
  1035         int s = fastScanSpace();
       
  1036         if (!s || atEnd) {
       
  1037             int pos = textBuffer.size() - n - s;
       
  1038             putString(textBuffer, pos);
       
  1039             textBuffer.resize(pos);
       
  1040             return false;
       
  1041         }
       
  1042     }
       
  1043     if (tokenToInject >= 0)
       
  1044         injectToken(tokenToInject);
       
  1045     return true;
       
  1046 }
       
  1047 
       
  1048 bool QXmlStreamReaderPrivate::scanAfterLangleBang()
       
  1049 {
       
  1050     switch (peekChar()) {
       
  1051     case '[':
       
  1052         return scanString(spell[CDATA_START], CDATA_START, false);
       
  1053     case 'D':
       
  1054         return scanString(spell[DOCTYPE], DOCTYPE);
       
  1055     case 'A':
       
  1056         return scanString(spell[ATTLIST], ATTLIST);
       
  1057     case 'N':
       
  1058         return scanString(spell[NOTATION], NOTATION);
       
  1059     case 'E':
       
  1060         if (scanString(spell[ELEMENT], ELEMENT))
       
  1061             return true;
       
  1062         return scanString(spell[ENTITY], ENTITY);
       
  1063 
       
  1064     default:
       
  1065         ;
       
  1066     };
       
  1067     return false;
       
  1068 }
       
  1069 
       
  1070 bool QXmlStreamReaderPrivate::scanPublicOrSystem()
       
  1071 {
       
  1072     switch (peekChar()) {
       
  1073     case 'S':
       
  1074         return scanString(spell[SYSTEM], SYSTEM);
       
  1075     case 'P':
       
  1076         return scanString(spell[PUBLIC], PUBLIC);
       
  1077     default:
       
  1078         ;
       
  1079     }
       
  1080     return false;
       
  1081 }
       
  1082 
       
  1083 bool QXmlStreamReaderPrivate::scanNData()
       
  1084 {
       
  1085     if (fastScanSpace()) {
       
  1086         if (scanString(spell[NDATA], NDATA))
       
  1087             return true;
       
  1088         putChar(' ');
       
  1089     }
       
  1090     return false;
       
  1091 }
       
  1092 
       
  1093 bool QXmlStreamReaderPrivate::scanAfterDefaultDecl()
       
  1094 {
       
  1095     switch (peekChar()) {
       
  1096     case 'R':
       
  1097         return scanString(spell[REQUIRED], REQUIRED, false);
       
  1098     case 'I':
       
  1099         return scanString(spell[IMPLIED], IMPLIED, false);
       
  1100     case 'F':
       
  1101         return scanString(spell[FIXED], FIXED, false);
       
  1102     default:
       
  1103         ;
       
  1104     }
       
  1105     return false;
       
  1106 }
       
  1107 
       
  1108 bool QXmlStreamReaderPrivate::scanAttType()
       
  1109 {
       
  1110     switch (peekChar()) {
       
  1111     case 'C':
       
  1112         return scanString(spell[CDATA], CDATA);
       
  1113     case 'I':
       
  1114         if (scanString(spell[ID], ID))
       
  1115             return true;
       
  1116         if (scanString(spell[IDREF], IDREF))
       
  1117             return true;
       
  1118         return scanString(spell[IDREFS], IDREFS);
       
  1119     case 'E':
       
  1120         if (scanString(spell[ENTITY], ENTITY))
       
  1121             return true;
       
  1122         return scanString(spell[ENTITIES], ENTITIES);
       
  1123     case 'N':
       
  1124         if (scanString(spell[NOTATION], NOTATION))
       
  1125             return true;
       
  1126         if (scanString(spell[NMTOKEN], NMTOKEN))
       
  1127             return true;
       
  1128         return scanString(spell[NMTOKENS], NMTOKENS);
       
  1129     default:
       
  1130         ;
       
  1131     }
       
  1132     return false;
       
  1133 }
       
  1134 
       
  1135 /*!
       
  1136  \internal
       
  1137 
       
  1138  Scan strings with quotes or apostrophes surround them. For instance,
       
  1139  attributes, the version and encoding field in the XML prolog and
       
  1140  entity declarations.
       
  1141 
       
  1142  If normalizeLiterals is set to true, the function also normalizes
       
  1143  whitespace. It is set to true when the first start tag is
       
  1144  encountered.
       
  1145 
       
  1146  */
       
  1147 inline int QXmlStreamReaderPrivate::fastScanLiteralContent()
       
  1148 {
       
  1149     int n = 0;
       
  1150     uint c;
       
  1151     while ((c = getChar())) {
       
  1152         switch (ushort(c)) {
       
  1153         case 0xfffe:
       
  1154         case 0xffff:
       
  1155         case 0:
       
  1156             /* The putChar() call is necessary so the parser re-gets
       
  1157              * the character from the input source, when raising an error. */
       
  1158             putChar(c);
       
  1159             return n;
       
  1160         case '\r':
       
  1161             if (filterCarriageReturn() == 0)
       
  1162                 return n;
       
  1163             // fall through
       
  1164         case '\n':
       
  1165             ++lineNumber;
       
  1166             lastLineStart = characterOffset + readBufferPos;
       
  1167             // fall through
       
  1168         case ' ':
       
  1169         case '\t':
       
  1170             if (normalizeLiterals)
       
  1171                 textBuffer += QLatin1Char(' ');
       
  1172             else
       
  1173                 textBuffer += QChar(c);
       
  1174             ++n;
       
  1175             break;
       
  1176         case '&':
       
  1177         case '<':
       
  1178         case '\"':
       
  1179         case '\'':
       
  1180             if (!(c & 0xff0000)) {
       
  1181                 putChar(c);
       
  1182                 return n;
       
  1183             }
       
  1184             // fall through
       
  1185         default:
       
  1186             textBuffer += QChar(c);
       
  1187             ++n;
       
  1188         }
       
  1189     }
       
  1190     return n;
       
  1191 }
       
  1192 
       
  1193 inline int QXmlStreamReaderPrivate::fastScanSpace()
       
  1194 {
       
  1195     int n = 0;
       
  1196     ushort c;
       
  1197     while ((c = getChar())) {
       
  1198         switch (c) {
       
  1199         case '\r':
       
  1200             if ((c = filterCarriageReturn()) == 0)
       
  1201                 return n;
       
  1202             // fall through
       
  1203         case '\n':
       
  1204             ++lineNumber;
       
  1205             lastLineStart = characterOffset + readBufferPos;
       
  1206             // fall through
       
  1207         case ' ':
       
  1208         case '\t':
       
  1209             textBuffer += QChar(c);
       
  1210             ++n;
       
  1211             break;
       
  1212         default:
       
  1213             putChar(c);
       
  1214             return n;
       
  1215         }
       
  1216     }
       
  1217     return n;
       
  1218 }
       
  1219 
       
  1220 /*!
       
  1221   \internal
       
  1222 
       
  1223   Used for text nodes essentially. That is, characters appearing
       
  1224   inside elements.
       
  1225  */
       
  1226 inline int QXmlStreamReaderPrivate::fastScanContentCharList()
       
  1227 {
       
  1228     int n = 0;
       
  1229     uint c;
       
  1230     while ((c = getChar())) {
       
  1231         switch (ushort(c)) {
       
  1232         case 0xfffe:
       
  1233         case 0xffff:
       
  1234         case 0:
       
  1235             putChar(c);
       
  1236             return n;
       
  1237         case ']': {
       
  1238             isWhitespace = false;
       
  1239             int pos = textBuffer.size();
       
  1240             textBuffer += QChar(ushort(c));
       
  1241             ++n;
       
  1242             while ((c = getChar()) == ']') {
       
  1243                 textBuffer += QChar(ushort(c));
       
  1244                 ++n;
       
  1245             }
       
  1246             if (c == 0) {
       
  1247                 putString(textBuffer, pos);
       
  1248                 textBuffer.resize(pos);
       
  1249             } else if (c == '>' && textBuffer.at(textBuffer.size()-2) == QLatin1Char(']')) {
       
  1250                 raiseWellFormedError(QXmlStream::tr("Sequence ']]>' not allowed in content."));
       
  1251             } else {
       
  1252                 putChar(c);
       
  1253                 break;
       
  1254             }
       
  1255             return n;
       
  1256         } break;
       
  1257         case '\r':
       
  1258             if ((c = filterCarriageReturn()) == 0)
       
  1259                 return n;
       
  1260             // fall through
       
  1261         case '\n':
       
  1262             ++lineNumber;
       
  1263             lastLineStart = characterOffset + readBufferPos;
       
  1264             // fall through
       
  1265         case ' ':
       
  1266         case '\t':
       
  1267             textBuffer += QChar(ushort(c));
       
  1268             ++n;
       
  1269             break;
       
  1270         case '&':
       
  1271         case '<':
       
  1272             if (!(c & 0xff0000)) {
       
  1273                 putChar(c);
       
  1274                 return n;
       
  1275             }
       
  1276             // fall through
       
  1277         default:
       
  1278             if (c < 0x20) {
       
  1279                 putChar(c);
       
  1280                 return n;
       
  1281             }
       
  1282             isWhitespace = false;
       
  1283             textBuffer += QChar(ushort(c));
       
  1284             ++n;
       
  1285         }
       
  1286     }
       
  1287     return n;
       
  1288 }
       
  1289 
       
  1290 inline int QXmlStreamReaderPrivate::fastScanName(int *prefix)
       
  1291 {
       
  1292     int n = 0;
       
  1293     ushort c;
       
  1294     while ((c = getChar())) {
       
  1295         switch (c) {
       
  1296         case '\n':
       
  1297         case ' ':
       
  1298         case '\t':
       
  1299         case '\r':
       
  1300         case '&':
       
  1301         case '#':
       
  1302         case '\'':
       
  1303         case '\"':
       
  1304         case '<':
       
  1305         case '>':
       
  1306         case '[':
       
  1307         case ']':
       
  1308         case '=':
       
  1309         case '%':
       
  1310         case '/':
       
  1311         case ';':
       
  1312         case '?':
       
  1313         case '!':
       
  1314         case '^':
       
  1315         case '|':
       
  1316         case ',':
       
  1317         case '(':
       
  1318         case ')':
       
  1319         case '+':
       
  1320         case '*':
       
  1321             putChar(c);
       
  1322             if (prefix && *prefix == n+1) {
       
  1323                 *prefix = 0;
       
  1324                 putChar(':');
       
  1325                 --n;
       
  1326             }
       
  1327             return n;
       
  1328         case ':':
       
  1329             if (prefix) {
       
  1330                 if (*prefix == 0) {
       
  1331                     *prefix = n+2;
       
  1332                 } else { // only one colon allowed according to the namespace spec.
       
  1333                     putChar(c);
       
  1334                     return n;
       
  1335                 }
       
  1336             } else {
       
  1337                 putChar(c);
       
  1338                 return n;
       
  1339             }
       
  1340             // fall through
       
  1341         default:
       
  1342             textBuffer += QChar(c);
       
  1343             ++n;
       
  1344         }
       
  1345     }
       
  1346 
       
  1347     if (prefix)
       
  1348         *prefix = 0;
       
  1349     int pos = textBuffer.size() - n;
       
  1350     putString(textBuffer, pos);
       
  1351     textBuffer.resize(pos);
       
  1352     return 0;
       
  1353 }
       
  1354 
       
  1355 enum NameChar { NameBeginning, NameNotBeginning, NotName };
       
  1356 
       
  1357 static const char Begi = static_cast<char>(NameBeginning);
       
  1358 static const char NtBg = static_cast<char>(NameNotBeginning);
       
  1359 static const char NotN = static_cast<char>(NotName);
       
  1360 
       
  1361 static const char nameCharTable[128] =
       
  1362 {
       
  1363 // 0x00
       
  1364     NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
       
  1365     NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
       
  1366 // 0x10
       
  1367     NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
       
  1368     NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
       
  1369 // 0x20 (0x2D is '-', 0x2E is '.')
       
  1370     NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
       
  1371     NotN, NotN, NotN, NotN, NotN, NtBg, NtBg, NotN,
       
  1372 // 0x30 (0x30..0x39 are '0'..'9', 0x3A is ':')
       
  1373     NtBg, NtBg, NtBg, NtBg, NtBg, NtBg, NtBg, NtBg,
       
  1374     NtBg, NtBg, Begi, NotN, NotN, NotN, NotN, NotN,
       
  1375 // 0x40 (0x41..0x5A are 'A'..'Z')
       
  1376     NotN, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
       
  1377     Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
       
  1378 // 0x50 (0x5F is '_')
       
  1379     Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
       
  1380     Begi, Begi, Begi, NotN, NotN, NotN, NotN, Begi,
       
  1381 // 0x60 (0x61..0x7A are 'a'..'z')
       
  1382     NotN, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
       
  1383     Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
       
  1384 // 0x70
       
  1385     Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
       
  1386     Begi, Begi, Begi, NotN, NotN, NotN, NotN, NotN
       
  1387 };
       
  1388 
       
  1389 static inline NameChar fastDetermineNameChar(QChar ch)
       
  1390 {
       
  1391     ushort uc = ch.unicode();
       
  1392     if (!(uc & ~0x7f)) // uc < 128
       
  1393         return static_cast<NameChar>(nameCharTable[uc]);
       
  1394 
       
  1395     QChar::Category cat = ch.category();
       
  1396     // ### some these categories might be slightly wrong
       
  1397     if ((cat >= QChar::Letter_Uppercase && cat <= QChar::Letter_Other)
       
  1398         || cat == QChar::Number_Letter)
       
  1399         return NameBeginning;
       
  1400     if ((cat >= QChar::Number_DecimalDigit && cat <= QChar::Number_Other)
       
  1401                 || (cat >= QChar::Mark_NonSpacing && cat <= QChar::Mark_Enclosing))
       
  1402         return NameNotBeginning;
       
  1403     return NotName;
       
  1404 }
       
  1405 
       
  1406 inline int QXmlStreamReaderPrivate::fastScanNMTOKEN()
       
  1407 {
       
  1408     int n = 0;
       
  1409     uint c;
       
  1410     while ((c = getChar())) {
       
  1411         if (fastDetermineNameChar(c) == NotName) {
       
  1412             putChar(c);
       
  1413             return n;
       
  1414         } else {
       
  1415             ++n;
       
  1416             textBuffer += QChar(c);
       
  1417         }
       
  1418     }
       
  1419 
       
  1420     int pos = textBuffer.size() - n;
       
  1421     putString(textBuffer, pos);
       
  1422     textBuffer.resize(pos);
       
  1423 
       
  1424     return n;
       
  1425 }
       
  1426 
       
  1427 void QXmlStreamReaderPrivate::putString(const QString &s, int from)
       
  1428 {
       
  1429     putStack.reserve(s.size());
       
  1430     for (int i = s.size()-1; i >= from; --i)
       
  1431         putStack.rawPush() = s.at(i).unicode();
       
  1432 }
       
  1433 
       
  1434 void QXmlStreamReaderPrivate::putStringLiteral(const QString &s)
       
  1435 {
       
  1436     putStack.reserve(s.size());
       
  1437     for (int i = s.size()-1; i >= 0; --i)
       
  1438         putStack.rawPush() = ((LETTER << 16) | s.at(i).unicode());
       
  1439 }
       
  1440 
       
  1441 void QXmlStreamReaderPrivate::putReplacement(const QString &s)
       
  1442 {
       
  1443     putStack.reserve(s.size());
       
  1444     for (int i = s.size()-1; i >= 0; --i) {
       
  1445         ushort c = s.at(i).unicode();
       
  1446         if (c == '\n' || c == '\r')
       
  1447             putStack.rawPush() = ((LETTER << 16) | c);
       
  1448         else
       
  1449             putStack.rawPush() = c;
       
  1450     }
       
  1451 }
       
  1452 void QXmlStreamReaderPrivate::putReplacementInAttributeValue(const QString &s)
       
  1453 {
       
  1454     putStack.reserve(s.size());
       
  1455     for (int i = s.size()-1; i >= 0; --i) {
       
  1456         ushort c = s.at(i).unicode();
       
  1457         if (c == '&' || c == ';')
       
  1458             putStack.rawPush() = c;
       
  1459         else if (c == '\n' || c == '\r')
       
  1460             putStack.rawPush() = ' ';
       
  1461         else
       
  1462             putStack.rawPush() = ((LETTER << 16) | c);
       
  1463     }
       
  1464 }
       
  1465 
       
  1466 ushort QXmlStreamReaderPrivate::getChar_helper()
       
  1467 {
       
  1468     const int BUFFER_SIZE = 8192;
       
  1469     characterOffset += readBufferPos;
       
  1470     readBufferPos = 0;
       
  1471     readBuffer.resize(0);
       
  1472 #ifndef QT_NO_TEXTCODEC
       
  1473     if (decoder)
       
  1474 #endif
       
  1475         nbytesread = 0;
       
  1476     if (device) {
       
  1477         rawReadBuffer.resize(BUFFER_SIZE);
       
  1478         int nbytesreadOrMinus1 = device->read(rawReadBuffer.data() + nbytesread, BUFFER_SIZE - nbytesread);
       
  1479         nbytesread += qMax(nbytesreadOrMinus1, 0);
       
  1480     } else {
       
  1481         if (nbytesread)
       
  1482             rawReadBuffer += dataBuffer;
       
  1483         else
       
  1484             rawReadBuffer = dataBuffer;
       
  1485         nbytesread = rawReadBuffer.size();
       
  1486         dataBuffer.clear();
       
  1487     }
       
  1488     if (!nbytesread) {
       
  1489         atEnd = true;
       
  1490         return 0;
       
  1491     }
       
  1492 
       
  1493 #ifndef QT_NO_TEXTCODEC
       
  1494     if (!decoder) {
       
  1495         if (nbytesread < 4) { // the 4 is to cover 0xef 0xbb 0xbf plus
       
  1496                               // one extra for the utf8 codec
       
  1497             atEnd = true;
       
  1498             return 0;
       
  1499         }
       
  1500         int mib = 106; // UTF-8
       
  1501 
       
  1502         // look for byte order mark
       
  1503         uchar ch1 = rawReadBuffer.at(0);
       
  1504         uchar ch2 = rawReadBuffer.at(1);
       
  1505         uchar ch3 = rawReadBuffer.at(2);
       
  1506         uchar ch4 = rawReadBuffer.at(3);
       
  1507 
       
  1508         if ((ch1 == 0 && ch2 == 0 && ch3 == 0xfe && ch4 == 0xff) ||
       
  1509             (ch1 == 0xff && ch2 == 0xfe && ch3 == 0 && ch4 == 0))
       
  1510             mib = 1017; // UTF-32 with byte order mark
       
  1511         else if (ch1 == 0x3c && ch2 == 0x00 && ch3 == 0x00 && ch4 == 0x00)
       
  1512             mib = 1019; // UTF-32LE
       
  1513         else if (ch1 == 0x00 && ch2 == 0x00 && ch3 == 0x00 && ch4 == 0x3c)
       
  1514             mib = 1018; // UTF-32BE
       
  1515         else if ((ch1 == 0xfe && ch2 == 0xff) || (ch1 == 0xff && ch2 == 0xfe))
       
  1516             mib = 1015; // UTF-16 with byte order mark
       
  1517         else if (ch1 == 0x3c && ch2 == 0x00)
       
  1518             mib = 1014; // UTF-16LE
       
  1519         else if (ch1 == 0x00 && ch2 == 0x3c)
       
  1520             mib = 1013; // UTF-16BE
       
  1521         codec = QTextCodec::codecForMib(mib);
       
  1522         Q_ASSERT(codec);
       
  1523         decoder = codec->makeDecoder();
       
  1524     }
       
  1525 
       
  1526     decoder->toUnicode(&readBuffer, rawReadBuffer.data(), nbytesread);
       
  1527 
       
  1528     if(lockEncoding && decoder->hasFailure()) {
       
  1529         raiseWellFormedError(QXmlStream::tr("Encountered incorrectly encoded content."));
       
  1530         readBuffer.clear();
       
  1531         return 0;
       
  1532     }
       
  1533 #else
       
  1534     readBuffer = QString::fromLatin1(rawReadBuffer.data(), nbytesread);
       
  1535 #endif // QT_NO_TEXTCODEC
       
  1536 
       
  1537     readBuffer.reserve(1); // keep capacity when calling resize() next time
       
  1538 
       
  1539     if (readBufferPos < readBuffer.size()) {
       
  1540         ushort c = readBuffer.at(readBufferPos++).unicode();
       
  1541         return c;
       
  1542     }
       
  1543 
       
  1544     atEnd = true;
       
  1545     return 0;
       
  1546 }
       
  1547 
       
  1548 QStringRef QXmlStreamReaderPrivate::namespaceForPrefix(const QStringRef &prefix)
       
  1549 {
       
  1550      for (int j = namespaceDeclarations.size() - 1; j >= 0; --j) {
       
  1551          const NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(j);
       
  1552          if (namespaceDeclaration.prefix == prefix) {
       
  1553              return namespaceDeclaration.namespaceUri;
       
  1554          }
       
  1555      }
       
  1556 
       
  1557 #if 1
       
  1558      if (namespaceProcessing && !prefix.isEmpty())
       
  1559          raiseWellFormedError(QXmlStream::tr("Namespace prefix '%1' not declared").arg(prefix.toString()));
       
  1560 #endif
       
  1561 
       
  1562      return QStringRef();
       
  1563 }
       
  1564 
       
  1565 /*
       
  1566   uses namespaceForPrefix and builds the attribute vector
       
  1567  */
       
  1568 void QXmlStreamReaderPrivate::resolveTag()
       
  1569 {
       
  1570     int n = attributeStack.size();
       
  1571 
       
  1572     if (namespaceProcessing) {
       
  1573         for (int a = 0; a < dtdAttributes.size(); ++a) {
       
  1574             DtdAttribute &dtdAttribute = dtdAttributes[a];
       
  1575             if (!dtdAttribute.isNamespaceAttribute
       
  1576                 || dtdAttribute.defaultValue.isNull()
       
  1577                 || dtdAttribute.tagName != qualifiedName
       
  1578                 || dtdAttribute.attributeQualifiedName.isNull())
       
  1579                 continue;
       
  1580             int i = 0;
       
  1581             while (i < n && symName(attributeStack[i].key) != dtdAttribute.attributeQualifiedName)
       
  1582                 ++i;
       
  1583             if (i != n)
       
  1584                 continue;
       
  1585             if (dtdAttribute.attributePrefix.isEmpty() && dtdAttribute.attributeName == QLatin1String("xmlns")) {
       
  1586                 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
       
  1587                 namespaceDeclaration.prefix.clear();
       
  1588 
       
  1589                 const QStringRef ns(dtdAttribute.defaultValue);
       
  1590                 if(ns == QLatin1String("http://www.w3.org/2000/xmlns/") ||
       
  1591                    ns == QLatin1String("http://www.w3.org/XML/1998/namespace"))
       
  1592                     raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
       
  1593                 else
       
  1594                     namespaceDeclaration.namespaceUri = ns;
       
  1595             } else if (dtdAttribute.attributePrefix == QLatin1String("xmlns")) {
       
  1596                 NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
       
  1597                 QStringRef namespacePrefix = dtdAttribute.attributeName;
       
  1598                 QStringRef namespaceUri = dtdAttribute.defaultValue;
       
  1599                 if (((namespacePrefix == QLatin1String("xml"))
       
  1600                      ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace")))
       
  1601                     || namespaceUri == QLatin1String("http://www.w3.org/2000/xmlns/")
       
  1602                     || namespaceUri.isEmpty()
       
  1603                     || namespacePrefix == QLatin1String("xmlns"))
       
  1604                     raiseWellFormedError(QXmlStream::tr("Illegal namespace declaration."));
       
  1605 
       
  1606                 namespaceDeclaration.prefix = namespacePrefix;
       
  1607                 namespaceDeclaration.namespaceUri = namespaceUri;
       
  1608             }
       
  1609         }
       
  1610     }
       
  1611 
       
  1612     tagStack.top().namespaceDeclaration.namespaceUri = namespaceUri = namespaceForPrefix(prefix);
       
  1613 
       
  1614     attributes.resize(n);
       
  1615 
       
  1616     for (int i = 0; i < n; ++i) {
       
  1617         QXmlStreamAttribute &attribute = attributes[i];
       
  1618         Attribute &attrib = attributeStack[i];
       
  1619         QStringRef prefix(symPrefix(attrib.key));
       
  1620         QStringRef name(symString(attrib.key));
       
  1621         QStringRef qualifiedName(symName(attrib.key));
       
  1622         QStringRef value(symString(attrib.value));
       
  1623 
       
  1624         attribute.m_name = QXmlStreamStringRef(name);
       
  1625         attribute.m_qualifiedName = QXmlStreamStringRef(qualifiedName);
       
  1626         attribute.m_value = QXmlStreamStringRef(value);
       
  1627 
       
  1628         if (!prefix.isEmpty()) {
       
  1629             QStringRef attributeNamespaceUri = namespaceForPrefix(prefix);
       
  1630             attribute.m_namespaceUri = QXmlStreamStringRef(attributeNamespaceUri);
       
  1631         }
       
  1632 
       
  1633         for (int j = 0; j < i; ++j) {
       
  1634             if (attributes[j].name() == attribute.name()
       
  1635                 && attributes[j].namespaceUri() == attribute.namespaceUri()
       
  1636                 && (namespaceProcessing || attributes[j].qualifiedName() == attribute.qualifiedName()))
       
  1637                 raiseWellFormedError(QXmlStream::tr("Attribute redefined."));
       
  1638         }
       
  1639     }
       
  1640 
       
  1641     for (int a = 0; a < dtdAttributes.size(); ++a) {
       
  1642         DtdAttribute &dtdAttribute = dtdAttributes[a];
       
  1643         if (dtdAttribute.isNamespaceAttribute
       
  1644             || dtdAttribute.defaultValue.isNull()
       
  1645             || dtdAttribute.tagName != qualifiedName
       
  1646             || dtdAttribute.attributeQualifiedName.isNull())
       
  1647             continue;
       
  1648         int i = 0;
       
  1649         while (i < n && symName(attributeStack[i].key) != dtdAttribute.attributeQualifiedName)
       
  1650             ++i;
       
  1651         if (i != n)
       
  1652             continue;
       
  1653 
       
  1654 
       
  1655 
       
  1656         QXmlStreamAttribute attribute;
       
  1657         attribute.m_name = QXmlStreamStringRef(dtdAttribute.attributeName);
       
  1658         attribute.m_qualifiedName = QXmlStreamStringRef(dtdAttribute.attributeQualifiedName);
       
  1659         attribute.m_value = QXmlStreamStringRef(dtdAttribute.defaultValue);
       
  1660 
       
  1661         if (!dtdAttribute.attributePrefix.isEmpty()) {
       
  1662             QStringRef attributeNamespaceUri = namespaceForPrefix(dtdAttribute.attributePrefix);
       
  1663             attribute.m_namespaceUri = QXmlStreamStringRef(attributeNamespaceUri);
       
  1664         }
       
  1665         attribute.m_isDefault = true;
       
  1666         attributes.append(attribute);
       
  1667     }
       
  1668 
       
  1669     attributeStack.clear();
       
  1670 }
       
  1671 
       
  1672 void QXmlStreamReaderPrivate::resolvePublicNamespaces()
       
  1673 {
       
  1674     const Tag &tag = tagStack.top();
       
  1675     int n = namespaceDeclarations.size() - tag.namespaceDeclarationsSize;
       
  1676     publicNamespaceDeclarations.resize(n);
       
  1677     for (int i = 0; i < n; ++i) {
       
  1678         const NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(tag.namespaceDeclarationsSize + i);
       
  1679         QXmlStreamNamespaceDeclaration &publicNamespaceDeclaration = publicNamespaceDeclarations[i];
       
  1680         publicNamespaceDeclaration.m_prefix = QXmlStreamStringRef(namespaceDeclaration.prefix);
       
  1681         publicNamespaceDeclaration.m_namespaceUri = QXmlStreamStringRef(namespaceDeclaration.namespaceUri);
       
  1682     }
       
  1683 }
       
  1684 
       
  1685 void QXmlStreamReaderPrivate::resolveDtd()
       
  1686 {
       
  1687     publicNotationDeclarations.resize(notationDeclarations.size());
       
  1688     for (int i = 0; i < notationDeclarations.size(); ++i) {
       
  1689         const QXmlStreamReaderPrivate::NotationDeclaration &notationDeclaration = notationDeclarations.at(i);
       
  1690         QXmlStreamNotationDeclaration &publicNotationDeclaration = publicNotationDeclarations[i];
       
  1691         publicNotationDeclaration.m_name = QXmlStreamStringRef(notationDeclaration.name);
       
  1692         publicNotationDeclaration.m_systemId = QXmlStreamStringRef(notationDeclaration.systemId);
       
  1693         publicNotationDeclaration.m_publicId = QXmlStreamStringRef(notationDeclaration.publicId);
       
  1694 
       
  1695     }
       
  1696     notationDeclarations.clear();
       
  1697     publicEntityDeclarations.resize(entityDeclarations.size());
       
  1698     for (int i = 0; i < entityDeclarations.size(); ++i) {
       
  1699         const QXmlStreamReaderPrivate::EntityDeclaration &entityDeclaration = entityDeclarations.at(i);
       
  1700         QXmlStreamEntityDeclaration &publicEntityDeclaration = publicEntityDeclarations[i];
       
  1701         publicEntityDeclaration.m_name = QXmlStreamStringRef(entityDeclaration.name);
       
  1702         publicEntityDeclaration.m_notationName = QXmlStreamStringRef(entityDeclaration.notationName);
       
  1703         publicEntityDeclaration.m_systemId = QXmlStreamStringRef(entityDeclaration.systemId);
       
  1704         publicEntityDeclaration.m_publicId = QXmlStreamStringRef(entityDeclaration.publicId);
       
  1705         publicEntityDeclaration.m_value = QXmlStreamStringRef(entityDeclaration.value);
       
  1706     }
       
  1707     entityDeclarations.clear();
       
  1708     parameterEntityHash.clear();
       
  1709 }
       
  1710 
       
  1711 uint QXmlStreamReaderPrivate::resolveCharRef(int symbolIndex)
       
  1712 {
       
  1713     bool ok = true;
       
  1714     uint s;
       
  1715     // ### add toXShort to QStringRef?
       
  1716     if (sym(symbolIndex).c == 'x')
       
  1717         s = symString(symbolIndex, 1).toString().toUInt(&ok, 16);
       
  1718     else
       
  1719         s = symString(symbolIndex).toString().toUInt(&ok, 10);
       
  1720 
       
  1721     ok &= (s == 0x9 || s == 0xa || s == 0xd || (s >= 0x20 && s <= 0xd7ff)
       
  1722            || (s >= 0xe000 && s <= 0xfffd) || (s >= 0x10000 && s <= 0x10ffff));
       
  1723 
       
  1724     return ok ? s : 0;
       
  1725 }
       
  1726 
       
  1727 
       
  1728 void QXmlStreamReaderPrivate::checkPublicLiteral(const QStringRef &publicId)
       
  1729 {
       
  1730 //#x20 | #xD | #xA | [a-zA-Z0-9] | [-'()+,./:=?;!*#@$_%]
       
  1731 
       
  1732     const ushort *data = reinterpret_cast<const ushort *>(publicId.constData());
       
  1733     uchar c = 0;
       
  1734     int i;
       
  1735     for (i = publicId.size() - 1; i >= 0; --i) {
       
  1736         if (data[i] < 256)
       
  1737             switch ((c = data[i])) {
       
  1738             case ' ': case '\n': case '\r': case '-': case '(': case ')':
       
  1739             case '+': case ',': case '.': case '/': case ':': case '=':
       
  1740             case '?': case ';': case '!': case '*': case '#': case '@':
       
  1741             case '$': case '_': case '%': case '\'': case '\"':
       
  1742                 continue;
       
  1743             default:
       
  1744                 if ((c >= 'a' && c <= 'z')
       
  1745                     || (c >= 'A' && c <= 'Z')
       
  1746                     || (c >= '0' && c <= '9'))
       
  1747                     continue;
       
  1748             }
       
  1749         break;
       
  1750     }
       
  1751     if (i >= 0)
       
  1752         raiseWellFormedError(QXmlStream::tr("Unexpected character '%1' in public id literal.").arg(QChar(QLatin1Char(c))));
       
  1753 }
       
  1754 
       
  1755 /*
       
  1756   Checks whether the document starts with an xml declaration. If it
       
  1757   does, this function returns true; otherwise it sets up everything
       
  1758   for a synthetic start document event and returns false.
       
  1759  */
       
  1760 bool QXmlStreamReaderPrivate::checkStartDocument()
       
  1761 {
       
  1762     hasCheckedStartDocument = true;
       
  1763 
       
  1764     if (scanString(spell[XML], XML))
       
  1765         return true;
       
  1766 
       
  1767     type = QXmlStreamReader::StartDocument;
       
  1768     if (atEnd) {
       
  1769         hasCheckedStartDocument = false;
       
  1770         raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
       
  1771     }
       
  1772     return false;
       
  1773 }
       
  1774 
       
  1775 void QXmlStreamReaderPrivate::startDocument()
       
  1776 {
       
  1777     QString err;
       
  1778     if (documentVersion != QLatin1String("1.0")) {
       
  1779         if (documentVersion.toString().contains(QLatin1Char(' ')))
       
  1780             err = QXmlStream::tr("Invalid XML version string.");
       
  1781         else
       
  1782             err = QXmlStream::tr("Unsupported XML version.");
       
  1783     }
       
  1784     int n = attributeStack.size();
       
  1785 
       
  1786     /* We use this bool to ensure that the pesudo attributes are in the
       
  1787      * proper order:
       
  1788      *
       
  1789      * [23]     XMLDecl     ::=     '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>' */
       
  1790     bool hasStandalone = false;
       
  1791 
       
  1792     for (int i = 0; err.isNull() && i < n; ++i) {
       
  1793         Attribute &attrib = attributeStack[i];
       
  1794         QStringRef prefix(symPrefix(attrib.key));
       
  1795         QStringRef key(symString(attrib.key));
       
  1796         QStringRef value(symString(attrib.value));
       
  1797 
       
  1798         if (prefix.isEmpty() && key == QLatin1String("encoding")) {
       
  1799             const QString name(value.toString());
       
  1800             documentEncoding = value;
       
  1801 
       
  1802             if(hasStandalone)
       
  1803                 err = QXmlStream::tr("The standalone pseudo attribute must appear after the encoding.");
       
  1804             if(!QXmlUtils::isEncName(name))
       
  1805                 err = QXmlStream::tr("%1 is an invalid encoding name.").arg(name);
       
  1806             else {
       
  1807 #ifdef QT_NO_TEXTCODEC
       
  1808                 readBuffer = QString::fromLatin1(rawReadBuffer.data(), nbytesread);
       
  1809 #else
       
  1810                 QTextCodec *const newCodec = QTextCodec::codecForName(name.toLatin1());
       
  1811                 if (!newCodec)
       
  1812                     err = QXmlStream::tr("Encoding %1 is unsupported").arg(name);
       
  1813                 else if (newCodec != codec && !lockEncoding) {
       
  1814                     codec = newCodec;
       
  1815                     delete decoder;
       
  1816                     decoder = codec->makeDecoder();
       
  1817                     decoder->toUnicode(&readBuffer, rawReadBuffer.data(), nbytesread);
       
  1818                 }
       
  1819 #endif // QT_NO_TEXTCODEC
       
  1820             }
       
  1821         } else if (prefix.isEmpty() && key == QLatin1String("standalone")) {
       
  1822             hasStandalone = true;
       
  1823             if (value == QLatin1String("yes"))
       
  1824                 standalone = true;
       
  1825             else if (value == QLatin1String("no"))
       
  1826                 standalone = false;
       
  1827             else
       
  1828                 err = QXmlStream::tr("Standalone accepts only yes or no.");
       
  1829         } else {
       
  1830             err = QXmlStream::tr("Invalid attribute in XML declaration.");
       
  1831         }
       
  1832     }
       
  1833 
       
  1834     if (!err.isNull())
       
  1835         raiseWellFormedError(err);
       
  1836     attributeStack.clear();
       
  1837 }
       
  1838 
       
  1839 
       
  1840 void QXmlStreamReaderPrivate::raiseError(QXmlStreamReader::Error error, const QString& message)
       
  1841 {
       
  1842     this->error = error;
       
  1843     errorString = message;
       
  1844     if (errorString.isNull()) {
       
  1845         if (error == QXmlStreamReader::PrematureEndOfDocumentError)
       
  1846             errorString = QXmlStream::tr("Premature end of document.");
       
  1847         else if (error == QXmlStreamReader::CustomError)
       
  1848             errorString = QXmlStream::tr("Invalid document.");
       
  1849     }
       
  1850 
       
  1851     type = QXmlStreamReader::Invalid;
       
  1852 }
       
  1853 
       
  1854 void QXmlStreamReaderPrivate::raiseWellFormedError(const QString &message)
       
  1855 {
       
  1856     raiseError(QXmlStreamReader::NotWellFormedError, message);
       
  1857 }
       
  1858 
       
  1859 void QXmlStreamReaderPrivate::parseError()
       
  1860 {
       
  1861 
       
  1862     if (token == EOF_SYMBOL) {
       
  1863         raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
       
  1864         return;
       
  1865     }
       
  1866     const int nmax = 4;
       
  1867     QString error_message;
       
  1868     int ers = state_stack[tos];
       
  1869     int nexpected = 0;
       
  1870     int expected[nmax];
       
  1871     if (token != ERROR)
       
  1872         for (int tk = 0; tk < TERMINAL_COUNT; ++tk) {
       
  1873             int k = t_action(ers, tk);
       
  1874             if (k <= 0)
       
  1875                 continue;
       
  1876             if (spell[tk]) {
       
  1877                 if (nexpected < nmax)
       
  1878                     expected[nexpected++] = tk;
       
  1879             }
       
  1880         }
       
  1881 
       
  1882     error_message.clear ();
       
  1883     if (nexpected && nexpected < nmax) {
       
  1884         bool first = true;
       
  1885 
       
  1886         for (int s = 0; s < nexpected; ++s) {
       
  1887             if (first)
       
  1888                 error_message += QXmlStream::tr ("Expected ");
       
  1889             else if (s == nexpected - 1)
       
  1890                 error_message += QLatin1String (nexpected > 2 ? ", or " : " or ");
       
  1891             else
       
  1892                 error_message += QLatin1String (", ");
       
  1893 
       
  1894             first = false;
       
  1895             error_message += QLatin1String("\'");
       
  1896             error_message += QLatin1String (spell [expected[s]]);
       
  1897             error_message += QLatin1String("\'");
       
  1898         }
       
  1899         error_message += QXmlStream::tr(", but got \'");
       
  1900         error_message += QLatin1String(spell [token]);
       
  1901         error_message += QLatin1String("\'");
       
  1902     } else {
       
  1903         error_message += QXmlStream::tr("Unexpected \'");
       
  1904         error_message += QLatin1String(spell [token]);
       
  1905         error_message += QLatin1String("\'");
       
  1906     }
       
  1907     error_message += QLatin1Char('.');
       
  1908 
       
  1909     raiseWellFormedError(error_message);
       
  1910 }
       
  1911 
       
  1912 void QXmlStreamReaderPrivate::resume(int rule) {
       
  1913     resumeReduction = rule;
       
  1914     if (error == QXmlStreamReader::NoError)
       
  1915         raiseError(QXmlStreamReader::PrematureEndOfDocumentError);
       
  1916 }
       
  1917 
       
  1918 /*! Returns the current line number, starting with 1.
       
  1919 
       
  1920 \sa columnNumber(), characterOffset()
       
  1921  */
       
  1922 qint64 QXmlStreamReader::lineNumber() const
       
  1923 {
       
  1924     Q_D(const QXmlStreamReader);
       
  1925     return d->lineNumber + 1; // in public we start with 1
       
  1926 }
       
  1927 
       
  1928 /*! Returns the current column number, starting with 0.
       
  1929 
       
  1930 \sa lineNumber(), characterOffset()
       
  1931  */
       
  1932 qint64 QXmlStreamReader::columnNumber() const
       
  1933 {
       
  1934     Q_D(const QXmlStreamReader);
       
  1935     return d->characterOffset - d->lastLineStart + d->readBufferPos;
       
  1936 }
       
  1937 
       
  1938 /*! Returns the current character offset, starting with 0.
       
  1939 
       
  1940 \sa lineNumber(), columnNumber()
       
  1941 */
       
  1942 qint64 QXmlStreamReader::characterOffset() const
       
  1943 {
       
  1944     Q_D(const QXmlStreamReader);
       
  1945     return d->characterOffset + d->readBufferPos;
       
  1946 }
       
  1947 
       
  1948 
       
  1949 /*!  Returns the text of \l Characters, \l Comment, \l DTD, or
       
  1950   EntityReference.
       
  1951  */
       
  1952 QStringRef QXmlStreamReader::text() const
       
  1953 {
       
  1954     Q_D(const QXmlStreamReader);
       
  1955     return d->text;
       
  1956 }
       
  1957 
       
  1958 
       
  1959 /*!  If the state() is \l DTD, this function returns the DTD's
       
  1960   notation declarations. Otherwise an empty vector is returned.
       
  1961 
       
  1962   The QXmlStreamNotationDeclarations class is defined to be a QVector
       
  1963   of QXmlStreamNotationDeclaration.
       
  1964  */
       
  1965 QXmlStreamNotationDeclarations QXmlStreamReader::notationDeclarations() const
       
  1966 {
       
  1967     Q_D(const QXmlStreamReader);
       
  1968     if (d->notationDeclarations.size())
       
  1969         const_cast<QXmlStreamReaderPrivate *>(d)->resolveDtd();
       
  1970     return d->publicNotationDeclarations;
       
  1971 }
       
  1972 
       
  1973 
       
  1974 /*!  If the state() is \l DTD, this function returns the DTD's
       
  1975   unparsed (external) entity declarations. Otherwise an empty vector is returned.
       
  1976 
       
  1977   The QXmlStreamEntityDeclarations class is defined to be a QVector
       
  1978   of QXmlStreamEntityDeclaration.
       
  1979  */
       
  1980 QXmlStreamEntityDeclarations QXmlStreamReader::entityDeclarations() const
       
  1981 {
       
  1982     Q_D(const QXmlStreamReader);
       
  1983     if (d->entityDeclarations.size())
       
  1984         const_cast<QXmlStreamReaderPrivate *>(d)->resolveDtd();
       
  1985     return d->publicEntityDeclarations;
       
  1986 }
       
  1987 
       
  1988 /*!
       
  1989   \since 4.4
       
  1990 
       
  1991   If the state() is \l DTD, this function returns the DTD's
       
  1992   name. Otherwise an empty string is returned.
       
  1993 
       
  1994  */
       
  1995 QStringRef QXmlStreamReader::dtdName() const
       
  1996 {
       
  1997    Q_D(const QXmlStreamReader);
       
  1998    if (d->type == QXmlStreamReader::DTD)
       
  1999        return d->dtdName;
       
  2000    return QStringRef();
       
  2001 }
       
  2002 
       
  2003 /*!
       
  2004   \since 4.4
       
  2005 
       
  2006   If the state() is \l DTD, this function returns the DTD's
       
  2007   public identifier. Otherwise an empty string is returned.
       
  2008 
       
  2009  */
       
  2010 QStringRef QXmlStreamReader::dtdPublicId() const
       
  2011 {
       
  2012    Q_D(const QXmlStreamReader);
       
  2013    if (d->type == QXmlStreamReader::DTD)
       
  2014        return d->dtdPublicId;
       
  2015    return QStringRef();
       
  2016 }
       
  2017 
       
  2018 /*!
       
  2019   \since 4.4
       
  2020 
       
  2021   If the state() is \l DTD, this function returns the DTD's
       
  2022   system identifier. Otherwise an empty string is returned.
       
  2023 
       
  2024  */
       
  2025 QStringRef QXmlStreamReader::dtdSystemId() const
       
  2026 {
       
  2027    Q_D(const QXmlStreamReader);
       
  2028    if (d->type == QXmlStreamReader::DTD)
       
  2029        return d->dtdSystemId;
       
  2030    return QStringRef();
       
  2031 }
       
  2032 
       
  2033 /*!  If the state() is \l StartElement, this function returns the
       
  2034   element's namespace declarations. Otherwise an empty vector is
       
  2035   returned.
       
  2036 
       
  2037   The QXmlStreamNamespaceDeclaration class is defined to be a QVector
       
  2038   of QXmlStreamNamespaceDeclaration.
       
  2039 
       
  2040   \sa addExtraNamespaceDeclaration(), addExtraNamespaceDeclarations()
       
  2041  */
       
  2042 QXmlStreamNamespaceDeclarations QXmlStreamReader::namespaceDeclarations() const
       
  2043 {
       
  2044     Q_D(const QXmlStreamReader);
       
  2045     if (d->publicNamespaceDeclarations.isEmpty() && d->type == StartElement)
       
  2046         const_cast<QXmlStreamReaderPrivate *>(d)->resolvePublicNamespaces();
       
  2047     return d->publicNamespaceDeclarations;
       
  2048 }
       
  2049 
       
  2050 
       
  2051 /*!
       
  2052   \since 4.4
       
  2053 
       
  2054   Adds an \a extraNamespaceDeclaration. The declaration will be
       
  2055   valid for children of the current element, or - should the function
       
  2056   be called before any elements are read - for the entire XML
       
  2057   document.
       
  2058 
       
  2059   \sa namespaceDeclarations(), addExtraNamespaceDeclarations(), setNamespaceProcessing()
       
  2060  */
       
  2061 void QXmlStreamReader::addExtraNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &extraNamespaceDeclaration)
       
  2062 {
       
  2063     Q_D(QXmlStreamReader);
       
  2064     QXmlStreamReaderPrivate::NamespaceDeclaration &namespaceDeclaration = d->namespaceDeclarations.push();
       
  2065     namespaceDeclaration.prefix = d->addToStringStorage(extraNamespaceDeclaration.prefix());
       
  2066     namespaceDeclaration.namespaceUri = d->addToStringStorage(extraNamespaceDeclaration.namespaceUri());
       
  2067 }
       
  2068 
       
  2069 /*!
       
  2070   \since 4.4
       
  2071 
       
  2072   Adds a vector of declarations specified by \a extraNamespaceDeclarations.
       
  2073 
       
  2074   \sa namespaceDeclarations(), addExtraNamespaceDeclaration()
       
  2075  */
       
  2076 void QXmlStreamReader::addExtraNamespaceDeclarations(const QXmlStreamNamespaceDeclarations &extraNamespaceDeclarations)
       
  2077 {
       
  2078     for (int i = 0; i < extraNamespaceDeclarations.size(); ++i)
       
  2079         addExtraNamespaceDeclaration(extraNamespaceDeclarations.at(i));
       
  2080 }
       
  2081 
       
  2082 
       
  2083 /*!  Convenience function to be called in case a StartElement was
       
  2084   read. Reads until the corresponding EndElement and returns all text
       
  2085   in-between. In case of no error, the current token (see tokenType())
       
  2086   after having called this function is EndElement.
       
  2087 
       
  2088   The function concatenates text() when it reads either \l Characters
       
  2089   or EntityReference tokens, but skips ProcessingInstruction and \l
       
  2090   Comment. If the current token is not StartElement, an empty string is
       
  2091   returned.
       
  2092 
       
  2093   The \a behaviour defines what happens in case anything else is
       
  2094   read before reaching EndElement. The function can include the text from
       
  2095   child elements (useful for example for HTML), ignore child elements, or
       
  2096   raise an UnexpectedElementError and return what was read so far.
       
  2097 
       
  2098   \since 4.6
       
  2099  */
       
  2100 QString QXmlStreamReader::readElementText(ReadElementTextBehaviour behaviour)
       
  2101 {
       
  2102     Q_D(QXmlStreamReader);
       
  2103     if (isStartElement()) {
       
  2104         QString result;
       
  2105         forever {
       
  2106             switch (readNext()) {
       
  2107             case Characters:
       
  2108             case EntityReference:
       
  2109                 result.insert(result.size(), d->text.unicode(), d->text.size());
       
  2110                 break;
       
  2111             case EndElement:
       
  2112                 return result;
       
  2113             case ProcessingInstruction:
       
  2114             case Comment:
       
  2115                 break;
       
  2116             case StartElement:
       
  2117                 if (behaviour == SkipChildElements) {
       
  2118                     skipCurrentElement();
       
  2119                     break;
       
  2120                 } else if (behaviour == IncludeChildElements) {
       
  2121                     result += readElementText(behaviour);
       
  2122                     break;
       
  2123                 }
       
  2124                 // Fall through (for ErrorOnUnexpectedElement)
       
  2125             default:
       
  2126                 if (d->error || behaviour == ErrorOnUnexpectedElement) {
       
  2127                     if (!d->error)
       
  2128                         d->raiseError(UnexpectedElementError, QXmlStream::tr("Expected character data."));
       
  2129                     return result;
       
  2130                 }
       
  2131             }
       
  2132         }
       
  2133     }
       
  2134     return QString();
       
  2135 }
       
  2136 
       
  2137 /*!
       
  2138   \overload readElementText()
       
  2139 
       
  2140   Calling this function is equivalent to calling readElementText(ErrorOnUnexpectedElement).
       
  2141  */
       
  2142 QString QXmlStreamReader::readElementText()
       
  2143 {
       
  2144     return readElementText(ErrorOnUnexpectedElement);
       
  2145 }
       
  2146 
       
  2147 /*!  Raises a custom error with an optional error \a message.
       
  2148 
       
  2149   \sa error(), errorString()
       
  2150  */
       
  2151 void QXmlStreamReader::raiseError(const QString& message)
       
  2152 {
       
  2153     Q_D(QXmlStreamReader);
       
  2154     d->raiseError(CustomError, message);
       
  2155 }
       
  2156 
       
  2157 /*!
       
  2158   Returns the error message that was set with raiseError().
       
  2159 
       
  2160   \sa error(), lineNumber(), columnNumber(), characterOffset()
       
  2161  */
       
  2162 QString QXmlStreamReader::errorString() const
       
  2163 {
       
  2164     Q_D(const QXmlStreamReader);
       
  2165     if (d->type == QXmlStreamReader::Invalid)
       
  2166         return d->errorString;
       
  2167     return QString();
       
  2168 }
       
  2169 
       
  2170 /*!  Returns the type of the current error, or NoError if no error occurred.
       
  2171 
       
  2172   \sa errorString(), raiseError()
       
  2173  */
       
  2174 QXmlStreamReader::Error QXmlStreamReader::error() const
       
  2175 {
       
  2176     Q_D(const QXmlStreamReader);
       
  2177     if (d->type == QXmlStreamReader::Invalid)
       
  2178         return d->error;
       
  2179     return NoError;
       
  2180 }
       
  2181 
       
  2182 /*!
       
  2183   Returns the target of a ProcessingInstruction.
       
  2184  */
       
  2185 QStringRef QXmlStreamReader::processingInstructionTarget() const
       
  2186 {
       
  2187     Q_D(const QXmlStreamReader);
       
  2188     return d->processingInstructionTarget;
       
  2189 }
       
  2190 
       
  2191 /*!
       
  2192   Returns the data of a ProcessingInstruction.
       
  2193  */
       
  2194 QStringRef QXmlStreamReader::processingInstructionData() const
       
  2195 {
       
  2196     Q_D(const QXmlStreamReader);
       
  2197     return d->processingInstructionData;
       
  2198 }
       
  2199 
       
  2200 
       
  2201 
       
  2202 /*!
       
  2203   Returns the local name of a StartElement, EndElement, or an EntityReference.
       
  2204 
       
  2205   \sa namespaceUri(), qualifiedName()
       
  2206  */
       
  2207 QStringRef QXmlStreamReader::name() const
       
  2208 {
       
  2209     Q_D(const QXmlStreamReader);
       
  2210     return d->name;
       
  2211 }
       
  2212 
       
  2213 /*!
       
  2214   Returns the namespaceUri of a StartElement or EndElement.
       
  2215 
       
  2216   \sa name(), qualifiedName()
       
  2217  */
       
  2218 QStringRef QXmlStreamReader::namespaceUri() const
       
  2219 {
       
  2220     Q_D(const QXmlStreamReader);
       
  2221     return d->namespaceUri;
       
  2222 }
       
  2223 
       
  2224 /*!
       
  2225   Returns the qualified name of a StartElement or EndElement;
       
  2226 
       
  2227   A qualified name is the raw name of an element in the XML data. It
       
  2228   consists of the namespace prefix, followed by colon, followed by the
       
  2229   element's local name. Since the namespace prefix is not unique (the
       
  2230   same prefix can point to different namespaces and different prefixes
       
  2231   can point to the same namespace), you shouldn't use qualifiedName(),
       
  2232   but the resolved namespaceUri() and the attribute's local name().
       
  2233 
       
  2234    \sa name(), prefix(), namespaceUri()
       
  2235  */
       
  2236 QStringRef QXmlStreamReader::qualifiedName() const
       
  2237 {
       
  2238     Q_D(const QXmlStreamReader);
       
  2239     return d->qualifiedName;
       
  2240 }
       
  2241 
       
  2242 
       
  2243 
       
  2244 /*!
       
  2245   \since 4.4
       
  2246 
       
  2247   Returns the prefix of a StartElement or EndElement.
       
  2248 
       
  2249   \sa name(), qualifiedName()
       
  2250 */
       
  2251 QStringRef QXmlStreamReader::prefix() const
       
  2252 {
       
  2253     Q_D(const QXmlStreamReader);
       
  2254     return d->prefix;
       
  2255 }
       
  2256 
       
  2257 /*!
       
  2258   Returns the attributes of a StartElement.
       
  2259  */
       
  2260 QXmlStreamAttributes QXmlStreamReader::attributes() const
       
  2261 {
       
  2262     Q_D(const QXmlStreamReader);
       
  2263     return d->attributes;
       
  2264 }
       
  2265 
       
  2266 #endif // QT_NO_XMLSTREAMREADER
       
  2267 
       
  2268 /*!
       
  2269     \class QXmlStreamAttribute
       
  2270     \since 4.3
       
  2271     \reentrant
       
  2272     \brief The QXmlStreamAttribute class represents a single XML attribute
       
  2273 
       
  2274     \ingroup xml-tools
       
  2275 
       
  2276     An attribute consists of an optionally empty namespaceUri(), a
       
  2277     name(), a value(), and an isDefault() attribute.
       
  2278 
       
  2279     The raw XML attribute name is returned as qualifiedName().
       
  2280 */
       
  2281 
       
  2282 /*!
       
  2283   Creates an empty attribute.
       
  2284  */
       
  2285 QXmlStreamAttribute::QXmlStreamAttribute()
       
  2286 {
       
  2287     m_isDefault = false;
       
  2288 }
       
  2289 
       
  2290 /*!
       
  2291   Destructs an attribute.
       
  2292  */
       
  2293 QXmlStreamAttribute::~QXmlStreamAttribute()
       
  2294 {
       
  2295 }
       
  2296 
       
  2297 /*!  Constructs an attribute in the namespace described with \a
       
  2298   namespaceUri with \a name and value \a value.
       
  2299  */
       
  2300 QXmlStreamAttribute::QXmlStreamAttribute(const QString &namespaceUri, const QString &name, const QString &value)
       
  2301 {
       
  2302     m_namespaceUri = QXmlStreamStringRef(QStringRef(&namespaceUri));
       
  2303     m_name = m_qualifiedName = QXmlStreamStringRef(QStringRef(&name));
       
  2304     m_value = QXmlStreamStringRef(QStringRef(&value));
       
  2305     m_namespaceUri = QXmlStreamStringRef(QStringRef(&namespaceUri));
       
  2306 }
       
  2307 
       
  2308 /*!
       
  2309     Constructs an attribute with qualified name \a qualifiedName and value \a value.
       
  2310  */
       
  2311 QXmlStreamAttribute::QXmlStreamAttribute(const QString &qualifiedName, const QString &value)
       
  2312 {
       
  2313     int colon = qualifiedName.indexOf(QLatin1Char(':'));
       
  2314     m_name = QXmlStreamStringRef(QStringRef(&qualifiedName,
       
  2315                                             colon + 1,
       
  2316                                             qualifiedName.size() - (colon + 1)));
       
  2317     m_qualifiedName = QXmlStreamStringRef(QStringRef(&qualifiedName));
       
  2318     m_value = QXmlStreamStringRef(QStringRef(&value));
       
  2319 }
       
  2320 
       
  2321 /*! \fn QStringRef QXmlStreamAttribute::namespaceUri() const
       
  2322 
       
  2323    Returns the attribute's resolved namespaceUri, or an empty string
       
  2324    reference if the attribute does not have a defined namespace.
       
  2325  */
       
  2326 /*! \fn QStringRef QXmlStreamAttribute::name() const
       
  2327    Returns the attribute's local name.
       
  2328  */
       
  2329 /*! \fn QStringRef QXmlStreamAttribute::qualifiedName() const
       
  2330    Returns the attribute's qualified name.
       
  2331 
       
  2332    A qualified name is the raw name of an attribute in the XML
       
  2333    data. It consists of the namespace prefix(), followed by colon,
       
  2334    followed by the attribute's local name(). Since the namespace prefix
       
  2335    is not unique (the same prefix can point to different namespaces
       
  2336    and different prefixes can point to the same namespace), you
       
  2337    shouldn't use qualifiedName(), but the resolved namespaceUri() and
       
  2338    the attribute's local name().
       
  2339  */
       
  2340 /*!
       
  2341    \fn QStringRef QXmlStreamAttribute::prefix() const
       
  2342    \since 4.4
       
  2343    Returns the attribute's namespace prefix.
       
  2344 
       
  2345    \sa name(), qualifiedName()
       
  2346 
       
  2347 */
       
  2348 
       
  2349 /*! \fn QStringRef QXmlStreamAttribute::value() const
       
  2350    Returns the attribute's value.
       
  2351  */
       
  2352 
       
  2353 /*! \fn bool QXmlStreamAttribute::isDefault() const
       
  2354 
       
  2355    Returns true if the parser added this attribute with a default
       
  2356    value following an ATTLIST declaration in the DTD; otherwise
       
  2357    returns false.
       
  2358 */
       
  2359 /*! \fn bool QXmlStreamAttribute::operator==(const QXmlStreamAttribute &other) const
       
  2360 
       
  2361     Compares this attribute with \a other and returns true if they are
       
  2362     equal; otherwise returns false.
       
  2363  */
       
  2364 /*! \fn bool QXmlStreamAttribute::operator!=(const QXmlStreamAttribute &other) const
       
  2365 
       
  2366     Compares this attribute with \a other and returns true if they are
       
  2367     not equal; otherwise returns false.
       
  2368  */
       
  2369 
       
  2370 
       
  2371 /*!
       
  2372   Creates a copy of \a other.
       
  2373  */
       
  2374 QXmlStreamAttribute::QXmlStreamAttribute(const QXmlStreamAttribute &other)
       
  2375 {
       
  2376     *this = other;
       
  2377 }
       
  2378 
       
  2379 /*!
       
  2380   Assigns \a other to this attribute.
       
  2381  */
       
  2382 QXmlStreamAttribute& QXmlStreamAttribute::operator=(const QXmlStreamAttribute &other)
       
  2383 {
       
  2384     m_name = other.m_name;
       
  2385     m_namespaceUri = other.m_namespaceUri;
       
  2386     m_qualifiedName = other.m_qualifiedName;
       
  2387     m_value = other.m_value;
       
  2388     m_isDefault = other.m_isDefault;
       
  2389     return *this;
       
  2390 }
       
  2391 
       
  2392 
       
  2393 /*!
       
  2394     \class QXmlStreamAttributes
       
  2395     \since 4.3
       
  2396     \reentrant
       
  2397     \brief The QXmlStreamAttributes class represents a vector of QXmlStreamAttribute.
       
  2398 
       
  2399     Attributes are returned by a QXmlStreamReader in
       
  2400     \l{QXmlStreamReader::attributes()} {attributes()} when the reader
       
  2401     reports a \l {QXmlStreamReader::StartElement}{start element}. The
       
  2402     class can also be used with a QXmlStreamWriter as an argument to
       
  2403     \l {QXmlStreamWriter::writeAttributes()}{writeAttributes()}.
       
  2404 
       
  2405     The convenience function value() loops over the vector and returns
       
  2406     an attribute value for a given namespaceUri and an attribute's
       
  2407     name.
       
  2408 
       
  2409     New attributes can be added with append().
       
  2410 
       
  2411     \ingroup xml-tools
       
  2412 */
       
  2413 
       
  2414 /*!
       
  2415     \fn void QXmlStreamAttributes::append(const QXmlStreamAttribute &attribute)
       
  2416 
       
  2417     Appends the given \a attribute to the end of the vector.
       
  2418 
       
  2419     \sa QVector::append()
       
  2420 */
       
  2421 
       
  2422 
       
  2423 /*!
       
  2424     \typedef QXmlStreamNotationDeclarations
       
  2425     \relates QXmlStreamNotationDeclaration
       
  2426 
       
  2427     Synonym for QVector<QXmlStreamNotationDeclaration>.
       
  2428 */
       
  2429 
       
  2430 
       
  2431 /*!
       
  2432     \class QXmlStreamNotationDeclaration
       
  2433     \since 4.3
       
  2434     \reentrant
       
  2435     \brief The QXmlStreamNotationDeclaration class represents a DTD notation declaration.
       
  2436 
       
  2437     \ingroup xml-tools
       
  2438 
       
  2439     An notation declaration consists of a name(), a systemId(), and a publicId().
       
  2440 */
       
  2441 
       
  2442 /*!
       
  2443   Creates an empty notation declaration.
       
  2444 */
       
  2445 QXmlStreamNotationDeclaration::QXmlStreamNotationDeclaration()
       
  2446 {
       
  2447 }
       
  2448 /*!
       
  2449   Creates a copy of \a other.
       
  2450  */
       
  2451 QXmlStreamNotationDeclaration::QXmlStreamNotationDeclaration(const QXmlStreamNotationDeclaration &other)
       
  2452 {
       
  2453     *this = other;
       
  2454 }
       
  2455 
       
  2456 /*!
       
  2457   Assigns \a other to this notation declaration.
       
  2458  */
       
  2459 QXmlStreamNotationDeclaration& QXmlStreamNotationDeclaration::operator=(const QXmlStreamNotationDeclaration &other)
       
  2460 {
       
  2461     m_name = other.m_name;
       
  2462     m_systemId = other.m_systemId;
       
  2463     m_publicId = other.m_publicId;
       
  2464     return *this;
       
  2465 }
       
  2466 
       
  2467 /*!
       
  2468 Destructs this notation declaration.
       
  2469 */
       
  2470 QXmlStreamNotationDeclaration::~QXmlStreamNotationDeclaration()
       
  2471 {
       
  2472 }
       
  2473 
       
  2474 /*! \fn QStringRef QXmlStreamNotationDeclaration::name() const
       
  2475 
       
  2476 Returns the notation name.
       
  2477 */
       
  2478 /*! \fn QStringRef QXmlStreamNotationDeclaration::systemId() const
       
  2479 
       
  2480 Returns the system identifier.
       
  2481 */
       
  2482 /*! \fn QStringRef QXmlStreamNotationDeclaration::publicId() const
       
  2483 
       
  2484 Returns the public identifier.
       
  2485 */
       
  2486 
       
  2487 /*! \fn inline bool QXmlStreamNotationDeclaration::operator==(const QXmlStreamNotationDeclaration &other) const
       
  2488 
       
  2489     Compares this notation declaration with \a other and returns true
       
  2490     if they are equal; otherwise returns false.
       
  2491  */
       
  2492 /*! \fn inline bool QXmlStreamNotationDeclaration::operator!=(const QXmlStreamNotationDeclaration &other) const
       
  2493 
       
  2494     Compares this notation declaration with \a other and returns true
       
  2495     if they are not equal; otherwise returns false.
       
  2496  */
       
  2497 
       
  2498 /*!
       
  2499     \typedef QXmlStreamNamespaceDeclarations
       
  2500     \relates QXmlStreamNamespaceDeclaration
       
  2501 
       
  2502     Synonym for QVector<QXmlStreamNamespaceDeclaration>.
       
  2503 */
       
  2504 
       
  2505 /*!
       
  2506     \class QXmlStreamNamespaceDeclaration
       
  2507     \since 4.3
       
  2508     \reentrant
       
  2509     \brief The QXmlStreamNamespaceDeclaration class represents a namespace declaration.
       
  2510 
       
  2511     \ingroup xml-tools
       
  2512 
       
  2513     An namespace declaration consists of a prefix() and a namespaceUri().
       
  2514 */
       
  2515 /*! \fn inline bool QXmlStreamNamespaceDeclaration::operator==(const QXmlStreamNamespaceDeclaration &other) const
       
  2516 
       
  2517     Compares this namespace declaration with \a other and returns true
       
  2518     if they are equal; otherwise returns false.
       
  2519  */
       
  2520 /*! \fn inline bool QXmlStreamNamespaceDeclaration::operator!=(const QXmlStreamNamespaceDeclaration &other) const
       
  2521 
       
  2522     Compares this namespace declaration with \a other and returns true
       
  2523     if they are not equal; otherwise returns false.
       
  2524  */
       
  2525 
       
  2526 /*!
       
  2527   Creates an empty namespace declaration.
       
  2528 */
       
  2529 QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration()
       
  2530 {
       
  2531 }
       
  2532 
       
  2533 /*!
       
  2534   \since 4.4
       
  2535 
       
  2536   Creates a namespace declaration with \a prefix and \a namespaceUri.
       
  2537 */
       
  2538 QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration(const QString &prefix, const QString &namespaceUri)
       
  2539 {
       
  2540     m_prefix = prefix;
       
  2541     m_namespaceUri = namespaceUri;
       
  2542 }
       
  2543 
       
  2544 /*!
       
  2545   Creates a copy of \a other.
       
  2546  */
       
  2547 QXmlStreamNamespaceDeclaration::QXmlStreamNamespaceDeclaration(const QXmlStreamNamespaceDeclaration &other)
       
  2548 {
       
  2549     *this = other;
       
  2550 }
       
  2551 
       
  2552 /*!
       
  2553   Assigns \a other to this namespace declaration.
       
  2554  */
       
  2555 QXmlStreamNamespaceDeclaration& QXmlStreamNamespaceDeclaration::operator=(const QXmlStreamNamespaceDeclaration &other)
       
  2556 {
       
  2557     m_prefix = other.m_prefix;
       
  2558     m_namespaceUri = other.m_namespaceUri;
       
  2559     return *this;
       
  2560 }
       
  2561 /*!
       
  2562 Destructs this namespace declaration.
       
  2563 */
       
  2564 QXmlStreamNamespaceDeclaration::~QXmlStreamNamespaceDeclaration()
       
  2565 {
       
  2566 }
       
  2567 
       
  2568 /*! \fn QStringRef QXmlStreamNamespaceDeclaration::prefix() const
       
  2569 
       
  2570 Returns the prefix.
       
  2571 */
       
  2572 /*! \fn QStringRef QXmlStreamNamespaceDeclaration::namespaceUri() const
       
  2573 
       
  2574 Returns the namespaceUri.
       
  2575 */
       
  2576 
       
  2577 
       
  2578 
       
  2579 
       
  2580 /*!
       
  2581     \typedef QXmlStreamEntityDeclarations
       
  2582     \relates QXmlStreamEntityDeclaration
       
  2583 
       
  2584     Synonym for QVector<QXmlStreamEntityDeclaration>.
       
  2585 */
       
  2586 
       
  2587 /*!
       
  2588     \class QXmlStreamStringRef
       
  2589     \since 4.3
       
  2590     \internal
       
  2591 */
       
  2592 
       
  2593 /*!
       
  2594     \class QXmlStreamEntityDeclaration
       
  2595     \since 4.3
       
  2596     \reentrant
       
  2597     \brief The QXmlStreamEntityDeclaration class represents a DTD entity declaration.
       
  2598 
       
  2599     \ingroup xml-tools
       
  2600 
       
  2601     An entity declaration consists of a name(), a notationName(), a
       
  2602     systemId(), a publicId(), and a value().
       
  2603 */
       
  2604 
       
  2605 /*!
       
  2606   Creates an empty entity declaration.
       
  2607 */
       
  2608 QXmlStreamEntityDeclaration::QXmlStreamEntityDeclaration()
       
  2609 {
       
  2610 }
       
  2611 
       
  2612 /*!
       
  2613   Creates a copy of \a other.
       
  2614  */
       
  2615 QXmlStreamEntityDeclaration::QXmlStreamEntityDeclaration(const QXmlStreamEntityDeclaration &other)
       
  2616 {
       
  2617     *this = other;
       
  2618 }
       
  2619 
       
  2620 /*!
       
  2621   Assigns \a other to this entity declaration.
       
  2622  */
       
  2623 QXmlStreamEntityDeclaration& QXmlStreamEntityDeclaration::operator=(const QXmlStreamEntityDeclaration &other)
       
  2624 {
       
  2625     m_name = other.m_name;
       
  2626     m_notationName = other.m_notationName;
       
  2627     m_systemId = other.m_systemId;
       
  2628     m_publicId = other.m_publicId;
       
  2629     m_value = other.m_value;
       
  2630     return *this;
       
  2631 }
       
  2632 
       
  2633 /*!
       
  2634   Destructs this entity declaration.
       
  2635 */
       
  2636 QXmlStreamEntityDeclaration::~QXmlStreamEntityDeclaration()
       
  2637 {
       
  2638 }
       
  2639 
       
  2640 /*! \fn QStringRef QXmlStreamEntityDeclaration::name() const
       
  2641 
       
  2642 Returns the entity name.
       
  2643 */
       
  2644 /*! \fn QStringRef QXmlStreamEntityDeclaration::notationName() const
       
  2645 
       
  2646 Returns the notation name.
       
  2647 */
       
  2648 /*! \fn QStringRef QXmlStreamEntityDeclaration::systemId() const
       
  2649 
       
  2650 Returns the system identifier.
       
  2651 */
       
  2652 /*! \fn QStringRef QXmlStreamEntityDeclaration::publicId() const
       
  2653 
       
  2654 Returns the public identifier.
       
  2655 */
       
  2656 /*! \fn QStringRef QXmlStreamEntityDeclaration::value() const
       
  2657 
       
  2658 Returns the entity's value.
       
  2659 */
       
  2660 
       
  2661 /*! \fn bool QXmlStreamEntityDeclaration::operator==(const QXmlStreamEntityDeclaration &other) const
       
  2662 
       
  2663     Compares this entity declaration with \a other and returns true if
       
  2664     they are equal; otherwise returns false.
       
  2665  */
       
  2666 /*! \fn bool QXmlStreamEntityDeclaration::operator!=(const QXmlStreamEntityDeclaration &other) const
       
  2667 
       
  2668     Compares this entity declaration with \a other and returns true if
       
  2669     they are not equal; otherwise returns false.
       
  2670  */
       
  2671 
       
  2672 /*!  Returns the value of the attribute \a name in the namespace
       
  2673   described with \a namespaceUri, or an empty string reference if the
       
  2674   attribute is not defined. The \a namespaceUri can be empty.
       
  2675  */
       
  2676 QStringRef QXmlStreamAttributes::value(const QString &namespaceUri, const QString &name) const
       
  2677 {
       
  2678     for (int i = 0; i < size(); ++i) {
       
  2679         const QXmlStreamAttribute &attribute = at(i);
       
  2680         if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
       
  2681             return attribute.value();
       
  2682     }
       
  2683     return QStringRef();
       
  2684 }
       
  2685 
       
  2686 /*!\overload
       
  2687   Returns the value of the attribute \a name in the namespace
       
  2688   described with \a namespaceUri, or an empty string reference if the
       
  2689   attribute is not defined. The \a namespaceUri can be empty.
       
  2690  */
       
  2691 QStringRef QXmlStreamAttributes::value(const QString &namespaceUri, const QLatin1String &name) const
       
  2692 {
       
  2693     for (int i = 0; i < size(); ++i) {
       
  2694         const QXmlStreamAttribute &attribute = at(i);
       
  2695         if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
       
  2696             return attribute.value();
       
  2697     }
       
  2698     return QStringRef();
       
  2699 }
       
  2700 
       
  2701 /*!\overload
       
  2702   Returns the value of the attribute \a name in the namespace
       
  2703   described with \a namespaceUri, or an empty string reference if the
       
  2704   attribute is not defined. The \a namespaceUri can be empty.
       
  2705  */
       
  2706 QStringRef QXmlStreamAttributes::value(const QLatin1String &namespaceUri, const QLatin1String &name) const
       
  2707 {
       
  2708     for (int i = 0; i < size(); ++i) {
       
  2709         const QXmlStreamAttribute &attribute = at(i);
       
  2710         if (attribute.name() == name && attribute.namespaceUri() == namespaceUri)
       
  2711             return attribute.value();
       
  2712     }
       
  2713     return QStringRef();
       
  2714 }
       
  2715 
       
  2716 /*!\overload
       
  2717 
       
  2718   Returns the value of the attribute with qualified name \a
       
  2719   qualifiedName , or an empty string reference if the attribute is not
       
  2720   defined. A qualified name is the raw name of an attribute in the XML
       
  2721   data. It consists of the namespace prefix, followed by colon,
       
  2722   followed by the attribute's local name. Since the namespace prefix
       
  2723   is not unique (the same prefix can point to different namespaces and
       
  2724   different prefixes can point to the same namespace), you shouldn't
       
  2725   use qualified names, but a resolved namespaceUri and the attribute's
       
  2726   local name.
       
  2727  */
       
  2728 QStringRef QXmlStreamAttributes::value(const QString &qualifiedName) const
       
  2729 {
       
  2730     for (int i = 0; i < size(); ++i) {
       
  2731         const QXmlStreamAttribute &attribute = at(i);
       
  2732         if (attribute.qualifiedName() == qualifiedName)
       
  2733             return attribute.value();
       
  2734     }
       
  2735     return QStringRef();
       
  2736 }
       
  2737 
       
  2738 /*!\overload
       
  2739 
       
  2740   Returns the value of the attribute with qualified name \a
       
  2741   qualifiedName , or an empty string reference if the attribute is not
       
  2742   defined. A qualified name is the raw name of an attribute in the XML
       
  2743   data. It consists of the namespace prefix, followed by colon,
       
  2744   followed by the attribute's local name. Since the namespace prefix
       
  2745   is not unique (the same prefix can point to different namespaces and
       
  2746   different prefixes can point to the same namespace), you shouldn't
       
  2747   use qualified names, but a resolved namespaceUri and the attribute's
       
  2748   local name.
       
  2749  */
       
  2750 QStringRef QXmlStreamAttributes::value(const QLatin1String &qualifiedName) const
       
  2751 {
       
  2752     for (int i = 0; i < size(); ++i) {
       
  2753         const QXmlStreamAttribute &attribute = at(i);
       
  2754         if (attribute.qualifiedName() == qualifiedName)
       
  2755             return attribute.value();
       
  2756     }
       
  2757     return QStringRef();
       
  2758 }
       
  2759 
       
  2760 /*!Appends a new attribute with \a name in the namespace
       
  2761   described with \a namespaceUri, and value \a value. The \a
       
  2762   namespaceUri can be empty.
       
  2763  */
       
  2764 void QXmlStreamAttributes::append(const QString &namespaceUri, const QString &name, const QString &value)
       
  2765 {
       
  2766     append(QXmlStreamAttribute(namespaceUri, name, value));
       
  2767 }
       
  2768 
       
  2769 /*!\overload
       
  2770   Appends a new attribute with qualified name \a qualifiedName and
       
  2771   value \a value.
       
  2772  */
       
  2773 void QXmlStreamAttributes::append(const QString &qualifiedName, const QString &value)
       
  2774 {
       
  2775     append(QXmlStreamAttribute(qualifiedName, value));
       
  2776 }
       
  2777 
       
  2778 #ifndef QT_NO_XMLSTREAMREADER
       
  2779 
       
  2780 /*! \fn bool QXmlStreamReader::isStartDocument() const
       
  2781   Returns true if tokenType() equals \l StartDocument; otherwise returns false.
       
  2782 */
       
  2783 /*! \fn bool QXmlStreamReader::isEndDocument() const
       
  2784   Returns true if tokenType() equals \l EndDocument; otherwise returns false.
       
  2785 */
       
  2786 /*! \fn bool QXmlStreamReader::isStartElement() const
       
  2787   Returns true if tokenType() equals \l StartElement; otherwise returns false.
       
  2788 */
       
  2789 /*! \fn bool QXmlStreamReader::isEndElement() const
       
  2790   Returns true if tokenType() equals \l EndElement; otherwise returns false.
       
  2791 */
       
  2792 /*! \fn bool QXmlStreamReader::isCharacters() const
       
  2793   Returns true if tokenType() equals \l Characters; otherwise returns false.
       
  2794 
       
  2795   \sa isWhitespace(), isCDATA()
       
  2796 */
       
  2797 /*! \fn bool QXmlStreamReader::isComment() const
       
  2798   Returns true if tokenType() equals \l Comment; otherwise returns false.
       
  2799 */
       
  2800 /*! \fn bool QXmlStreamReader::isDTD() const
       
  2801   Returns true if tokenType() equals \l DTD; otherwise returns false.
       
  2802 */
       
  2803 /*! \fn bool QXmlStreamReader::isEntityReference() const
       
  2804   Returns true if tokenType() equals \l EntityReference; otherwise returns false.
       
  2805 */
       
  2806 /*! \fn bool QXmlStreamReader::isProcessingInstruction() const
       
  2807   Returns true if tokenType() equals \l ProcessingInstruction; otherwise returns false.
       
  2808 */
       
  2809 
       
  2810 /*!  Returns true if the reader reports characters that only consist
       
  2811   of white-space; otherwise returns false.
       
  2812 
       
  2813   \sa isCharacters(), text()
       
  2814 */
       
  2815 bool QXmlStreamReader::isWhitespace() const
       
  2816 {
       
  2817     Q_D(const QXmlStreamReader);
       
  2818     return d->type == QXmlStreamReader::Characters && d->isWhitespace;
       
  2819 }
       
  2820 
       
  2821 /*!  Returns true if the reader reports characters that stem from a
       
  2822   CDATA section; otherwise returns false.
       
  2823 
       
  2824   \sa isCharacters(), text()
       
  2825 */
       
  2826 bool QXmlStreamReader::isCDATA() const
       
  2827 {
       
  2828     Q_D(const QXmlStreamReader);
       
  2829     return d->type == QXmlStreamReader::Characters && d->isCDATA;
       
  2830 }
       
  2831 
       
  2832 
       
  2833 
       
  2834 /*!
       
  2835   Returns true if this document has been declared standalone in the
       
  2836   XML declaration; otherwise returns false.
       
  2837 
       
  2838   If no XML declaration has been parsed, this function returns false.
       
  2839  */
       
  2840 bool QXmlStreamReader::isStandaloneDocument() const
       
  2841 {
       
  2842     Q_D(const QXmlStreamReader);
       
  2843     return d->standalone;
       
  2844 }
       
  2845 
       
  2846 
       
  2847 /*!
       
  2848      \since 4.4
       
  2849 
       
  2850      If the state() is \l StartDocument, this function returns the
       
  2851      version string as specified in the XML declaration.
       
  2852      Otherwise an empty string is returned.
       
  2853  */
       
  2854 QStringRef QXmlStreamReader::documentVersion() const
       
  2855 {
       
  2856    Q_D(const QXmlStreamReader);
       
  2857    if (d->type == QXmlStreamReader::StartDocument)
       
  2858        return d->documentVersion;
       
  2859    return QStringRef();
       
  2860 }
       
  2861 
       
  2862 /*!
       
  2863      \since 4.4
       
  2864 
       
  2865      If the state() is \l StartDocument, this function returns the
       
  2866      encoding string as specified in the XML declaration.
       
  2867      Otherwise an empty string is returned.
       
  2868  */
       
  2869 QStringRef QXmlStreamReader::documentEncoding() const
       
  2870 {
       
  2871    Q_D(const QXmlStreamReader);
       
  2872    if (d->type == QXmlStreamReader::StartDocument)
       
  2873        return d->documentEncoding;
       
  2874    return QStringRef();
       
  2875 }
       
  2876 
       
  2877 #endif // QT_NO_XMLSTREAMREADER
       
  2878 
       
  2879 /*!
       
  2880   \class QXmlStreamWriter
       
  2881   \since 4.3
       
  2882   \reentrant
       
  2883 
       
  2884   \brief The QXmlStreamWriter class provides an XML writer with a
       
  2885   simple streaming API.
       
  2886 
       
  2887 
       
  2888   \inmodule QtXml
       
  2889   \ingroup xml-tools
       
  2890 
       
  2891   QXmlStreamWriter is the counterpart to QXmlStreamReader for writing
       
  2892   XML. Like its related class, it operates on a QIODevice specified
       
  2893   with setDevice(). The API is simple and straightforward: for every
       
  2894   XML token or event you want to write, the writer provides a
       
  2895   specialized function.
       
  2896 
       
  2897   You start a document with writeStartDocument() and end it with
       
  2898   writeEndDocument(). This will implicitly close all remaining open
       
  2899   tags.
       
  2900 
       
  2901   Element tags are opened with writeStartElement() followed by
       
  2902   writeAttribute() or writeAttributes(), element content, and then
       
  2903   writeEndElement(). A shorter form writeEmptyElement() can be used
       
  2904   to write empty elements, followed by writeAttributes().
       
  2905 
       
  2906   Element content consists of either characters, entity references or
       
  2907   nested elements. It is written with writeCharacters(), which also
       
  2908   takes care of escaping all forbidden characters and character
       
  2909   sequences, writeEntityReference(), or subsequent calls to
       
  2910   writeStartElement(). A convenience method writeTextElement() can be
       
  2911   used for writing terminal elements that contain nothing but text.
       
  2912 
       
  2913   The following abridged code snippet shows the basic use of the class
       
  2914   to write formatted XML with indentation:
       
  2915 
       
  2916   \snippet doc/src/snippets/qxmlstreamwriter/main.cpp start stream
       
  2917   \dots
       
  2918   \snippet doc/src/snippets/qxmlstreamwriter/main.cpp write element
       
  2919   \dots
       
  2920   \snippet doc/src/snippets/qxmlstreamwriter/main.cpp finish stream
       
  2921 
       
  2922   QXmlStreamWriter takes care of prefixing namespaces, all you have to
       
  2923   do is specify the \c namespaceUri when writing elements or
       
  2924   attributes. If you must conform to certain prefixes, you can force
       
  2925   the writer to use them by declaring the namespaces manually with
       
  2926   either writeNamespace() or writeDefaultNamespace(). Alternatively,
       
  2927   you can bypass the stream writer's namespace support and use
       
  2928   overloaded methods that take a qualified name instead. The namespace
       
  2929   \e http://www.w3.org/XML/1998/namespace is implicit and mapped to the
       
  2930   prefix \e xml.
       
  2931 
       
  2932   The stream writer can automatically format the generated XML data by
       
  2933   adding line-breaks and indentation to empty sections between
       
  2934   elements, making the XML data more readable for humans and easier to
       
  2935   work with for most source code management systems. The feature can
       
  2936   be turned on with the \l autoFormatting property, and customized
       
  2937   with the \l autoFormattingIndent property.
       
  2938 
       
  2939   Other functions are writeCDATA(), writeComment(),
       
  2940   writeProcessingInstruction(), and writeDTD(). Chaining of XML
       
  2941   streams is supported with writeCurrentToken().
       
  2942 
       
  2943   By default, QXmlStreamWriter encodes XML in UTF-8. Different
       
  2944   encodings can be enforced using setCodec().
       
  2945 
       
  2946   The \l{QXmlStream Bookmarks Example} illustrates how to use a
       
  2947   stream writer to write an XML bookmark file (XBEL) that
       
  2948   was previously read in by a QXmlStreamReader.
       
  2949 
       
  2950 */
       
  2951 
       
  2952 #ifndef QT_NO_XMLSTREAMWRITER
       
  2953 
       
  2954 class QXmlStreamWriterPrivate : public QXmlStreamPrivateTagStack {
       
  2955     QXmlStreamWriter *q_ptr;
       
  2956     Q_DECLARE_PUBLIC(QXmlStreamWriter)
       
  2957 public:
       
  2958     QXmlStreamWriterPrivate(QXmlStreamWriter *q);
       
  2959     ~QXmlStreamWriterPrivate() {
       
  2960         if (deleteDevice)
       
  2961             delete device;
       
  2962 #ifndef QT_NO_TEXTCODEC
       
  2963         delete encoder;
       
  2964 #endif
       
  2965     }
       
  2966 
       
  2967     void write(const QStringRef &);
       
  2968     void write(const QString &);
       
  2969     void writeEscaped(const QString &, bool escapeWhitespace = false);
       
  2970     void write(const char *s);
       
  2971     bool finishStartElement(bool contents = true);
       
  2972     void writeStartElement(const QString &namespaceUri, const QString &name);
       
  2973     QIODevice *device;
       
  2974     QString *stringDevice;
       
  2975     uint deleteDevice :1;
       
  2976     uint inStartElement :1;
       
  2977     uint inEmptyElement :1;
       
  2978     uint lastWasStartElement :1;
       
  2979     uint wroteSomething :1;
       
  2980     uint autoFormatting :1;
       
  2981     QByteArray autoFormattingIndent;
       
  2982     NamespaceDeclaration emptyNamespace;
       
  2983     int lastNamespaceDeclaration;
       
  2984 
       
  2985 #ifndef QT_NO_TEXTCODEC
       
  2986     QTextCodec *codec;
       
  2987     QTextEncoder *encoder;
       
  2988 #endif
       
  2989 
       
  2990     NamespaceDeclaration &findNamespace(const QString &namespaceUri, bool writeDeclaration = false, bool noDefault = false);
       
  2991     void writeNamespaceDeclaration(const NamespaceDeclaration &namespaceDeclaration);
       
  2992 
       
  2993     int namespacePrefixCount;
       
  2994 
       
  2995     void indent(int level);
       
  2996 };
       
  2997 
       
  2998 
       
  2999 QXmlStreamWriterPrivate::QXmlStreamWriterPrivate(QXmlStreamWriter *q)
       
  3000     :autoFormattingIndent(4, ' ')
       
  3001 {
       
  3002     q_ptr = q;
       
  3003     device = 0;
       
  3004     stringDevice = 0;
       
  3005     deleteDevice = false;
       
  3006 #ifndef QT_NO_TEXTCODEC
       
  3007     codec = QTextCodec::codecForMib(106); // utf8
       
  3008     encoder = codec->makeEncoder();
       
  3009     encoder->fromUnicode(QLatin1String("")); // no byte order mark for utf8
       
  3010 #endif
       
  3011     inStartElement = inEmptyElement = false;
       
  3012     wroteSomething = false;
       
  3013     lastWasStartElement = false;
       
  3014     lastNamespaceDeclaration = 1;
       
  3015     autoFormatting = false;
       
  3016     namespacePrefixCount = 0;
       
  3017 }
       
  3018 
       
  3019 void QXmlStreamWriterPrivate::write(const QStringRef &s)
       
  3020 {
       
  3021     if (device) {
       
  3022 #ifdef QT_NO_TEXTCODEC
       
  3023         device->write(s.toString().toLatin1(), s.size());
       
  3024 #else
       
  3025         device->write(encoder->fromUnicode(s.constData(), s.size()));
       
  3026 #endif
       
  3027     }
       
  3028     else if (stringDevice)
       
  3029         s.appendTo(stringDevice);
       
  3030     else
       
  3031         qWarning("QXmlStreamWriter: No device");
       
  3032 }
       
  3033 
       
  3034 void QXmlStreamWriterPrivate::write(const QString &s)
       
  3035 {
       
  3036     if (device) {
       
  3037 #ifdef QT_NO_TEXTCODEC
       
  3038         device->write(s.toLatin1(), s.size());
       
  3039 #else
       
  3040         device->write(encoder->fromUnicode(s));
       
  3041 #endif
       
  3042     }
       
  3043     else if (stringDevice)
       
  3044         stringDevice->append(s);
       
  3045     else
       
  3046         qWarning("QXmlStreamWriter: No device");
       
  3047 }
       
  3048 
       
  3049 void QXmlStreamWriterPrivate::writeEscaped(const QString &s, bool escapeWhitespace)
       
  3050 {
       
  3051     QString escaped;
       
  3052     escaped.reserve(s.size());
       
  3053     for ( int i = 0; i < s.size(); ++i ) {
       
  3054         QChar c = s.at(i);
       
  3055         if (c.unicode() == '<' )
       
  3056             escaped.append(QLatin1String("&lt;"));
       
  3057         else if (c.unicode() == '>' )
       
  3058             escaped.append(QLatin1String("&gt;"));
       
  3059         else if (c.unicode() == '&' )
       
  3060             escaped.append(QLatin1String("&amp;"));
       
  3061         else if (c.unicode() == '\"' )
       
  3062             escaped.append(QLatin1String("&quot;"));
       
  3063         else if (escapeWhitespace && c.isSpace()) {
       
  3064             if (c.unicode() == '\n')
       
  3065                 escaped.append(QLatin1String("&#10;"));
       
  3066             else if (c.unicode() == '\r')
       
  3067                 escaped.append(QLatin1String("&#13;"));
       
  3068             else if (c.unicode() == '\t')
       
  3069                 escaped.append(QLatin1String("&#9;"));
       
  3070             else
       
  3071                 escaped += c;
       
  3072         } else {
       
  3073             escaped += QChar(c);
       
  3074         }
       
  3075     }
       
  3076     if (device) {
       
  3077 #ifdef QT_NO_TEXTCODEC
       
  3078         device->write(escaped.toLatin1(), escaped.size());
       
  3079 #else
       
  3080         device->write(encoder->fromUnicode(escaped));
       
  3081 #endif
       
  3082     }
       
  3083     else if (stringDevice)
       
  3084         stringDevice->append(escaped);
       
  3085     else
       
  3086         qWarning("QXmlStreamWriter: No device");
       
  3087 }
       
  3088 
       
  3089 
       
  3090 void QXmlStreamWriterPrivate::write(const char *s)
       
  3091 {
       
  3092     if (device) {
       
  3093 #ifndef QT_NO_TEXTCODEC
       
  3094         if (codec->mibEnum() != 106)
       
  3095             device->write(encoder->fromUnicode(QLatin1String(s)));
       
  3096         else
       
  3097 #endif
       
  3098             device->write(s, strlen(s));
       
  3099     } else if (stringDevice) {
       
  3100         stringDevice->append(QLatin1String(s));
       
  3101     } else
       
  3102         qWarning("QXmlStreamWriter: No device");
       
  3103 }
       
  3104 
       
  3105 void QXmlStreamWriterPrivate::writeNamespaceDeclaration(const NamespaceDeclaration &namespaceDeclaration) {
       
  3106     if (namespaceDeclaration.prefix.isEmpty()) {
       
  3107         write(" xmlns=\"");
       
  3108         write(namespaceDeclaration.namespaceUri);
       
  3109         write("\"");
       
  3110     } else {
       
  3111         write(" xmlns:");
       
  3112         write(namespaceDeclaration.prefix);
       
  3113         write("=\"");
       
  3114         write(namespaceDeclaration.namespaceUri);
       
  3115         write("\"");
       
  3116     }
       
  3117 }
       
  3118 
       
  3119 bool QXmlStreamWriterPrivate::finishStartElement(bool contents)
       
  3120 {
       
  3121     bool hadSomethingWritten = wroteSomething;
       
  3122     wroteSomething = contents;
       
  3123     if (!inStartElement)
       
  3124         return hadSomethingWritten;
       
  3125 
       
  3126     if (inEmptyElement) {
       
  3127         write("/>");
       
  3128         QXmlStreamWriterPrivate::Tag &tag = tagStack_pop();
       
  3129         lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
       
  3130         lastWasStartElement = false;
       
  3131     } else {
       
  3132         write(">");
       
  3133     }
       
  3134     inStartElement = inEmptyElement = false;
       
  3135     lastNamespaceDeclaration = namespaceDeclarations.size();
       
  3136     return hadSomethingWritten;
       
  3137 }
       
  3138 
       
  3139 QXmlStreamPrivateTagStack::NamespaceDeclaration &QXmlStreamWriterPrivate::findNamespace(const QString &namespaceUri, bool writeDeclaration, bool noDefault)
       
  3140 {
       
  3141     for (int j = namespaceDeclarations.size() - 1; j >= 0; --j) {
       
  3142         NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations[j];
       
  3143         if (namespaceDeclaration.namespaceUri == namespaceUri) {
       
  3144             if (!noDefault || !namespaceDeclaration.prefix.isEmpty())
       
  3145                 return namespaceDeclaration;
       
  3146         }
       
  3147     }
       
  3148     if (namespaceUri.isEmpty())
       
  3149         return emptyNamespace;
       
  3150     NamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.push();
       
  3151     if (namespaceUri.isEmpty()) {
       
  3152         namespaceDeclaration.prefix.clear();
       
  3153     } else {
       
  3154         QString s;
       
  3155         int n = ++namespacePrefixCount;
       
  3156         forever {
       
  3157             s = QLatin1Char('n') + QString::number(n++);
       
  3158             int j = namespaceDeclarations.size() - 2;
       
  3159             while (j >= 0 && namespaceDeclarations.at(j).prefix != s)
       
  3160                 --j;
       
  3161             if (j < 0)
       
  3162                 break;
       
  3163 	}
       
  3164         namespaceDeclaration.prefix = addToStringStorage(s);
       
  3165     }
       
  3166     namespaceDeclaration.namespaceUri = addToStringStorage(namespaceUri);
       
  3167     if (writeDeclaration)
       
  3168         writeNamespaceDeclaration(namespaceDeclaration);
       
  3169     return namespaceDeclaration;
       
  3170 }
       
  3171 
       
  3172 
       
  3173 
       
  3174 void QXmlStreamWriterPrivate::indent(int level)
       
  3175 {
       
  3176     write("\n");
       
  3177     for (int i = level; i > 0; --i)
       
  3178         write(autoFormattingIndent.constData());
       
  3179 }
       
  3180 
       
  3181 
       
  3182 /*!
       
  3183   Constructs a stream writer.
       
  3184 
       
  3185   \sa setDevice()
       
  3186  */
       
  3187 QXmlStreamWriter::QXmlStreamWriter()
       
  3188     : d_ptr(new QXmlStreamWriterPrivate(this))
       
  3189 {
       
  3190 }
       
  3191 
       
  3192 /*!
       
  3193   Constructs a stream writer that writes into \a device;
       
  3194  */
       
  3195 QXmlStreamWriter::QXmlStreamWriter(QIODevice *device)
       
  3196     : d_ptr(new QXmlStreamWriterPrivate(this))
       
  3197 {
       
  3198     Q_D(QXmlStreamWriter);
       
  3199     d->device = device;
       
  3200 }
       
  3201 
       
  3202 /*!  Constructs a stream writer that writes into \a array. This is the
       
  3203   same as creating an xml writer that operates on a QBuffer device
       
  3204   which in turn operates on \a array.
       
  3205  */
       
  3206 QXmlStreamWriter::QXmlStreamWriter(QByteArray *array)
       
  3207     : d_ptr(new QXmlStreamWriterPrivate(this))
       
  3208 {
       
  3209     Q_D(QXmlStreamWriter);
       
  3210     d->device = new QBuffer(array);
       
  3211     d->device->open(QIODevice::WriteOnly);
       
  3212     d->deleteDevice = true;
       
  3213 }
       
  3214 
       
  3215 
       
  3216 /*!  Constructs a stream writer that writes into \a string.
       
  3217  */
       
  3218 QXmlStreamWriter::QXmlStreamWriter(QString *string)
       
  3219     : d_ptr(new QXmlStreamWriterPrivate(this))
       
  3220 {
       
  3221     Q_D(QXmlStreamWriter);
       
  3222     d->stringDevice = string;
       
  3223 }
       
  3224 
       
  3225 /*!
       
  3226     Destructor.
       
  3227 */
       
  3228 QXmlStreamWriter::~QXmlStreamWriter()
       
  3229 {
       
  3230 }
       
  3231 
       
  3232 
       
  3233 /*!
       
  3234     Sets the current device to \a device. If you want the stream to
       
  3235     write into a QByteArray, you can create a QBuffer device.
       
  3236 
       
  3237     \sa device()
       
  3238 */
       
  3239 void QXmlStreamWriter::setDevice(QIODevice *device)
       
  3240 {
       
  3241     Q_D(QXmlStreamWriter);
       
  3242     if (device == d->device)
       
  3243         return;
       
  3244     d->stringDevice = 0;
       
  3245     if (d->deleteDevice) {
       
  3246         delete d->device;
       
  3247         d->deleteDevice = false;
       
  3248     }
       
  3249     d->device = device;
       
  3250 }
       
  3251 
       
  3252 /*!
       
  3253     Returns the current device associated with the QXmlStreamWriter,
       
  3254     or 0 if no device has been assigned.
       
  3255 
       
  3256     \sa setDevice()
       
  3257 */
       
  3258 QIODevice *QXmlStreamWriter::device() const
       
  3259 {
       
  3260     Q_D(const QXmlStreamWriter);
       
  3261     return d->device;
       
  3262 }
       
  3263 
       
  3264 
       
  3265 #ifndef QT_NO_TEXTCODEC
       
  3266 /*!
       
  3267     Sets the codec for this stream to \a codec. The codec is used for
       
  3268     encoding any data that is written. By default, QXmlStreamWriter
       
  3269     uses UTF-8.
       
  3270 
       
  3271     The encoding information is stored in the initial xml tag which
       
  3272     gets written when you call writeStartDocument(). Call this
       
  3273     function before calling writeStartDocument().
       
  3274 
       
  3275     \sa codec()
       
  3276 */
       
  3277 void QXmlStreamWriter::setCodec(QTextCodec *codec)
       
  3278 {
       
  3279     Q_D(QXmlStreamWriter);
       
  3280     if (codec) {
       
  3281         d->codec = codec;
       
  3282         delete d->encoder;
       
  3283         d->encoder = codec->makeEncoder();
       
  3284         if (codec->mibEnum() == 106)
       
  3285             d->encoder->fromUnicode(QLatin1String("")); // no byte order mark for utf8
       
  3286     }
       
  3287 }
       
  3288 
       
  3289 /*!
       
  3290     Sets the codec for this stream to the QTextCodec for the encoding
       
  3291     specified by \a codecName. Common values for \c codecName include
       
  3292     "ISO 8859-1", "UTF-8", and "UTF-16". If the encoding isn't
       
  3293     recognized, nothing happens.
       
  3294 
       
  3295     \sa QTextCodec::codecForName()
       
  3296 */
       
  3297 void QXmlStreamWriter::setCodec(const char *codecName)
       
  3298 {
       
  3299     setCodec(QTextCodec::codecForName(codecName));
       
  3300 }
       
  3301 
       
  3302 /*!
       
  3303     Returns the codec that is currently assigned to the stream.
       
  3304 
       
  3305     \sa setCodec()
       
  3306 */
       
  3307 QTextCodec *QXmlStreamWriter::codec() const
       
  3308 {
       
  3309     Q_D(const QXmlStreamWriter);
       
  3310     return d->codec;
       
  3311 }
       
  3312 #endif // QT_NO_TEXTCODEC
       
  3313 
       
  3314 /*!
       
  3315     \property  QXmlStreamWriter::autoFormatting
       
  3316     \since 4.4
       
  3317     the auto-formatting flag of the stream writer
       
  3318 
       
  3319     This property controls whether or not the stream writer
       
  3320     automatically formats the generated XML data. If enabled, the
       
  3321     writer automatically adds line-breaks and indentation to empty
       
  3322     sections between elements (ignorable whitespace). The main purpose
       
  3323     of auto-formatting is to split the data into several lines, and to
       
  3324     increase readability for a human reader. The indentation depth can
       
  3325     be controlled through the \l autoFormattingIndent property.
       
  3326 
       
  3327     By default, auto-formatting is disabled.
       
  3328 */
       
  3329 
       
  3330 /*!
       
  3331  \since 4.4
       
  3332 
       
  3333  Enables auto formatting if \a enable is \c true, otherwise
       
  3334  disables it.
       
  3335 
       
  3336  The default value is \c false.
       
  3337  */
       
  3338 void QXmlStreamWriter::setAutoFormatting(bool enable)
       
  3339 {
       
  3340     Q_D(QXmlStreamWriter);
       
  3341     d->autoFormatting = enable;
       
  3342 }
       
  3343 
       
  3344 /*!
       
  3345  \since 4.4
       
  3346 
       
  3347  Returns \c true if auto formattting is enabled, otherwise \c false.
       
  3348  */
       
  3349 bool QXmlStreamWriter::autoFormatting() const
       
  3350 {
       
  3351     Q_D(const QXmlStreamWriter);
       
  3352     return d->autoFormatting;
       
  3353 }
       
  3354 
       
  3355 /*!
       
  3356     \property QXmlStreamWriter::autoFormattingIndent
       
  3357     \since 4.4
       
  3358 
       
  3359     \brief the number of spaces or tabs used for indentation when
       
  3360     auto-formatting is enabled.  Positive numbers indicate spaces,
       
  3361     negative numbers tabs.
       
  3362 
       
  3363     The default indentation is 4.
       
  3364 
       
  3365     \sa autoFormatting
       
  3366 */
       
  3367 
       
  3368 
       
  3369 void QXmlStreamWriter::setAutoFormattingIndent(int spacesOrTabs)
       
  3370 {
       
  3371     Q_D(QXmlStreamWriter);
       
  3372     d->autoFormattingIndent = QByteArray(qAbs(spacesOrTabs), spacesOrTabs >= 0 ? ' ' : '\t');
       
  3373 }
       
  3374 
       
  3375 int QXmlStreamWriter::autoFormattingIndent() const
       
  3376 {
       
  3377     Q_D(const QXmlStreamWriter);
       
  3378     return d->autoFormattingIndent.count(' ') - d->autoFormattingIndent.count('\t');
       
  3379 }
       
  3380 
       
  3381 
       
  3382 /*!
       
  3383   \overload
       
  3384   Writes an attribute with \a qualifiedName and \a value.
       
  3385 
       
  3386 
       
  3387   This function can only be called after writeStartElement() before
       
  3388   any content is written, or after writeEmptyElement().
       
  3389  */
       
  3390 void QXmlStreamWriter::writeAttribute(const QString &qualifiedName, const QString &value)
       
  3391 {
       
  3392     Q_D(QXmlStreamWriter);
       
  3393     Q_ASSERT(d->inStartElement);
       
  3394     Q_ASSERT(qualifiedName.count(QLatin1Char(':')) <= 1);
       
  3395     d->write(" ");
       
  3396     d->write(qualifiedName);
       
  3397     d->write("=\"");
       
  3398     d->writeEscaped(value, true);
       
  3399     d->write("\"");
       
  3400 }
       
  3401 
       
  3402 /*!  Writes an attribute with \a name and \a value, prefixed for
       
  3403   the specified \a namespaceUri. If the namespace has not been
       
  3404   declared yet, QXmlStreamWriter will generate a namespace declaration
       
  3405   for it.
       
  3406 
       
  3407   This function can only be called after writeStartElement() before
       
  3408   any content is written, or after writeEmptyElement().
       
  3409  */
       
  3410 void QXmlStreamWriter::writeAttribute(const QString &namespaceUri, const QString &name, const QString &value)
       
  3411 {
       
  3412     Q_D(QXmlStreamWriter);
       
  3413     Q_ASSERT(d->inStartElement);
       
  3414     Q_ASSERT(!name.contains(QLatin1Char(':')));
       
  3415     QXmlStreamWriterPrivate::NamespaceDeclaration &namespaceDeclaration = d->findNamespace(namespaceUri, true, true);
       
  3416     d->write(" ");
       
  3417     if (!namespaceDeclaration.prefix.isEmpty()) {
       
  3418         d->write(namespaceDeclaration.prefix);
       
  3419         d->write(":");
       
  3420     }
       
  3421     d->write(name);
       
  3422     d->write("=\"");
       
  3423     d->writeEscaped(value, true);
       
  3424     d->write("\"");
       
  3425 }
       
  3426 
       
  3427 /*!
       
  3428   \overload
       
  3429 
       
  3430   Writes the \a attribute.
       
  3431 
       
  3432   This function can only be called after writeStartElement() before
       
  3433   any content is written, or after writeEmptyElement().
       
  3434  */
       
  3435 void QXmlStreamWriter::writeAttribute(const QXmlStreamAttribute& attribute)
       
  3436 {
       
  3437     if (attribute.namespaceUri().isEmpty())
       
  3438         writeAttribute(attribute.qualifiedName().toString(),
       
  3439                        attribute.value().toString());
       
  3440     else
       
  3441         writeAttribute(attribute.namespaceUri().toString(),
       
  3442                        attribute.name().toString(),
       
  3443                        attribute.value().toString());
       
  3444 }
       
  3445 
       
  3446 
       
  3447 /*!  Writes the attribute vector \a attributes. If a namespace
       
  3448   referenced in an attribute not been declared yet, QXmlStreamWriter
       
  3449   will generate a namespace declaration for it.
       
  3450 
       
  3451   This function can only be called after writeStartElement() before
       
  3452   any content is written, or after writeEmptyElement().
       
  3453 
       
  3454   \sa writeAttribute(), writeNamespace()
       
  3455  */
       
  3456 void QXmlStreamWriter::writeAttributes(const QXmlStreamAttributes& attributes)
       
  3457 {
       
  3458     Q_D(QXmlStreamWriter);
       
  3459     Q_ASSERT(d->inStartElement);
       
  3460     Q_UNUSED(d);
       
  3461     for (int i = 0; i < attributes.size(); ++i)
       
  3462         writeAttribute(attributes.at(i));
       
  3463 }
       
  3464 
       
  3465 
       
  3466 /*!  Writes \a text as CDATA section. If \a text contains the
       
  3467   forbidden character sequence "]]>", it is split into different CDATA
       
  3468   sections.
       
  3469 
       
  3470   This function mainly exists for completeness. Normally you should
       
  3471   not need use it, because writeCharacters() automatically escapes all
       
  3472   non-content characters.
       
  3473  */
       
  3474 void QXmlStreamWriter::writeCDATA(const QString &text)
       
  3475 {
       
  3476     Q_D(QXmlStreamWriter);
       
  3477     d->finishStartElement();
       
  3478     QString copy(text);
       
  3479     copy.replace(QLatin1String("]]>"), QLatin1String("]]]]><![CDATA[>"));
       
  3480     d->write("<![CDATA[");
       
  3481     d->write(copy);
       
  3482     d->write("]]>");
       
  3483 }
       
  3484 
       
  3485 
       
  3486 /*!  Writes \a text. The characters "<", "&", and "\"" are escaped as entity
       
  3487   references "&lt;", "&amp;, and "&quot;". To avoid the forbidden sequence
       
  3488   "]]>", ">" is also escaped as "&gt;".
       
  3489 
       
  3490   \sa writeEntityReference()
       
  3491  */
       
  3492 void QXmlStreamWriter::writeCharacters(const QString &text)
       
  3493 {
       
  3494     Q_D(QXmlStreamWriter);
       
  3495     d->finishStartElement();
       
  3496     d->writeEscaped(text);
       
  3497 }
       
  3498 
       
  3499 
       
  3500 /*!  Writes \a text as XML comment, where \a text must not contain the
       
  3501      forbidden sequence "--" or end with "-". Note that XML does not
       
  3502      provide any way to escape "-" in a comment.
       
  3503  */
       
  3504 void QXmlStreamWriter::writeComment(const QString &text)
       
  3505 {
       
  3506     Q_D(QXmlStreamWriter);
       
  3507     Q_ASSERT(!text.contains(QLatin1String("--")) && !text.endsWith(QLatin1Char('-')));
       
  3508     if (!d->finishStartElement(false) && d->autoFormatting)
       
  3509         d->indent(d->tagStack.size());
       
  3510     d->write("<!--");
       
  3511     d->write(text);
       
  3512     d->write("-->");
       
  3513     d->inStartElement = d->lastWasStartElement = false;
       
  3514 }
       
  3515 
       
  3516 
       
  3517 /*!  Writes a DTD section. The \a dtd represents the entire
       
  3518   doctypedecl production from the XML 1.0 specification.
       
  3519  */
       
  3520 void QXmlStreamWriter::writeDTD(const QString &dtd)
       
  3521 {
       
  3522     Q_D(QXmlStreamWriter);
       
  3523     d->finishStartElement();
       
  3524     if (d->autoFormatting)
       
  3525         d->write("\n");
       
  3526     d->write(dtd);
       
  3527     if (d->autoFormatting)
       
  3528         d->write("\n");
       
  3529 }
       
  3530 
       
  3531 
       
  3532 
       
  3533 /*!  \overload
       
  3534   Writes an empty element with qualified name \a qualifiedName.
       
  3535   Subsequent calls to writeAttribute() will add attributes to this element.
       
  3536 */
       
  3537 void QXmlStreamWriter::writeEmptyElement(const QString &qualifiedName)
       
  3538 {
       
  3539     Q_D(QXmlStreamWriter);
       
  3540     Q_ASSERT(qualifiedName.count(QLatin1Char(':')) <= 1);
       
  3541     d->writeStartElement(QString(), qualifiedName);
       
  3542     d->inEmptyElement = true;
       
  3543 }
       
  3544 
       
  3545 
       
  3546 /*!  Writes an empty element with \a name, prefixed for the specified
       
  3547   \a namespaceUri. If the namespace has not been declared,
       
  3548   QXmlStreamWriter will generate a namespace declaration for it.
       
  3549   Subsequent calls to writeAttribute() will add attributes to this element.
       
  3550 
       
  3551   \sa writeNamespace()
       
  3552  */
       
  3553 void QXmlStreamWriter::writeEmptyElement(const QString &namespaceUri, const QString &name)
       
  3554 {
       
  3555     Q_D(QXmlStreamWriter);
       
  3556     Q_ASSERT(!name.contains(QLatin1Char(':')));
       
  3557     d->writeStartElement(namespaceUri, name);
       
  3558     d->inEmptyElement = true;
       
  3559 }
       
  3560 
       
  3561 
       
  3562 /*!\overload
       
  3563   Writes a text element with \a qualifiedName and \a text.
       
  3564 
       
  3565 
       
  3566   This is a convenience function equivalent to:
       
  3567   \snippet doc/src/snippets/code/src_corelib_xml_qxmlstream.cpp 1
       
  3568 
       
  3569 */
       
  3570 void QXmlStreamWriter::writeTextElement(const QString &qualifiedName, const QString &text)
       
  3571 {
       
  3572     writeStartElement(qualifiedName);
       
  3573     writeCharacters(text);
       
  3574     writeEndElement();
       
  3575 }
       
  3576 
       
  3577 /*!  Writes a text element with \a name, prefixed for the specified \a
       
  3578      namespaceUri, and \a text. If the namespace has not been
       
  3579      declared, QXmlStreamWriter will generate a namespace declaration
       
  3580      for it.
       
  3581 
       
  3582 
       
  3583   This is a convenience function equivalent to:
       
  3584   \snippet doc/src/snippets/code/src_corelib_xml_qxmlstream.cpp 2
       
  3585 
       
  3586 */
       
  3587 void QXmlStreamWriter::writeTextElement(const QString &namespaceUri, const QString &name, const QString &text)
       
  3588 {
       
  3589     writeStartElement(namespaceUri, name);
       
  3590     writeCharacters(text);
       
  3591     writeEndElement();
       
  3592 }
       
  3593 
       
  3594 
       
  3595 /*!
       
  3596   Closes all remaining open start elements and writes a newline.
       
  3597 
       
  3598   \sa writeStartDocument()
       
  3599  */
       
  3600 void QXmlStreamWriter::writeEndDocument()
       
  3601 {
       
  3602     Q_D(QXmlStreamWriter);
       
  3603     while (d->tagStack.size())
       
  3604         writeEndElement();
       
  3605     d->write("\n");
       
  3606 }
       
  3607 
       
  3608 /*!
       
  3609   Closes the previous start element.
       
  3610 
       
  3611   \sa writeStartElement()
       
  3612  */
       
  3613 void QXmlStreamWriter::writeEndElement()
       
  3614 {
       
  3615     Q_D(QXmlStreamWriter);
       
  3616     if (d->tagStack.isEmpty())
       
  3617         return;
       
  3618 
       
  3619     // shortcut: if nothing was written, close as empty tag
       
  3620     if (d->inStartElement && !d->inEmptyElement) {
       
  3621         d->write("/>");
       
  3622         d->lastWasStartElement = d->inStartElement = false;
       
  3623         QXmlStreamWriterPrivate::Tag &tag = d->tagStack_pop();
       
  3624         d->lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
       
  3625         return;
       
  3626     }
       
  3627 
       
  3628     if (!d->finishStartElement(false) && !d->lastWasStartElement && d->autoFormatting)
       
  3629         d->indent(d->tagStack.size()-1);
       
  3630     if (d->tagStack.isEmpty())
       
  3631         return;
       
  3632     d->lastWasStartElement = false;
       
  3633     QXmlStreamWriterPrivate::Tag &tag = d->tagStack_pop();
       
  3634     d->lastNamespaceDeclaration = tag.namespaceDeclarationsSize;
       
  3635     d->write("</");
       
  3636     if (!tag.namespaceDeclaration.prefix.isEmpty()) {
       
  3637         d->write(tag.namespaceDeclaration.prefix);
       
  3638         d->write(":");
       
  3639     }
       
  3640     d->write(tag.name);
       
  3641     d->write(">");
       
  3642 }
       
  3643 
       
  3644 
       
  3645 
       
  3646 /*!
       
  3647   Writes the entity reference \a name to the stream, as "&\a{name};".
       
  3648  */
       
  3649 void QXmlStreamWriter::writeEntityReference(const QString &name)
       
  3650 {
       
  3651     Q_D(QXmlStreamWriter);
       
  3652     d->finishStartElement();
       
  3653     d->write("&");
       
  3654     d->write(name);
       
  3655     d->write(";");
       
  3656 }
       
  3657 
       
  3658 
       
  3659 /*!  Writes a namespace declaration for \a namespaceUri with \a
       
  3660   prefix. If \a prefix is empty, QXmlStreamWriter assigns a unique
       
  3661   prefix consisting of the letter 'n' followed by a number.
       
  3662 
       
  3663   If writeStartElement() or writeEmptyElement() was called, the
       
  3664   declaration applies to the current element; otherwise it applies to
       
  3665   the next child element.
       
  3666 
       
  3667   Note that the prefix \e xml is both predefined and reserved for
       
  3668   \e http://www.w3.org/XML/1998/namespace, which in turn cannot be
       
  3669   bound to any other prefix. The prefix \e xmlns and its URI
       
  3670   \e http://www.w3.org/2000/xmlns/ are used for the namespace mechanism
       
  3671   itself and thus completely forbidden in declarations.
       
  3672 
       
  3673  */
       
  3674 void QXmlStreamWriter::writeNamespace(const QString &namespaceUri, const QString &prefix)
       
  3675 {
       
  3676     Q_D(QXmlStreamWriter);
       
  3677     Q_ASSERT(!namespaceUri.isEmpty());
       
  3678     Q_ASSERT(prefix != QLatin1String("xmlns"));
       
  3679     if (prefix.isEmpty()) {
       
  3680         d->findNamespace(namespaceUri, d->inStartElement);
       
  3681     } else {
       
  3682         Q_ASSERT(!((prefix == QLatin1String("xml")) ^ (namespaceUri == QLatin1String("http://www.w3.org/XML/1998/namespace"))));
       
  3683         Q_ASSERT(namespaceUri != QLatin1String("http://www.w3.org/2000/xmlns/"));
       
  3684         QXmlStreamWriterPrivate::NamespaceDeclaration &namespaceDeclaration = d->namespaceDeclarations.push();
       
  3685         namespaceDeclaration.prefix = d->addToStringStorage(prefix);
       
  3686         namespaceDeclaration.namespaceUri = d->addToStringStorage(namespaceUri);
       
  3687         if (d->inStartElement)
       
  3688             d->writeNamespaceDeclaration(namespaceDeclaration);
       
  3689     }
       
  3690 }
       
  3691 
       
  3692 
       
  3693 /*! Writes a default namespace declaration for \a namespaceUri.
       
  3694 
       
  3695   If writeStartElement() or writeEmptyElement() was called, the
       
  3696   declaration applies to the current element; otherwise it applies to
       
  3697   the next child element.
       
  3698 
       
  3699   Note that the namespaces \e http://www.w3.org/XML/1998/namespace
       
  3700   (bound to \e xmlns) and \e http://www.w3.org/2000/xmlns/ (bound to
       
  3701   \e xml) by definition cannot be declared as default.
       
  3702  */
       
  3703 void QXmlStreamWriter::writeDefaultNamespace(const QString &namespaceUri)
       
  3704 {
       
  3705     Q_D(QXmlStreamWriter);
       
  3706     Q_ASSERT(namespaceUri != QLatin1String("http://www.w3.org/XML/1998/namespace"));
       
  3707     Q_ASSERT(namespaceUri != QLatin1String("http://www.w3.org/2000/xmlns/"));
       
  3708     QXmlStreamWriterPrivate::NamespaceDeclaration &namespaceDeclaration = d->namespaceDeclarations.push();
       
  3709     namespaceDeclaration.prefix.clear();
       
  3710     namespaceDeclaration.namespaceUri = d->addToStringStorage(namespaceUri);
       
  3711     if (d->inStartElement)
       
  3712         d->writeNamespaceDeclaration(namespaceDeclaration);
       
  3713 }
       
  3714 
       
  3715 
       
  3716 /*!
       
  3717   Writes an XML processing instruction with \a target and \a data,
       
  3718   where \a data must not contain the sequence "?>".
       
  3719  */
       
  3720 void QXmlStreamWriter::writeProcessingInstruction(const QString &target, const QString &data)
       
  3721 {
       
  3722     Q_D(QXmlStreamWriter);
       
  3723     Q_ASSERT(!data.contains(QLatin1String("?>")));
       
  3724     d->finishStartElement();
       
  3725     d->write("<?");
       
  3726     d->write(target);
       
  3727     if (!data.isNull()) {
       
  3728         d->write(" ");
       
  3729         d->write(data);
       
  3730     }
       
  3731     d->write("?>");
       
  3732 }
       
  3733 
       
  3734 
       
  3735 
       
  3736 /*!\overload
       
  3737 
       
  3738   Writes a document start with XML version number "1.0". This also
       
  3739   writes the encoding information.
       
  3740 
       
  3741   \sa writeEndDocument(), setCodec()
       
  3742   \since 4.5
       
  3743  */
       
  3744 void QXmlStreamWriter::writeStartDocument()
       
  3745 {
       
  3746     writeStartDocument(QLatin1String("1.0"));
       
  3747 }
       
  3748 
       
  3749 
       
  3750 /*!
       
  3751   Writes a document start with the XML version number \a version.
       
  3752 
       
  3753   \sa writeEndDocument()
       
  3754  */
       
  3755 void QXmlStreamWriter::writeStartDocument(const QString &version)
       
  3756 {
       
  3757     Q_D(QXmlStreamWriter);
       
  3758     d->finishStartElement(false);
       
  3759     d->write("<?xml version=\"");
       
  3760     d->write(version);
       
  3761     if (d->device) { // stringDevice does not get any encoding
       
  3762         d->write("\" encoding=\"");
       
  3763 #ifdef QT_NO_TEXTCODEC
       
  3764         d->write("iso-8859-1");
       
  3765 #else
       
  3766         d->write(d->codec->name().constData());
       
  3767 #endif
       
  3768     }
       
  3769     d->write("\"?>");
       
  3770 }
       
  3771 
       
  3772 /*!  Writes a document start with the XML version number \a version
       
  3773   and a standalone attribute \a standalone.
       
  3774 
       
  3775   \sa writeEndDocument()
       
  3776   \since 4.5
       
  3777  */
       
  3778 void QXmlStreamWriter::writeStartDocument(const QString &version, bool standalone)
       
  3779 {
       
  3780     Q_D(QXmlStreamWriter);
       
  3781     d->finishStartElement(false);
       
  3782     d->write("<?xml version=\"");
       
  3783     d->write(version);
       
  3784     if (d->device) { // stringDevice does not get any encoding
       
  3785         d->write("\" encoding=\"");
       
  3786 #ifdef QT_NO_TEXTCODEC
       
  3787         d->write("iso-8859-1");
       
  3788 #else
       
  3789         d->write(d->codec->name().constData());
       
  3790 #endif
       
  3791     }
       
  3792     d->write("\" standalone=\"");
       
  3793     d->write(standalone ? "yes" : "no");
       
  3794     d->write("\"?>");
       
  3795 }
       
  3796 
       
  3797 
       
  3798 /*!\overload
       
  3799 
       
  3800    Writes a start element with \a qualifiedName. Subsequent calls to
       
  3801    writeAttribute() will add attributes to this element.
       
  3802 
       
  3803    \sa writeEndElement(), writeEmptyElement()
       
  3804  */
       
  3805 void QXmlStreamWriter::writeStartElement(const QString &qualifiedName)
       
  3806 {
       
  3807     Q_D(QXmlStreamWriter);
       
  3808     Q_ASSERT(qualifiedName.count(QLatin1Char(':')) <= 1);
       
  3809     d->writeStartElement(QString(), qualifiedName);
       
  3810 }
       
  3811 
       
  3812 
       
  3813 /*!  Writes a start element with \a name, prefixed for the specified
       
  3814   \a namespaceUri. If the namespace has not been declared yet,
       
  3815   QXmlStreamWriter will generate a namespace declaration for
       
  3816   it. Subsequent calls to writeAttribute() will add attributes to this
       
  3817   element.
       
  3818 
       
  3819   \sa writeNamespace(), writeEndElement(), writeEmptyElement()
       
  3820  */
       
  3821 void QXmlStreamWriter::writeStartElement(const QString &namespaceUri, const QString &name)
       
  3822 {
       
  3823     Q_D(QXmlStreamWriter);
       
  3824     Q_ASSERT(!name.contains(QLatin1Char(':')));
       
  3825     d->writeStartElement(namespaceUri, name);
       
  3826 }
       
  3827 
       
  3828 void QXmlStreamWriterPrivate::writeStartElement(const QString &namespaceUri, const QString &name)
       
  3829 {
       
  3830     if (!finishStartElement(false) && autoFormatting)
       
  3831         indent(tagStack.size());
       
  3832 
       
  3833     Tag &tag = tagStack_push();
       
  3834     tag.name = addToStringStorage(name);
       
  3835     tag.namespaceDeclaration = findNamespace(namespaceUri);
       
  3836     write("<");
       
  3837     if (!tag.namespaceDeclaration.prefix.isEmpty()) {
       
  3838         write(tag.namespaceDeclaration.prefix);
       
  3839         write(":");
       
  3840     }
       
  3841     write(tag.name);
       
  3842     inStartElement = lastWasStartElement = true;
       
  3843 
       
  3844     for (int i = lastNamespaceDeclaration; i < namespaceDeclarations.size(); ++i)
       
  3845         writeNamespaceDeclaration(namespaceDeclarations[i]);
       
  3846     tag.namespaceDeclarationsSize = lastNamespaceDeclaration;
       
  3847 }
       
  3848 
       
  3849 #ifndef QT_NO_XMLSTREAMREADER
       
  3850 /*!  Writes the current state of the \a reader. All possible valid
       
  3851   states are supported.
       
  3852 
       
  3853   The purpose of this function is to support chained processing of XML data.
       
  3854 
       
  3855   \sa QXmlStreamReader::tokenType()
       
  3856  */
       
  3857 void QXmlStreamWriter::writeCurrentToken(const QXmlStreamReader &reader)
       
  3858 {
       
  3859     switch (reader.tokenType()) {
       
  3860     case QXmlStreamReader::NoToken:
       
  3861         break;
       
  3862     case QXmlStreamReader::StartDocument:
       
  3863         writeStartDocument();
       
  3864         break;
       
  3865     case QXmlStreamReader::EndDocument:
       
  3866         writeEndDocument();
       
  3867         break;
       
  3868     case QXmlStreamReader::StartElement: {
       
  3869         QXmlStreamNamespaceDeclarations namespaceDeclarations = reader.namespaceDeclarations();
       
  3870         for (int i = 0; i < namespaceDeclarations.size(); ++i) {
       
  3871             const QXmlStreamNamespaceDeclaration &namespaceDeclaration = namespaceDeclarations.at(i);
       
  3872             writeNamespace(namespaceDeclaration.namespaceUri().toString(),
       
  3873                            namespaceDeclaration.prefix().toString());
       
  3874         }
       
  3875         writeStartElement(reader.namespaceUri().toString(), reader.name().toString());
       
  3876         writeAttributes(reader.attributes());
       
  3877              } break;
       
  3878     case QXmlStreamReader::EndElement:
       
  3879         writeEndElement();
       
  3880         break;
       
  3881     case QXmlStreamReader::Characters:
       
  3882         if (reader.isCDATA())
       
  3883             writeCDATA(reader.text().toString());
       
  3884         else
       
  3885             writeCharacters(reader.text().toString());
       
  3886         break;
       
  3887     case QXmlStreamReader::Comment:
       
  3888         writeComment(reader.text().toString());
       
  3889         break;
       
  3890     case QXmlStreamReader::DTD:
       
  3891         writeDTD(reader.text().toString());
       
  3892         break;
       
  3893     case QXmlStreamReader::EntityReference:
       
  3894         writeEntityReference(reader.name().toString());
       
  3895         break;
       
  3896     case QXmlStreamReader::ProcessingInstruction:
       
  3897         writeProcessingInstruction(reader.processingInstructionTarget().toString(),
       
  3898                                    reader.processingInstructionData().toString());
       
  3899         break;
       
  3900     default:
       
  3901         Q_ASSERT(reader.tokenType() != QXmlStreamReader::Invalid);
       
  3902         qWarning("QXmlStreamWriter: writeCurrentToken() with invalid state.");
       
  3903         break;
       
  3904     }
       
  3905 }
       
  3906 
       
  3907 /*!
       
  3908  \fn bool QXmlStreamAttributes::hasAttribute(const QString &qualifiedName) const
       
  3909  \since 4.5
       
  3910 
       
  3911  Returns true if this QXmlStreamAttributes has an attribute whose
       
  3912  qualified name is \a qualifiedName; otherwise returns false.
       
  3913 
       
  3914  Note that this is not namespace aware. For instance, if this
       
  3915  QXmlStreamAttributes contains an attribute whose lexical name is "xlink:href"
       
  3916  this doesn't tell that an attribute named \c href in the XLink namespace is
       
  3917  present, since the \c xlink prefix can be bound to any namespace. Use the
       
  3918  overload that takes a namespace URI and a local name as parameter, for
       
  3919  namespace aware code.
       
  3920 */
       
  3921 
       
  3922 /*!
       
  3923  \fn bool QXmlStreamAttributes::hasAttribute(const QLatin1String &qualifiedName) const
       
  3924  \overload
       
  3925  \since 4.5
       
  3926 */
       
  3927 
       
  3928 /*!
       
  3929  \fn bool QXmlStreamAttributes::hasAttribute(const QString &namespaceUri,
       
  3930                                              const QString &name) const
       
  3931  \overload
       
  3932  \since 4.5
       
  3933 
       
  3934  Returns true if this QXmlStreamAttributes has an attribute whose
       
  3935  namespace URI and name correspond to \a namespaceUri and \a name;
       
  3936  otherwise returns false.
       
  3937 */
       
  3938 
       
  3939 #endif // QT_NO_XMLSTREAMREADER
       
  3940 #endif // QT_NO_XMLSTREAMWRITER
       
  3941 
       
  3942 QT_END_NAMESPACE
       
  3943 
       
  3944 #endif // QT_NO_XMLSTREAM