src/xml/sax/qxml.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
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 QtXml 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 "qxml.h"
       
    43 #include "qtextcodec.h"
       
    44 #include "qbuffer.h"
       
    45 #include "qregexp.h"
       
    46 #include "qmap.h"
       
    47 #include "qstack.h"
       
    48 #include <qdebug.h>
       
    49 
       
    50 
       
    51 #ifdef Q_CC_BOR // borland 6 finds bogus warnings when building this file in uic3
       
    52 #    pragma warn -8080
       
    53 #endif
       
    54 
       
    55 //#define QT_QXML_DEBUG
       
    56 
       
    57 // Error strings for the XML reader
       
    58 #define XMLERR_OK                         QT_TRANSLATE_NOOP("QXml", "no error occurred")
       
    59 #define XMLERR_ERRORBYCONSUMER            QT_TRANSLATE_NOOP("QXml", "error triggered by consumer")
       
    60 #define XMLERR_UNEXPECTEDEOF              QT_TRANSLATE_NOOP("QXml", "unexpected end of file")
       
    61 #define XMLERR_MORETHANONEDOCTYPE         QT_TRANSLATE_NOOP("QXml", "more than one document type definition")
       
    62 #define XMLERR_ERRORPARSINGELEMENT        QT_TRANSLATE_NOOP("QXml", "error occurred while parsing element")
       
    63 #define XMLERR_TAGMISMATCH                QT_TRANSLATE_NOOP("QXml", "tag mismatch")
       
    64 #define XMLERR_ERRORPARSINGCONTENT        QT_TRANSLATE_NOOP("QXml", "error occurred while parsing content")
       
    65 #define XMLERR_UNEXPECTEDCHARACTER        QT_TRANSLATE_NOOP("QXml", "unexpected character")
       
    66 #define XMLERR_INVALIDNAMEFORPI           QT_TRANSLATE_NOOP("QXml", "invalid name for processing instruction")
       
    67 #define XMLERR_VERSIONEXPECTED            QT_TRANSLATE_NOOP("QXml", "version expected while reading the XML declaration")
       
    68 #define XMLERR_WRONGVALUEFORSDECL         QT_TRANSLATE_NOOP("QXml", "wrong value for standalone declaration")
       
    69 #define XMLERR_EDECLORSDDECLEXPECTED      QT_TRANSLATE_NOOP("QXml", "encoding declaration or standalone declaration expected while reading the XML declaration")
       
    70 #define XMLERR_SDDECLEXPECTED             QT_TRANSLATE_NOOP("QXml", "standalone declaration expected while reading the XML declaration")
       
    71 #define XMLERR_ERRORPARSINGDOCTYPE        QT_TRANSLATE_NOOP("QXml", "error occurred while parsing document type definition")
       
    72 #define XMLERR_LETTEREXPECTED             QT_TRANSLATE_NOOP("QXml", "letter is expected")
       
    73 #define XMLERR_ERRORPARSINGCOMMENT        QT_TRANSLATE_NOOP("QXml", "error occurred while parsing comment")
       
    74 #define XMLERR_ERRORPARSINGREFERENCE      QT_TRANSLATE_NOOP("QXml", "error occurred while parsing reference")
       
    75 #define XMLERR_INTERNALGENERALENTITYINDTD QT_TRANSLATE_NOOP("QXml", "internal general entity reference not allowed in DTD")
       
    76 #define XMLERR_EXTERNALGENERALENTITYINAV  QT_TRANSLATE_NOOP("QXml", "external parsed general entity reference not allowed in attribute value")
       
    77 #define XMLERR_EXTERNALGENERALENTITYINDTD QT_TRANSLATE_NOOP("QXml", "external parsed general entity reference not allowed in DTD")
       
    78 #define XMLERR_UNPARSEDENTITYREFERENCE    QT_TRANSLATE_NOOP("QXml", "unparsed entity reference in wrong context")
       
    79 #define XMLERR_RECURSIVEENTITIES          QT_TRANSLATE_NOOP("QXml", "recursive entities")
       
    80 #define XMLERR_ERRORINTEXTDECL            QT_TRANSLATE_NOOP("QXml", "error in the text declaration of an external entity")
       
    81 
       
    82 QT_BEGIN_NAMESPACE
       
    83 
       
    84 // the constants for the lookup table
       
    85 static const signed char cltWS      =  0; // white space
       
    86 static const signed char cltPer     =  1; // %
       
    87 static const signed char cltAmp     =  2; // &
       
    88 static const signed char cltGt      =  3; // >
       
    89 static const signed char cltLt      =  4; // <
       
    90 static const signed char cltSlash   =  5; // /
       
    91 static const signed char cltQm      =  6; // ?
       
    92 static const signed char cltEm      =  7; // !
       
    93 static const signed char cltDash    =  8; // -
       
    94 static const signed char cltCB      =  9; // ]
       
    95 static const signed char cltOB      = 10; // [
       
    96 static const signed char cltEq      = 11; // =
       
    97 static const signed char cltDq      = 12; // "
       
    98 static const signed char cltSq      = 13; // '
       
    99 static const signed char cltUnknown = 14;
       
   100 
       
   101 // Hack for letting QDom know where the skipped entity occurred
       
   102 // ### Qt5: the use of this variable means the code isn't reentrant.
       
   103 bool qt_xml_skipped_entity_in_content;
       
   104 
       
   105 // character lookup table
       
   106 static const signed char charLookupTable[256]={
       
   107     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x00 - 0x07
       
   108     cltUnknown, // 0x08
       
   109     cltWS,      // 0x09 \t
       
   110     cltWS,      // 0x0A \n
       
   111     cltUnknown, // 0x0B
       
   112     cltUnknown, // 0x0C
       
   113     cltWS,      // 0x0D \r
       
   114     cltUnknown, // 0x0E
       
   115     cltUnknown, // 0x0F
       
   116     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x17 - 0x16
       
   117     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x18 - 0x1F
       
   118     cltWS,      // 0x20 Space
       
   119     cltEm,      // 0x21 !
       
   120     cltDq,      // 0x22 "
       
   121     cltUnknown, // 0x23
       
   122     cltUnknown, // 0x24
       
   123     cltPer,     // 0x25 %
       
   124     cltAmp,     // 0x26 &
       
   125     cltSq,      // 0x27 '
       
   126     cltUnknown, // 0x28
       
   127     cltUnknown, // 0x29
       
   128     cltUnknown, // 0x2A
       
   129     cltUnknown, // 0x2B
       
   130     cltUnknown, // 0x2C
       
   131     cltDash,    // 0x2D -
       
   132     cltUnknown, // 0x2E
       
   133     cltSlash,   // 0x2F /
       
   134     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x30 - 0x37
       
   135     cltUnknown, // 0x38
       
   136     cltUnknown, // 0x39
       
   137     cltUnknown, // 0x3A
       
   138     cltUnknown, // 0x3B
       
   139     cltLt,      // 0x3C <
       
   140     cltEq,      // 0x3D =
       
   141     cltGt,      // 0x3E >
       
   142     cltQm,      // 0x3F ?
       
   143     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x40 - 0x47
       
   144     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x48 - 0x4F
       
   145     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x50 - 0x57
       
   146     cltUnknown, // 0x58
       
   147     cltUnknown, // 0x59
       
   148     cltUnknown, // 0x5A
       
   149     cltOB,      // 0x5B [
       
   150     cltUnknown, // 0x5C
       
   151     cltCB,      // 0x5D]
       
   152     cltUnknown, // 0x5E
       
   153     cltUnknown, // 0x5F
       
   154     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x60 - 0x67
       
   155     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x68 - 0x6F
       
   156     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x70 - 0x77
       
   157     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x78 - 0x7F
       
   158     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x80 - 0x87
       
   159     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x88 - 0x8F
       
   160     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x90 - 0x97
       
   161     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x98 - 0x9F
       
   162     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xA0 - 0xA7
       
   163     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xA8 - 0xAF
       
   164     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xB0 - 0xB7
       
   165     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xB8 - 0xBF
       
   166     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xC0 - 0xC7
       
   167     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xC8 - 0xCF
       
   168     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xD0 - 0xD7
       
   169     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xD8 - 0xDF
       
   170     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xE0 - 0xE7
       
   171     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xE8 - 0xEF
       
   172     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xF0 - 0xF7
       
   173     cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown  // 0xF8 - 0xFF
       
   174 };
       
   175 
       
   176 //
       
   177 // local helper functions
       
   178 //
       
   179 
       
   180 /*
       
   181   This function strips the TextDecl [77] ("<?xml ...?>") from the string \a
       
   182   str. The stripped version is stored in \a str. If this function finds an
       
   183   invalid TextDecl, it returns false, otherwise true.
       
   184 
       
   185   This function is used for external entities since those can include an
       
   186   TextDecl that must be stripped before inserting the entity.
       
   187 */
       
   188 static bool stripTextDecl(QString& str)
       
   189 {
       
   190     QString textDeclStart(QLatin1String("<?xml"));
       
   191     if (str.startsWith(textDeclStart)) {
       
   192         QRegExp textDecl(QString::fromLatin1(
       
   193             "^<\\?xml\\s+"
       
   194             "(version\\s*=\\s*((['\"])[-a-zA-Z0-9_.:]+\\3))?"
       
   195             "\\s*"
       
   196             "(encoding\\s*=\\s*((['\"])[A-Za-z][-a-zA-Z0-9_.]*\\6))?"
       
   197             "\\s*\\?>"
       
   198        ));
       
   199         QString strTmp = str.replace(textDecl, QLatin1String(""));
       
   200         if (strTmp.length() != str.length())
       
   201             return false; // external entity has wrong TextDecl
       
   202         str = strTmp;
       
   203     }
       
   204     return true;
       
   205 }
       
   206 
       
   207 
       
   208 class QXmlAttributesPrivate
       
   209 {
       
   210 };
       
   211 
       
   212 /* \class QXmlInputSourcePrivate
       
   213     \internal
       
   214 
       
   215   There's a slight misdesign in this class that can
       
   216   be worth to keep in mind: the `str' member is
       
   217   a buffer which QXmlInputSource::next() returns from,
       
   218   and which is populated from the input device or input
       
   219   stream. However, when the input is a QString(the user called
       
   220   QXmlInputSource::setData()), `str' has two roles: it's the
       
   221   buffer, but also the source. This /seems/ to be no problem
       
   222   because in the case of having no device or stream, the QString
       
   223   is read in one go.
       
   224  */
       
   225 class QXmlInputSourcePrivate
       
   226 {
       
   227 public:
       
   228     QIODevice *inputDevice;
       
   229     QTextStream *inputStream;
       
   230 
       
   231     QString str;
       
   232     const QChar *unicode;
       
   233     int pos;
       
   234     int length;
       
   235     bool nextReturnedEndOfData;
       
   236 #ifndef QT_NO_TEXTCODEC
       
   237     QTextDecoder *encMapper;
       
   238 #endif
       
   239 
       
   240     QByteArray encodingDeclBytes;
       
   241     QString encodingDeclChars;
       
   242     bool lookingForEncodingDecl;
       
   243 };
       
   244 class QXmlParseExceptionPrivate
       
   245 {
       
   246 public:
       
   247     QXmlParseExceptionPrivate()
       
   248         : column(-1), line(-1)
       
   249     {
       
   250     }
       
   251     QXmlParseExceptionPrivate(const QXmlParseExceptionPrivate &other)
       
   252         : msg(other.msg), column(other.column), line(other.line),
       
   253           pub(other.pub), sys(other.sys)
       
   254     {
       
   255     }
       
   256 
       
   257     QString msg;
       
   258     int column;
       
   259     int line;
       
   260     QString pub;
       
   261     QString sys;
       
   262 
       
   263 };
       
   264 
       
   265 class QXmlLocatorPrivate
       
   266 {
       
   267 };
       
   268 
       
   269 class QXmlDefaultHandlerPrivate
       
   270 {
       
   271 };
       
   272 
       
   273 class QXmlSimpleReaderPrivate
       
   274 {
       
   275 public:
       
   276     ~QXmlSimpleReaderPrivate();
       
   277 private:
       
   278     // functions
       
   279     QXmlSimpleReaderPrivate(QXmlSimpleReader *reader);
       
   280     void initIncrementalParsing();
       
   281 
       
   282     // used to determine if elements are correctly nested
       
   283     QStack<QString> tags;
       
   284 
       
   285     // used by parseReference() and parsePEReference()
       
   286     enum EntityRecognitionContext { InContent, InAttributeValue, InEntityValue, InDTD };
       
   287 
       
   288     // used for entity declarations
       
   289     struct ExternParameterEntity
       
   290     {
       
   291         ExternParameterEntity() {}
       
   292         ExternParameterEntity(const QString &p, const QString &s)
       
   293             : publicId(p), systemId(s) {}
       
   294         QString publicId;
       
   295         QString systemId;
       
   296 
       
   297         Q_DUMMY_COMPARISON_OPERATOR(ExternParameterEntity)
       
   298     };
       
   299     struct ExternEntity
       
   300     {
       
   301         ExternEntity() {}
       
   302         ExternEntity(const QString &p, const QString &s, const QString &n)
       
   303             : publicId(p), systemId(s), notation(n) {}
       
   304         QString publicId;
       
   305         QString systemId;
       
   306         QString notation;
       
   307         Q_DUMMY_COMPARISON_OPERATOR(ExternEntity)
       
   308     };
       
   309     QMap<QString,ExternParameterEntity> externParameterEntities;
       
   310     QMap<QString,QString> parameterEntities;
       
   311     QMap<QString,ExternEntity> externEntities;
       
   312     QMap<QString,QString> entities;
       
   313 
       
   314     // used for parsing of entity references
       
   315     struct XmlRef {
       
   316         XmlRef()
       
   317             : index(0) {}
       
   318         XmlRef(const QString &_name, const QString &_value)
       
   319             : name(_name), value(_value), index(0) {}
       
   320         bool isEmpty() const { return index == value.length(); }
       
   321         QChar next() { return value.at(index++); }
       
   322         QString name;
       
   323         QString value;
       
   324         int index;
       
   325     };
       
   326     QStack<XmlRef> xmlRefStack;
       
   327 
       
   328     // used for standalone declaration
       
   329     enum Standalone { Yes, No, Unknown };
       
   330 
       
   331     QString doctype; // only used for the doctype
       
   332     QString xmlVersion; // only used to store the version information
       
   333     QString encoding; // only used to store the encoding
       
   334     Standalone standalone; // used to store the value of the standalone declaration
       
   335 
       
   336     QString publicId; // used by parseExternalID() to store the public ID
       
   337     QString systemId; // used by parseExternalID() to store the system ID
       
   338 
       
   339     // Since publicId/systemId is used as temporary variables by parseExternalID(), it
       
   340     // might overwrite the PUBLIC/SYSTEM for the document we're parsing. In effect, we would
       
   341     // possibly send off an QXmlParseException that has the PUBLIC/SYSTEM of a entity declaration
       
   342     // instead of those of the current document.
       
   343     // Hence we have these two variables for storing the document's data.
       
   344     QString thisPublicId;
       
   345     QString thisSystemId;
       
   346 
       
   347     QString attDeclEName; // use by parseAttlistDecl()
       
   348     QString attDeclAName; // use by parseAttlistDecl()
       
   349 
       
   350     // flags for some features support
       
   351     bool useNamespaces;
       
   352     bool useNamespacePrefixes;
       
   353     bool reportWhitespaceCharData;
       
   354     bool reportEntities;
       
   355 
       
   356     // used to build the attribute list
       
   357     QXmlAttributes attList;
       
   358 
       
   359     // used in QXmlSimpleReader::parseContent() to decide whether character
       
   360     // data was read
       
   361     bool contentCharDataRead;
       
   362 
       
   363     // helper classes
       
   364     QScopedPointer<QXmlLocator> locator;
       
   365     QXmlNamespaceSupport namespaceSupport;
       
   366 
       
   367     // error string
       
   368     QString error;
       
   369 
       
   370     // arguments for parse functions (this is needed to allow incremental
       
   371     // parsing)
       
   372     bool parsePI_xmldecl;
       
   373     bool parseName_useRef;
       
   374     bool parseReference_charDataRead;
       
   375     EntityRecognitionContext parseReference_context;
       
   376     bool parseExternalID_allowPublicID;
       
   377     EntityRecognitionContext parsePEReference_context;
       
   378     QString parseString_s;
       
   379 
       
   380     // for incremental parsing
       
   381     struct ParseState {
       
   382         typedef bool (QXmlSimpleReaderPrivate::*ParseFunction)();
       
   383         ParseFunction function;
       
   384         int state;
       
   385     };
       
   386     QStack<ParseState> *parseStack;
       
   387 
       
   388     // used in parseProlog()
       
   389     bool xmldecl_possible;
       
   390     bool doctype_read;
       
   391 
       
   392     // used in parseDoctype()
       
   393     bool startDTDwasReported;
       
   394 
       
   395     // used in parseString()
       
   396     signed char Done;
       
   397 
       
   398 
       
   399     // variables
       
   400     QXmlContentHandler *contentHnd;
       
   401     QXmlErrorHandler   *errorHnd;
       
   402     QXmlDTDHandler     *dtdHnd;
       
   403     QXmlEntityResolver *entityRes;
       
   404     QXmlLexicalHandler *lexicalHnd;
       
   405     QXmlDeclHandler    *declHnd;
       
   406 
       
   407     QXmlInputSource *inputSource;
       
   408 
       
   409     QChar c; // the character at reading position
       
   410     int   lineNr; // number of line
       
   411     int   columnNr; // position in line
       
   412 
       
   413     QChar   nameArray[256]; // only used for names
       
   414     QString nameValue; // only used for names
       
   415     int     nameArrayPos;
       
   416     int     nameValueLen;
       
   417     QChar   refArray[256]; // only used for references
       
   418     QString refValue; // only used for references
       
   419     int     refArrayPos;
       
   420     int     refValueLen;
       
   421     QChar   stringArray[256]; // used for any other strings that are parsed
       
   422     QString stringValue; // used for any other strings that are parsed
       
   423     int     stringArrayPos;
       
   424     int     stringValueLen;
       
   425     QString emptyStr;
       
   426 
       
   427     const QString &string();
       
   428     void stringClear();
       
   429     void stringAddC(QChar);
       
   430     inline void stringAddC() { stringAddC(c); }
       
   431     const QString &name();
       
   432     void nameClear();
       
   433     void nameAddC(QChar);
       
   434     inline void nameAddC() { nameAddC(c); }
       
   435     const QString &ref();
       
   436     void refClear();
       
   437     void refAddC(QChar);
       
   438     inline void refAddC() { refAddC(c); }
       
   439 
       
   440     // private functions
       
   441     bool eat_ws();
       
   442     bool next_eat_ws();
       
   443 
       
   444     void QT_FASTCALL next();
       
   445     bool atEnd();
       
   446 
       
   447     void init(const QXmlInputSource* i);
       
   448     void initData();
       
   449 
       
   450     bool entityExist(const QString&) const;
       
   451 
       
   452     bool parseBeginOrContinue(int state, bool incremental);
       
   453 
       
   454     bool parseProlog();
       
   455     bool parseElement();
       
   456     bool processElementEmptyTag();
       
   457     bool processElementETagBegin2();
       
   458     bool processElementAttribute();
       
   459     bool parseMisc();
       
   460     bool parseContent();
       
   461 
       
   462     bool parsePI();
       
   463     bool parseDoctype();
       
   464     bool parseComment();
       
   465 
       
   466     bool parseName();
       
   467     bool parseNmtoken();
       
   468     bool parseAttribute();
       
   469     bool parseReference();
       
   470     bool processReference();
       
   471 
       
   472     bool parseExternalID();
       
   473     bool parsePEReference();
       
   474     bool parseMarkupdecl();
       
   475     bool parseAttlistDecl();
       
   476     bool parseAttType();
       
   477     bool parseAttValue();
       
   478     bool parseElementDecl();
       
   479     bool parseNotationDecl();
       
   480     bool parseChoiceSeq();
       
   481     bool parseEntityDecl();
       
   482     bool parseEntityValue();
       
   483 
       
   484     bool parseString();
       
   485 
       
   486     bool insertXmlRef(const QString&, const QString&, bool);
       
   487 
       
   488     bool reportEndEntities();
       
   489     void reportParseError(const QString& error);
       
   490 
       
   491     typedef bool (QXmlSimpleReaderPrivate::*ParseFunction) ();
       
   492     void unexpectedEof(ParseFunction where, int state);
       
   493     void parseFailed(ParseFunction where, int state);
       
   494     void pushParseState(ParseFunction function, int state);
       
   495 
       
   496     Q_DECLARE_PUBLIC(QXmlSimpleReader)
       
   497     QXmlSimpleReader *q_ptr;
       
   498 
       
   499     friend class QXmlSimpleReaderLocator;
       
   500 };
       
   501 
       
   502 /*!
       
   503     \class QXmlParseException
       
   504     \reentrant
       
   505     \brief The QXmlParseException class is used to report errors with
       
   506     the QXmlErrorHandler interface.
       
   507 
       
   508     \inmodule QtXml
       
   509     \ingroup xml-tools
       
   510 
       
   511     The XML subsystem constructs an instance of this class when it
       
   512     detects an error. You can retrieve the place where the error
       
   513     occurred using systemId(), publicId(), lineNumber() and
       
   514     columnNumber(), along with the error message(). The possible error
       
   515     messages are:
       
   516 
       
   517 
       
   518     \list
       
   519         \o "no error occurred"
       
   520         \o "error triggered by consumer"
       
   521         \o "unexpected end of file"
       
   522         \o "more than one document type definition"
       
   523         \o "error occurred while parsing element"
       
   524         \o "tag mismatch"
       
   525         \o "error occurred while parsing content"
       
   526         \o "unexpected character"
       
   527         \o "invalid name for processing instruction"
       
   528         \o "version expected while reading the XML declaration"
       
   529         \o "wrong value for standalone declaration"
       
   530         \o "encoding declaration or standalone declaration expected while reading the XML declaration"
       
   531         \o "standalone declaration expected while reading the XML declaration"
       
   532         \o "error occurred while parsing document type definition"
       
   533         \o "letter is expected"
       
   534         \o "error occurred while parsing comment"
       
   535         \o "error occurred while parsing reference"
       
   536         \o "internal general entity reference not allowed in DTD"
       
   537         \o "external parsed general entity reference not allowed in attribute value"
       
   538         \o "external parsed general entity reference not allowed in DTD"
       
   539         \o "unparsed entity reference n wrong context"
       
   540         \o "recursive entities"
       
   541         \o "error in the text declaration of an external entity"
       
   542     \endlist
       
   543 
       
   544     Note that, if you want to display these error messages to your
       
   545     application's users, they will be displayed in English unless
       
   546     they are explicitly translated.
       
   547 
       
   548     \sa QXmlErrorHandler, QXmlReader
       
   549 */
       
   550 
       
   551 /*!
       
   552     Constructs a parse exception with the error string \a name for
       
   553     column \a c and line \a l for the public identifier \a p and the
       
   554     system identifier \a s.
       
   555 */
       
   556 
       
   557 QXmlParseException::QXmlParseException(const QString& name, int c, int l,
       
   558                                        const QString& p, const QString& s)
       
   559     : d(new QXmlParseExceptionPrivate)
       
   560 {
       
   561     d->msg = name;
       
   562     d->column = c;
       
   563     d->line = l;
       
   564     d->pub = p;
       
   565     d->sys = s;
       
   566 }
       
   567 
       
   568 /*!
       
   569     Creates a copy of \a other.
       
   570 */
       
   571 QXmlParseException::QXmlParseException(const QXmlParseException& other) :
       
   572      d(new QXmlParseExceptionPrivate(*other.d))
       
   573 {
       
   574 
       
   575 }
       
   576 
       
   577 /*!
       
   578     Destroys the QXmlParseException.
       
   579 */
       
   580 QXmlParseException::~QXmlParseException()
       
   581 {
       
   582 }
       
   583 
       
   584 /*!
       
   585     Returns the error message.
       
   586 */
       
   587 QString QXmlParseException::message() const
       
   588 {
       
   589     return d->msg;
       
   590 }
       
   591 /*!
       
   592     Returns the column number where the error occurred.
       
   593 */
       
   594 int QXmlParseException::columnNumber() const
       
   595 {
       
   596     return d->column;
       
   597 }
       
   598 /*!
       
   599     Returns the line number where the error occurred.
       
   600 */
       
   601 int QXmlParseException::lineNumber() const
       
   602 {
       
   603     return d->line;
       
   604 }
       
   605 /*!
       
   606     Returns the public identifier where the error occurred.
       
   607 */
       
   608 QString QXmlParseException::publicId() const
       
   609 {
       
   610     return d->pub;
       
   611 }
       
   612 /*!
       
   613     Returns the system identifier where the error occurred.
       
   614 */
       
   615 QString QXmlParseException::systemId() const
       
   616 {
       
   617     return d->sys;
       
   618 }
       
   619 
       
   620 
       
   621 /*!
       
   622     \class QXmlLocator
       
   623     \reentrant
       
   624     \brief The QXmlLocator class provides the XML handler classes with
       
   625     information about the parsing position within a file.
       
   626 
       
   627     \inmodule QtXml
       
   628     \ingroup xml-tools
       
   629 
       
   630     The reader reports a QXmlLocator to the content handler before it
       
   631     starts to parse the document. This is done with the
       
   632     QXmlContentHandler::setDocumentLocator() function. The handler
       
   633     classes can now use this locator to get the position (lineNumber()
       
   634     and columnNumber()) that the reader has reached.
       
   635 */
       
   636 
       
   637 /*!
       
   638     Constructor.
       
   639 */
       
   640 QXmlLocator::QXmlLocator()
       
   641 {
       
   642 }
       
   643 
       
   644 /*!
       
   645     Destructor.
       
   646 */
       
   647 QXmlLocator::~QXmlLocator()
       
   648 {
       
   649 }
       
   650 
       
   651 /*!
       
   652     \fn int QXmlLocator::columnNumber() const
       
   653 
       
   654     Returns the column number (starting at 1) or -1 if there is no
       
   655     column number available.
       
   656 */
       
   657 
       
   658 /*!
       
   659     \fn int QXmlLocator::lineNumber() const
       
   660 
       
   661     Returns the line number (starting at 1) or -1 if there is no line
       
   662     number available.
       
   663 */
       
   664 
       
   665 class QXmlSimpleReaderLocator : public QXmlLocator
       
   666 {
       
   667 public:
       
   668     QXmlSimpleReaderLocator(QXmlSimpleReader* parent)
       
   669     {
       
   670         reader = parent;
       
   671     }
       
   672     ~QXmlSimpleReaderLocator()
       
   673     {
       
   674     }
       
   675 
       
   676     int columnNumber() const
       
   677     {
       
   678         return (reader->d_ptr->columnNr == -1 ? -1 : reader->d_ptr->columnNr + 1);
       
   679     }
       
   680     int lineNumber() const
       
   681     {
       
   682         return (reader->d_ptr->lineNr == -1 ? -1 : reader->d_ptr->lineNr + 1);
       
   683     }
       
   684 //    QString getPublicId()
       
   685 //    QString getSystemId()
       
   686 
       
   687 private:
       
   688     QXmlSimpleReader *reader;
       
   689 };
       
   690 
       
   691 /*********************************************
       
   692  *
       
   693  * QXmlNamespaceSupport
       
   694  *
       
   695  *********************************************/
       
   696 
       
   697 typedef QMap<QString, QString> NamespaceMap;
       
   698 
       
   699 class QXmlNamespaceSupportPrivate
       
   700 {
       
   701 public:
       
   702     QXmlNamespaceSupportPrivate()
       
   703     {
       
   704         ns.insert(QLatin1String("xml"), QLatin1String("http://www.w3.org/XML/1998/namespace")); // the XML namespace
       
   705     }
       
   706 
       
   707     ~QXmlNamespaceSupportPrivate()
       
   708     {
       
   709     }
       
   710 
       
   711     QStack<NamespaceMap> nsStack;
       
   712     NamespaceMap ns;
       
   713 };
       
   714 
       
   715 /*!
       
   716     \class QXmlNamespaceSupport
       
   717     \since 4.4
       
   718     \reentrant
       
   719     \brief The QXmlNamespaceSupport class is a helper class for XML
       
   720     readers which want to include namespace support.
       
   721 
       
   722     \inmodule QtXml
       
   723     \ingroup xml-tools
       
   724 
       
   725     You can set the prefix for the current namespace with setPrefix(),
       
   726     and get the list of current prefixes (or those for a given URI)
       
   727     with prefixes(). The namespace URI is available from uri(). Use
       
   728     pushContext() to start a new namespace context, and popContext()
       
   729     to return to the previous namespace context. Use splitName() or
       
   730     processName() to split a name into its prefix and local name.
       
   731 
       
   732     \sa {Namespace Support via Features}
       
   733 */
       
   734 
       
   735 /*!
       
   736     Constructs a QXmlNamespaceSupport.
       
   737 */
       
   738 QXmlNamespaceSupport::QXmlNamespaceSupport()
       
   739 {
       
   740     d = new QXmlNamespaceSupportPrivate;
       
   741 }
       
   742 
       
   743 /*!
       
   744     Destroys a QXmlNamespaceSupport.
       
   745 */
       
   746 QXmlNamespaceSupport::~QXmlNamespaceSupport()
       
   747 {
       
   748     delete d;
       
   749 }
       
   750 
       
   751 /*!
       
   752     This function declares a prefix \a pre in the current namespace
       
   753     context to be the namespace URI \a uri. The prefix remains in
       
   754     force until this context is popped, unless it is shadowed in a
       
   755     descendant context.
       
   756 
       
   757     Note that there is an asymmetry in this library. prefix() does not
       
   758     return the default "" prefix, even if you have declared one; to
       
   759     check for a default prefix, you must look it up explicitly using
       
   760     uri(). This asymmetry exists to make it easier to look up prefixes
       
   761     for attribute names, where the default prefix is not allowed.
       
   762 */
       
   763 void QXmlNamespaceSupport::setPrefix(const QString& pre, const QString& uri)
       
   764 {
       
   765     if(pre.isNull()) {
       
   766         d->ns.insert(QLatin1String(""), uri);
       
   767     } else {
       
   768         d->ns.insert(pre, uri);
       
   769     }
       
   770 }
       
   771 
       
   772 /*!
       
   773     Returns one of the prefixes mapped to the namespace URI \a uri.
       
   774 
       
   775     If more than one prefix is currently mapped to the same URI, this
       
   776     function makes an arbitrary selection; if you want all of the
       
   777     prefixes, use prefixes() instead.
       
   778 
       
   779     Note: to check for a default prefix, use the uri() function with
       
   780     an argument of "".
       
   781 */
       
   782 QString QXmlNamespaceSupport::prefix(const QString& uri) const
       
   783 {
       
   784     NamespaceMap::const_iterator itc, it = d->ns.constBegin();
       
   785     while ((itc=it) != d->ns.constEnd()) {
       
   786         ++it;
       
   787         if (*itc == uri && !itc.key().isEmpty())
       
   788             return itc.key();
       
   789     }
       
   790     return QLatin1String("");
       
   791 }
       
   792 
       
   793 /*!
       
   794     Looks up the prefix \a prefix in the current context and returns
       
   795     the currently-mapped namespace URI. Use the empty string ("") for
       
   796     the default namespace.
       
   797 */
       
   798 QString QXmlNamespaceSupport::uri(const QString& prefix) const
       
   799 {
       
   800     return d->ns[prefix];
       
   801 }
       
   802 
       
   803 /*!
       
   804     Splits the name \a qname at the ':' and returns the prefix in \a
       
   805     prefix and the local name in \a localname.
       
   806 
       
   807     \sa processName()
       
   808 */
       
   809 void QXmlNamespaceSupport::splitName(const QString& qname, QString& prefix,
       
   810                                      QString& localname) const
       
   811 {
       
   812     int pos = qname.indexOf(QLatin1Char(':'));
       
   813     if (pos == -1)
       
   814         pos = qname.size();
       
   815 
       
   816     prefix = qname.left(pos);
       
   817     localname = qname.mid(pos+1);
       
   818 }
       
   819 
       
   820 /*!
       
   821     Processes a raw XML 1.0 name in the current context by removing
       
   822     the prefix and looking it up among the prefixes currently
       
   823     declared.
       
   824 
       
   825     \a qname is the raw XML 1.0 name to be processed. \a isAttribute
       
   826     is true if the name is an attribute name.
       
   827 
       
   828     This function stores the namespace URI in \a nsuri (which will be
       
   829     set to an empty string if the raw name has an undeclared prefix),
       
   830     and stores the local name (without prefix) in \a localname (which
       
   831     will be set to an empty string if no namespace is in use).
       
   832 
       
   833     Note that attribute names are processed differently than element
       
   834     names: an unprefixed element name gets the default namespace (if
       
   835     any), while an unprefixed attribute name does not.
       
   836 */
       
   837 void QXmlNamespaceSupport::processName(const QString& qname,
       
   838         bool isAttribute,
       
   839         QString& nsuri, QString& localname) const
       
   840 {
       
   841     int len = qname.size();
       
   842     const QChar *data = qname.constData();
       
   843     for (int pos = 0; pos < len; ++pos) {
       
   844         if (data[pos] == QLatin1Char(':')) {
       
   845             nsuri = uri(qname.left(pos));
       
   846             localname = qname.mid(pos + 1);
       
   847             return;
       
   848         }
       
   849     }
       
   850 
       
   851     // there was no ':'
       
   852     nsuri.clear();
       
   853     // attributes don't take default namespace
       
   854     if (!isAttribute && !d->ns.isEmpty()) {
       
   855 	/*
       
   856 	    We want to access d->ns.value(""), but as an optimization
       
   857 	    we use the fact that "" compares less than any other
       
   858 	    string, so it's either first in the map or not there.
       
   859 	*/
       
   860         NamespaceMap::const_iterator first = d->ns.constBegin();
       
   861         if (first.key().isEmpty())
       
   862             nsuri = first.value(); // get default namespace
       
   863     }
       
   864     localname = qname;
       
   865 }
       
   866 
       
   867 /*!
       
   868     Returns a list of all the prefixes currently declared.
       
   869 
       
   870     If there is a default prefix, this function does not return it in
       
   871     the list; check for the default prefix using uri() with an
       
   872     argument of "".
       
   873 */
       
   874 QStringList QXmlNamespaceSupport::prefixes() const
       
   875 {
       
   876     QStringList list;
       
   877 
       
   878     NamespaceMap::const_iterator itc, it = d->ns.constBegin();
       
   879     while ((itc=it) != d->ns.constEnd()) {
       
   880         ++it;
       
   881         if (!itc.key().isEmpty())
       
   882             list.append(itc.key());
       
   883     }
       
   884     return list;
       
   885 }
       
   886 
       
   887 /*!
       
   888     \overload
       
   889 
       
   890     Returns a list of all prefixes currently declared for the
       
   891     namespace URI \a uri.
       
   892 
       
   893     The "xml:" prefix is included. If you only want one prefix that is
       
   894     mapped to the namespace URI, and you don't care which one you get,
       
   895     use the prefix() function instead.
       
   896 
       
   897     Note: The empty (default) prefix is never included in this list;
       
   898     to check for the presence of a default namespace, call uri() with
       
   899     "" as the argument.
       
   900 */
       
   901 QStringList QXmlNamespaceSupport::prefixes(const QString& uri) const
       
   902 {
       
   903     QStringList list;
       
   904 
       
   905     NamespaceMap::const_iterator itc, it = d->ns.constBegin();
       
   906     while ((itc=it) != d->ns.constEnd()) {
       
   907         ++it;
       
   908         if (*itc == uri && !itc.key().isEmpty())
       
   909             list.append(itc.key());
       
   910     }
       
   911     return list;
       
   912 }
       
   913 
       
   914 /*!
       
   915     Starts a new namespace context.
       
   916 
       
   917     Normally, you should push a new context at the beginning of each
       
   918     XML element: the new context automatically inherits the
       
   919     declarations of its parent context, and it also keeps track of
       
   920     which declarations were made within this context.
       
   921 
       
   922     \sa popContext()
       
   923 */
       
   924 void QXmlNamespaceSupport::pushContext()
       
   925 {
       
   926     d->nsStack.push(d->ns);
       
   927 }
       
   928 
       
   929 /*!
       
   930     Reverts to the previous namespace context.
       
   931 
       
   932     Normally, you should pop the context at the end of each XML
       
   933     element. After popping the context, all namespace prefix mappings
       
   934     that were previously in force are restored.
       
   935 
       
   936     \sa pushContext()
       
   937 */
       
   938 void QXmlNamespaceSupport::popContext()
       
   939 {
       
   940     d->ns.clear();
       
   941     if(!d->nsStack.isEmpty())
       
   942         d->ns = d->nsStack.pop();
       
   943 }
       
   944 
       
   945 /*!
       
   946     Resets this namespace support object ready for reuse.
       
   947 */
       
   948 void QXmlNamespaceSupport::reset()
       
   949 {
       
   950     QXmlNamespaceSupportPrivate *newD = new QXmlNamespaceSupportPrivate;
       
   951     delete d;
       
   952     d = newD;
       
   953 }
       
   954 
       
   955 
       
   956 
       
   957 /*********************************************
       
   958  *
       
   959  * QXmlAttributes
       
   960  *
       
   961  *********************************************/
       
   962 
       
   963 /*!
       
   964     \class QXmlAttributes
       
   965     \reentrant
       
   966     \brief The QXmlAttributes class provides XML attributes.
       
   967 
       
   968     \inmodule QtXml
       
   969     \ingroup xml-tools
       
   970 
       
   971     If attributes are reported by QXmlContentHandler::startElement()
       
   972     this class is used to pass the attribute values.
       
   973 
       
   974     Use index() to locate the position of an attribute in the list,
       
   975     count() to retrieve the number of attributes, and clear() to
       
   976     remove the attributes. New attributes can be added with append().
       
   977     Use type() to get an attribute's type and value() to get its
       
   978     value. The attribute's name is available from localName() or
       
   979     qName(), and its namespace URI from uri().
       
   980 
       
   981 */
       
   982 
       
   983 /*!
       
   984     \fn QXmlAttributes::QXmlAttributes()
       
   985 
       
   986     Constructs an empty attribute list.
       
   987 */
       
   988 
       
   989 /*!
       
   990     \fn QXmlAttributes::~QXmlAttributes()
       
   991 
       
   992     Destroys the attributes object.
       
   993 */
       
   994 
       
   995 /*!
       
   996     Looks up the index of an attribute by the qualified name \a qName.
       
   997 
       
   998     Returns the index of the attribute or -1 if it wasn't found.
       
   999 
       
  1000     \sa {Namespace Support via Features}
       
  1001 */
       
  1002 int QXmlAttributes::index(const QString& qName) const
       
  1003 {
       
  1004     for (int i = 0; i < attList.size(); ++i) {
       
  1005         if (attList.at(i).qname == qName)
       
  1006             return i;
       
  1007     }
       
  1008     return -1;
       
  1009 }
       
  1010 
       
  1011 /*! \overload
       
  1012   */
       
  1013 int QXmlAttributes::index(const QLatin1String& qName) const
       
  1014 {
       
  1015     for (int i = 0; i < attList.size(); ++i) {
       
  1016         if (attList.at(i).qname == qName)
       
  1017             return i;
       
  1018     }
       
  1019     return -1;
       
  1020 }
       
  1021 
       
  1022 /*!
       
  1023     \overload
       
  1024 
       
  1025     Looks up the index of an attribute by a namespace name.
       
  1026 
       
  1027     \a uri specifies the namespace URI, or an empty string if the name
       
  1028     has no namespace URI. \a localPart specifies the attribute's local
       
  1029     name.
       
  1030 
       
  1031     Returns the index of the attribute, or -1 if it wasn't found.
       
  1032 
       
  1033     \sa {Namespace Support via Features}
       
  1034 */
       
  1035 int QXmlAttributes::index(const QString& uri, const QString& localPart) const
       
  1036 {
       
  1037     for (int i = 0; i < attList.size(); ++i) {
       
  1038         const Attribute &att = attList.at(i);
       
  1039         if (att.uri == uri && att.localname == localPart)
       
  1040             return i;
       
  1041     }
       
  1042     return -1;
       
  1043 }
       
  1044 
       
  1045 /*!
       
  1046     Returns the number of attributes in the list.
       
  1047 
       
  1048     \sa count()
       
  1049 */
       
  1050 int QXmlAttributes::length() const
       
  1051 {
       
  1052     return attList.count();
       
  1053 }
       
  1054 
       
  1055 /*!
       
  1056     \fn int QXmlAttributes::count() const
       
  1057 
       
  1058     Returns the number of attributes in the list. This function is
       
  1059     equivalent to length().
       
  1060 */
       
  1061 
       
  1062 /*!
       
  1063     Looks up an attribute's local name for the attribute at position
       
  1064     \a index. If no namespace processing is done, the local name is
       
  1065     an empty string.
       
  1066 
       
  1067     \sa {Namespace Support via Features}
       
  1068 */
       
  1069 QString QXmlAttributes::localName(int index) const
       
  1070 {
       
  1071     return attList.at(index).localname;
       
  1072 }
       
  1073 
       
  1074 /*!
       
  1075     Looks up an attribute's XML 1.0 qualified name for the attribute
       
  1076     at position \a index.
       
  1077 
       
  1078     \sa {Namespace Support via Features}
       
  1079 */
       
  1080 QString QXmlAttributes::qName(int index) const
       
  1081 {
       
  1082     return attList.at(index).qname;
       
  1083 }
       
  1084 
       
  1085 /*!
       
  1086     Looks up an attribute's namespace URI for the attribute at
       
  1087     position \a index. If no namespace processing is done or if the
       
  1088     attribute has no namespace, the namespace URI is an empty string.
       
  1089 
       
  1090     \sa {Namespace Support via Features}
       
  1091 */
       
  1092 QString QXmlAttributes::uri(int index) const
       
  1093 {
       
  1094     return attList.at(index).uri;
       
  1095 }
       
  1096 
       
  1097 /*!
       
  1098     Looks up an attribute's type for the attribute at position \a
       
  1099     index.
       
  1100 
       
  1101     Currently only "CDATA" is returned.
       
  1102 */
       
  1103 QString QXmlAttributes::type(int) const
       
  1104 {
       
  1105     return QLatin1String("CDATA");
       
  1106 }
       
  1107 
       
  1108 /*!
       
  1109     \overload
       
  1110 
       
  1111     Looks up an attribute's type for the qualified name \a qName.
       
  1112 
       
  1113     Currently only "CDATA" is returned.
       
  1114 */
       
  1115 QString QXmlAttributes::type(const QString&) const
       
  1116 {
       
  1117     return QLatin1String("CDATA");
       
  1118 }
       
  1119 
       
  1120 /*!
       
  1121     \overload
       
  1122 
       
  1123     Looks up an attribute's type by namespace name.
       
  1124 
       
  1125     \a uri specifies the namespace URI and \a localName specifies the
       
  1126     local name. If the name has no namespace URI, use an empty string
       
  1127     for \a uri.
       
  1128 
       
  1129     Currently only "CDATA" is returned.
       
  1130 */
       
  1131 QString QXmlAttributes::type(const QString&, const QString&) const
       
  1132 {
       
  1133     return QLatin1String("CDATA");
       
  1134 }
       
  1135 
       
  1136 /*!
       
  1137     Returns an attribute's value for the attribute at position \a
       
  1138     index. The index must be a valid position
       
  1139     (i.e., 0 <= \a index < count()).
       
  1140 */
       
  1141 QString QXmlAttributes::value(int index) const
       
  1142 {
       
  1143     return attList.at(index).value;
       
  1144 }
       
  1145 
       
  1146 /*!
       
  1147     \overload
       
  1148 
       
  1149     Returns an attribute's value for the qualified name \a qName, or an
       
  1150     empty string if no attribute exists for the name given.
       
  1151 
       
  1152     \sa {Namespace Support via Features}
       
  1153 */
       
  1154 QString QXmlAttributes::value(const QString& qName) const
       
  1155 {
       
  1156     int i = index(qName);
       
  1157     if (i == -1)
       
  1158         return QString();
       
  1159     return attList.at(i).value;
       
  1160 }
       
  1161 
       
  1162 /*!
       
  1163     \overload
       
  1164 
       
  1165     Returns an attribute's value for the qualified name \a qName, or an
       
  1166     empty string if no attribute exists for the name given.
       
  1167 
       
  1168     \sa {Namespace Support via Features}
       
  1169 */
       
  1170 QString QXmlAttributes::value(const QLatin1String& qName) const
       
  1171 {
       
  1172     int i = index(qName);
       
  1173     if (i == -1)
       
  1174         return QString();
       
  1175     return attList.at(i).value;
       
  1176 }
       
  1177 
       
  1178 /*!
       
  1179     \overload
       
  1180 
       
  1181     Returns an attribute's value by namespace name.
       
  1182 
       
  1183     \a uri specifies the namespace URI, or an empty string if the name
       
  1184     has no namespace URI. \a localName specifies the attribute's local
       
  1185     name.
       
  1186 */
       
  1187 QString QXmlAttributes::value(const QString& uri, const QString& localName) const
       
  1188 {
       
  1189     int i = index(uri, localName);
       
  1190     if (i == -1)
       
  1191         return QString();
       
  1192     return attList.at(i).value;
       
  1193 }
       
  1194 
       
  1195 /*!
       
  1196     Clears the list of attributes.
       
  1197 
       
  1198     \sa append()
       
  1199 */
       
  1200 void QXmlAttributes::clear()
       
  1201 {
       
  1202     attList.clear();
       
  1203 }
       
  1204 
       
  1205 /*!
       
  1206     Appends a new attribute entry to the list of attributes. The
       
  1207     qualified name of the attribute is \a qName, the namespace URI is
       
  1208     \a uri and the local name is \a localPart. The value of the
       
  1209     attribute is \a value.
       
  1210 
       
  1211     \sa qName() uri() localName() value()
       
  1212 */
       
  1213 void QXmlAttributes::append(const QString &qName, const QString &uri, const QString &localPart, const QString &value)
       
  1214 {
       
  1215     Attribute att;
       
  1216     att.qname = qName;
       
  1217     att.uri = uri;
       
  1218     att.localname = localPart;
       
  1219     att.value = value;
       
  1220 
       
  1221     attList.append(att);
       
  1222 }
       
  1223 
       
  1224 
       
  1225 /*********************************************
       
  1226  *
       
  1227  * QXmlInputSource
       
  1228  *
       
  1229  *********************************************/
       
  1230 
       
  1231 /*!
       
  1232     \class QXmlInputSource
       
  1233     \reentrant
       
  1234     \brief The QXmlInputSource class provides the input data for the
       
  1235     QXmlReader subclasses.
       
  1236 
       
  1237     \inmodule QtXml
       
  1238     \ingroup xml-tools
       
  1239 
       
  1240     All subclasses of QXmlReader read the input XML document from this
       
  1241     class.
       
  1242 
       
  1243     This class recognizes the encoding of the data by reading the
       
  1244     encoding declaration in the XML file if it finds one, and reading
       
  1245     the data using the corresponding encoding. If it does not find an
       
  1246     encoding declaration, then it assumes that the data is either in
       
  1247     UTF-8 or UTF-16, depending on whether it can find a byte-order
       
  1248     mark.
       
  1249 
       
  1250     There are two ways to populate the input source with data: you can
       
  1251     construct it with a QIODevice* so that the input source reads the
       
  1252     data from that device. Or you can set the data explicitly with one
       
  1253     of the setData() functions.
       
  1254 
       
  1255     Usually you either construct a QXmlInputSource that works on a
       
  1256     QIODevice* or you construct an empty QXmlInputSource and set the
       
  1257     data with setData(). There are only rare occasions where you would
       
  1258     want to mix both methods.
       
  1259 
       
  1260     The QXmlReader subclasses use the next() function to read the
       
  1261     input character by character. If you want to start from the
       
  1262     beginning again, use reset().
       
  1263 
       
  1264     The functions data() and fetchData() are useful if you want to do
       
  1265     something with the data other than parsing, e.g. displaying the
       
  1266     raw XML file. The benefit of using the QXmlInputClass in such
       
  1267     cases is that it tries to use the correct encoding.
       
  1268 
       
  1269     \sa QXmlReader QXmlSimpleReader
       
  1270 */
       
  1271 
       
  1272 // the following two are guaranteed not to be a character
       
  1273 const ushort QXmlInputSource::EndOfData = 0xfffe;
       
  1274 const ushort QXmlInputSource::EndOfDocument = 0xffff;
       
  1275 
       
  1276 /*
       
  1277     Common part of the constructors.
       
  1278 */
       
  1279 void QXmlInputSource::init()
       
  1280 {
       
  1281     d = new QXmlInputSourcePrivate;
       
  1282 
       
  1283     QT_TRY {
       
  1284         d->inputDevice = 0;
       
  1285         d->inputStream = 0;
       
  1286 
       
  1287         setData(QString());
       
  1288 #ifndef QT_NO_TEXTCODEC
       
  1289         d->encMapper = 0;
       
  1290 #endif
       
  1291         d->nextReturnedEndOfData = true; // first call to next() will call fetchData()
       
  1292 
       
  1293         d->encodingDeclBytes.clear();
       
  1294         d->encodingDeclChars.clear();
       
  1295         d->lookingForEncodingDecl = true;
       
  1296     } QT_CATCH(...) {
       
  1297         delete(d);
       
  1298         QT_RETHROW;
       
  1299     }
       
  1300 }
       
  1301 
       
  1302 /*!
       
  1303     Constructs an input source which contains no data.
       
  1304 
       
  1305     \sa setData()
       
  1306 */
       
  1307 QXmlInputSource::QXmlInputSource()
       
  1308 {
       
  1309     init();
       
  1310 }
       
  1311 
       
  1312 /*!
       
  1313     Constructs an input source and gets the data from device \a dev.
       
  1314     If \a dev is not open, it is opened in read-only mode. If \a dev
       
  1315     is 0 or it is not possible to read from the device, the input
       
  1316     source will contain no data.
       
  1317 
       
  1318     \sa setData() fetchData() QIODevice
       
  1319 */
       
  1320 QXmlInputSource::QXmlInputSource(QIODevice *dev)
       
  1321 {
       
  1322     init();
       
  1323     d->inputDevice = dev;
       
  1324     d->inputDevice->setTextModeEnabled(false);
       
  1325 }
       
  1326 
       
  1327 #ifdef QT3_SUPPORT
       
  1328 /*!
       
  1329     Use the QXmlInputSource(QIODevice *) constructor instead, with
       
  1330     the device used by \a stream.
       
  1331 
       
  1332     \sa QTextStream::device()
       
  1333 */
       
  1334 QXmlInputSource::QXmlInputSource(QTextStream& stream)
       
  1335 {
       
  1336     init();
       
  1337     d->inputStream = &stream;
       
  1338 }
       
  1339 
       
  1340 /*!
       
  1341     Use QXmlInputSource(&\a file) instead.
       
  1342 */
       
  1343 QXmlInputSource::QXmlInputSource(QFile& file)
       
  1344 {
       
  1345     init();
       
  1346     d->inputDevice = &file;
       
  1347 }
       
  1348 #endif
       
  1349 
       
  1350 /*!
       
  1351     Destructor.
       
  1352 */
       
  1353 QXmlInputSource::~QXmlInputSource()
       
  1354 {
       
  1355     // ### Qt 5: close the input device. See task 153111
       
  1356 #ifndef QT_NO_TEXTCODEC
       
  1357     delete d->encMapper;
       
  1358 #endif
       
  1359     delete d;
       
  1360 }
       
  1361 
       
  1362 /*!
       
  1363 Returns the next character of the input source. If this function
       
  1364 reaches the end of available data, it returns
       
  1365 QXmlInputSource::EndOfData. If you call next() after that, it
       
  1366 tries to fetch more data by calling fetchData(). If the
       
  1367 fetchData() call results in new data, this function returns the
       
  1368 first character of that data; otherwise it returns
       
  1369 QXmlInputSource::EndOfDocument.
       
  1370 
       
  1371 Readers, such as QXmlSimpleReader, will assume that the end of
       
  1372 the XML document has been reached if the this function returns
       
  1373 QXmlInputSource::EndOfDocument, and will check that the
       
  1374 supplied input is well-formed. Therefore, when reimplementing
       
  1375 this function, it is important to ensure that this behavior is
       
  1376 duplicated.
       
  1377 
       
  1378 \sa reset() fetchData() QXmlSimpleReader::parse() QXmlSimpleReader::parseContinue()
       
  1379 */
       
  1380 QChar QXmlInputSource::next()
       
  1381 {
       
  1382     if (d->pos >= d->length) {
       
  1383         if (d->nextReturnedEndOfData) {
       
  1384             d->nextReturnedEndOfData = false;
       
  1385             fetchData();
       
  1386             if (d->pos >= d->length) {
       
  1387                 return EndOfDocument;
       
  1388             }
       
  1389             return next();
       
  1390         }
       
  1391         d->nextReturnedEndOfData = true;
       
  1392         return EndOfData;
       
  1393     }
       
  1394 
       
  1395     // QXmlInputSource has no way to signal encoding errors. The best we can do
       
  1396     // is return EndOfDocument. We do *not* return EndOfData, because the reader
       
  1397     // will then just call this function again to get the next char.
       
  1398     QChar c = d->unicode[d->pos++];
       
  1399     if (c.unicode() == EndOfData)
       
  1400         c = EndOfDocument;
       
  1401     return c;
       
  1402 }
       
  1403 
       
  1404 /*!
       
  1405     This function sets the position used by next() to the beginning of
       
  1406     the data returned by data(). This is useful if you want to use the
       
  1407     input source for more than one parse.
       
  1408 
       
  1409     \note In the case that the underlying data source is a QIODevice,
       
  1410     the current position in the device is not automatically set to the
       
  1411     start of input. Call QIODevice::seek(0) on the device to do this.
       
  1412 
       
  1413     \sa next()
       
  1414 */
       
  1415 void QXmlInputSource::reset()
       
  1416 {
       
  1417     d->nextReturnedEndOfData = false;
       
  1418     d->pos = 0;
       
  1419 }
       
  1420 
       
  1421 /*!
       
  1422     Returns the data the input source contains or an empty string if the
       
  1423     input source does not contain any data.
       
  1424 
       
  1425     \sa setData() QXmlInputSource() fetchData()
       
  1426 */
       
  1427 QString QXmlInputSource::data() const
       
  1428 {
       
  1429     if (d->nextReturnedEndOfData) {
       
  1430         QXmlInputSource *that = const_cast<QXmlInputSource*>(this);
       
  1431         that->d->nextReturnedEndOfData = false;
       
  1432         that->fetchData();
       
  1433     }
       
  1434     return d->str;
       
  1435 }
       
  1436 
       
  1437 /*!
       
  1438     Sets the data of the input source to \a dat.
       
  1439 
       
  1440     If the input source already contains data, this function deletes
       
  1441     that data first.
       
  1442 
       
  1443     \sa data()
       
  1444 */
       
  1445 void QXmlInputSource::setData(const QString& dat)
       
  1446 {
       
  1447     d->str = dat;
       
  1448     d->unicode = dat.unicode();
       
  1449     d->pos = 0;
       
  1450     d->length = d->str.length();
       
  1451     d->nextReturnedEndOfData = false;
       
  1452 }
       
  1453 
       
  1454 /*!
       
  1455     \overload
       
  1456 
       
  1457     The data \a dat is passed through the correct text-codec, before
       
  1458     it is set.
       
  1459 */
       
  1460 void QXmlInputSource::setData(const QByteArray& dat)
       
  1461 {
       
  1462     setData(fromRawData(dat));
       
  1463 }
       
  1464 
       
  1465 /*!
       
  1466     This function reads more data from the device that was set during
       
  1467     construction. If the input source already contained data, this
       
  1468     function deletes that data first.
       
  1469 
       
  1470     This object contains no data after a call to this function if the
       
  1471     object was constructed without a device to read data from or if
       
  1472     this function was not able to get more data from the device.
       
  1473 
       
  1474     There are two occasions where a fetch is done implicitly by
       
  1475     another function call: during construction (so that the object
       
  1476     starts out with some initial data where available), and during a
       
  1477     call to next() (if the data had run out).
       
  1478 
       
  1479     You don't normally need to use this function if you use next().
       
  1480 
       
  1481     \sa data() next() QXmlInputSource()
       
  1482 */
       
  1483 
       
  1484 void QXmlInputSource::fetchData()
       
  1485 {
       
  1486     enum
       
  1487     {
       
  1488         BufferSize = 1024
       
  1489     };
       
  1490 
       
  1491     QByteArray rawData;
       
  1492 
       
  1493     if (d->inputDevice || d->inputStream) {
       
  1494         QIODevice *device = d->inputDevice ? d->inputDevice : d->inputStream->device();
       
  1495 
       
  1496         if (!device) {
       
  1497             if (d->inputStream && d->inputStream->string()) {
       
  1498                 QString *s = d->inputStream->string();
       
  1499                 rawData = QByteArray((const char *) s->constData(), s->size() * sizeof(QChar));
       
  1500             }
       
  1501         } else if (device->isOpen() || device->open(QIODevice::ReadOnly)) {
       
  1502             rawData.resize(BufferSize);
       
  1503             qint64 size = device->read(rawData.data(), BufferSize);
       
  1504 
       
  1505             if (size != -1) {
       
  1506                 // We don't want to give fromRawData() less than four bytes if we can avoid it.
       
  1507                 while (size < 4) {
       
  1508                     if (!device->waitForReadyRead(-1))
       
  1509                         break;
       
  1510                     int ret = device->read(rawData.data() + size, BufferSize - size);
       
  1511                     if (ret <= 0)
       
  1512                         break;
       
  1513                     size += ret;
       
  1514                 }
       
  1515             }
       
  1516 
       
  1517             rawData.resize(qMax(qint64(0), size));
       
  1518         }
       
  1519 
       
  1520         /* We do this inside the "if (d->inputDevice ..." scope
       
  1521          * because if we're not using a stream or device, that is,
       
  1522          * the user set a QString manually, we don't want to set
       
  1523          * d->str. */
       
  1524         setData(fromRawData(rawData));
       
  1525     }
       
  1526 }
       
  1527 
       
  1528 #ifndef QT_NO_TEXTCODEC
       
  1529 static QString extractEncodingDecl(const QString &text, bool *needMoreText)
       
  1530 {
       
  1531     *needMoreText = false;
       
  1532 
       
  1533     int l = text.length();
       
  1534     QString snip = QString::fromLatin1("<?xml").left(l);
       
  1535     if (l > 0 && !text.startsWith(snip))
       
  1536         return QString();
       
  1537 
       
  1538     int endPos = text.indexOf(QLatin1Char('>'));
       
  1539     if (endPos == -1) {
       
  1540         *needMoreText = l < 255; // we won't look forever
       
  1541         return QString();
       
  1542     }
       
  1543 
       
  1544     int pos = text.indexOf(QLatin1String("encoding"));
       
  1545     if (pos == -1 || pos >= endPos)
       
  1546         return QString();
       
  1547 
       
  1548     while (pos < endPos) {
       
  1549         ushort uc = text.at(pos).unicode();
       
  1550         if (uc == '\'' || uc == '"')
       
  1551             break;
       
  1552         ++pos;
       
  1553     }
       
  1554 
       
  1555     if (pos == endPos)
       
  1556         return QString();
       
  1557 
       
  1558     QString encoding;
       
  1559     ++pos;
       
  1560     while (pos < endPos) {
       
  1561         ushort uc = text.at(pos).unicode();
       
  1562         if (uc == '\'' || uc == '"')
       
  1563             break;
       
  1564         encoding.append(uc);
       
  1565         ++pos;
       
  1566     }
       
  1567 
       
  1568     return encoding;
       
  1569 }
       
  1570 #endif // QT_NO_TEXTCODEC
       
  1571 
       
  1572 /*!
       
  1573     This function reads the XML file from \a data and tries to
       
  1574     recognize the encoding. It converts the raw data \a data into a
       
  1575     QString and returns it. It tries its best to get the correct
       
  1576     encoding for the XML file.
       
  1577 
       
  1578     If \a beginning is true, this function assumes that the data
       
  1579     starts at the beginning of a new XML document and looks for an
       
  1580     encoding declaration. If \a beginning is false, it converts the
       
  1581     raw data using the encoding determined from prior calls.
       
  1582 */
       
  1583 QString QXmlInputSource::fromRawData(const QByteArray &data, bool beginning)
       
  1584 {
       
  1585 #ifdef QT_NO_TEXTCODEC
       
  1586     Q_UNUSED(beginning);
       
  1587     return QString::fromAscii(data.constData(), data.size());
       
  1588 #else
       
  1589     if (data.size() == 0)
       
  1590         return QString();
       
  1591     if (beginning) {
       
  1592         delete d->encMapper;
       
  1593         d->encMapper = 0;
       
  1594     }
       
  1595 
       
  1596     int mib = 106; // UTF-8
       
  1597 
       
  1598     // This is the initial UTF codec we will read the encoding declaration with
       
  1599     if (d->encMapper == 0) {
       
  1600         d->encodingDeclBytes.clear();
       
  1601         d->encodingDeclChars.clear();
       
  1602         d->lookingForEncodingDecl = true;
       
  1603 
       
  1604         // look for byte order mark and read the first 5 characters
       
  1605         if (data.size() >= 4) {
       
  1606             uchar ch1 = data.at(0);
       
  1607             uchar ch2 = data.at(1);
       
  1608             uchar ch3 = data.at(2);
       
  1609             uchar ch4 = data.at(3);
       
  1610 
       
  1611             if ((ch1 == 0 && ch2 == 0 && ch3 == 0xfe && ch4 == 0xff) ||
       
  1612                 (ch1 == 0xff && ch2 == 0xfe && ch3 == 0 && ch4 == 0))
       
  1613                 mib = 1017; // UTF-32 with byte order mark
       
  1614             else if (ch1 == 0x3c && ch2 == 0x00 && ch3 == 0x00 && ch4 == 0x00)
       
  1615                 mib = 1019; // UTF-32LE
       
  1616             else if (ch1 == 0x00 && ch2 == 0x00 && ch3 == 0x00 && ch4 == 0x3c)
       
  1617                 mib = 1018; // UTF-32BE
       
  1618         }
       
  1619         if (mib == 106 && data.size() >= 2) {
       
  1620             uchar ch1 = data.at(0);
       
  1621             uchar ch2 = data.at(1);
       
  1622 
       
  1623             if ((ch1 == 0xfe && ch2 == 0xff) || (ch1 == 0xff && ch2 == 0xfe))
       
  1624                 mib = 1015; // UTF-16 with byte order mark
       
  1625             else if (ch1 == 0x3c && ch2 == 0x00)
       
  1626                 mib = 1014; // UTF-16LE
       
  1627             else if (ch1 == 0x00 && ch2 == 0x3c)
       
  1628                 mib = 1013; // UTF-16BE
       
  1629         }
       
  1630 
       
  1631         QTextCodec *codec = QTextCodec::codecForMib(mib);
       
  1632         Q_ASSERT(codec);
       
  1633 
       
  1634         d->encMapper = codec->makeDecoder();
       
  1635     }
       
  1636 
       
  1637     QString input = d->encMapper->toUnicode(data, data.size());
       
  1638 
       
  1639     if (d->lookingForEncodingDecl) {
       
  1640         d->encodingDeclChars += input;
       
  1641 
       
  1642         bool needMoreText;
       
  1643         QString encoding = extractEncodingDecl(d->encodingDeclChars, &needMoreText);
       
  1644 
       
  1645         if (!encoding.isEmpty()) {
       
  1646             if (QTextCodec *codec = QTextCodec::codecForName(encoding.toLatin1())) {
       
  1647                 /* If the encoding is the same, we don't have to do toUnicode() all over again. */
       
  1648                 if(codec->mibEnum() != mib) {
       
  1649                     delete d->encMapper;
       
  1650                     d->encMapper = codec->makeDecoder();
       
  1651 
       
  1652                     /* The variable input can potentially be large, so we deallocate
       
  1653                      * it before calling toUnicode() in order to avoid having two
       
  1654                      * large QStrings in memory simultaneously. */
       
  1655                     input.clear();
       
  1656 
       
  1657                     // prime the decoder with the data so far
       
  1658                     d->encMapper->toUnicode(d->encodingDeclBytes, d->encodingDeclBytes.size());
       
  1659                     // now feed it the new data
       
  1660                     input = d->encMapper->toUnicode(data, data.size());
       
  1661                 }
       
  1662             }
       
  1663         }
       
  1664 
       
  1665         d->encodingDeclBytes += data;
       
  1666         d->lookingForEncodingDecl = needMoreText;
       
  1667     }
       
  1668 
       
  1669     return input;
       
  1670 #endif
       
  1671 }
       
  1672 
       
  1673 
       
  1674 /*********************************************
       
  1675  *
       
  1676  * QXmlDefaultHandler
       
  1677  *
       
  1678  *********************************************/
       
  1679 
       
  1680 /*!
       
  1681     \class QXmlContentHandler
       
  1682     \reentrant
       
  1683     \brief The QXmlContentHandler class provides an interface to
       
  1684     report the logical content of XML data.
       
  1685 
       
  1686     \inmodule QtXml
       
  1687     \ingroup xml-tools
       
  1688 
       
  1689     If the application needs to be informed of basic parsing events,
       
  1690     it can implement this interface and activate it using
       
  1691     QXmlReader::setContentHandler(). The reader can then report basic
       
  1692     document-related events like the start and end of elements and
       
  1693     character data through this interface.
       
  1694 
       
  1695     The order of events in this interface is very important, and
       
  1696     mirrors the order of information in the document itself. For
       
  1697     example, all of an element's content (character data, processing
       
  1698     instructions, and sub-elements) appears, in order, between the
       
  1699     startElement() event and the corresponding endElement() event.
       
  1700 
       
  1701     The class QXmlDefaultHandler provides a default implementation for
       
  1702     this interface; subclassing from the QXmlDefaultHandler class is
       
  1703     very convenient if you only want to be informed of some parsing
       
  1704     events.
       
  1705 
       
  1706     The startDocument() function is called at the start of the
       
  1707     document, and endDocument() is called at the end. Before parsing
       
  1708     begins setDocumentLocator() is called. For each element
       
  1709     startElement() is called, with endElement() being called at the
       
  1710     end of each element. The characters() function is called with
       
  1711     chunks of character data; ignorableWhitespace() is called with
       
  1712     chunks of whitespace and processingInstruction() is called with
       
  1713     processing instructions. If an entity is skipped skippedEntity()
       
  1714     is called. At the beginning of prefix-URI scopes
       
  1715     startPrefixMapping() is called.
       
  1716 
       
  1717     \sa QXmlDTDHandler, QXmlDeclHandler, QXmlEntityResolver, QXmlErrorHandler,
       
  1718         QXmlLexicalHandler, {Introduction to SAX2}
       
  1719 */
       
  1720 
       
  1721 /*!
       
  1722     \fn QXmlContentHandler::~QXmlContentHandler()
       
  1723 
       
  1724     Destroys the content handler.
       
  1725 */
       
  1726 
       
  1727 /*!
       
  1728     \fn void QXmlContentHandler::setDocumentLocator(QXmlLocator* locator)
       
  1729 
       
  1730     The reader calls this function before it starts parsing the
       
  1731     document. The argument \a locator is a pointer to a QXmlLocator
       
  1732     which allows the application to get the parsing position within
       
  1733     the document.
       
  1734 
       
  1735     Do not destroy the \a locator; it is destroyed when the reader is
       
  1736     destroyed. (Do not use the \a locator after the reader is
       
  1737     destroyed).
       
  1738 */
       
  1739 
       
  1740 /*!
       
  1741     \fn bool QXmlContentHandler::startDocument()
       
  1742 
       
  1743     The reader calls this function when it starts parsing the
       
  1744     document. The reader calls this function just once, after the call
       
  1745     to setDocumentLocator(), and before any other functions in this
       
  1746     class or in the QXmlDTDHandler class are called.
       
  1747 
       
  1748     If this function returns false the reader stops parsing and
       
  1749     reports an error. The reader uses the function errorString() to
       
  1750     get the error message.
       
  1751 
       
  1752     \sa endDocument()
       
  1753 */
       
  1754 
       
  1755 /*!
       
  1756     \fn bool QXmlContentHandler::endDocument()
       
  1757 
       
  1758     The reader calls this function after it has finished parsing. It
       
  1759     is called just once, and is the last handler function called. It
       
  1760     is called after the reader has read all input or has abandoned
       
  1761     parsing because of a fatal error.
       
  1762 
       
  1763     If this function returns false the reader stops parsing and
       
  1764     reports an error. The reader uses the function errorString() to
       
  1765     get the error message.
       
  1766 
       
  1767     \sa startDocument()
       
  1768 */
       
  1769 
       
  1770 /*!
       
  1771     \fn bool QXmlContentHandler::startPrefixMapping(const QString& prefix, const QString& uri)
       
  1772 
       
  1773     The reader calls this function to signal the begin of a prefix-URI
       
  1774     namespace mapping scope. This information is not necessary for
       
  1775     normal namespace processing since the reader automatically
       
  1776     replaces prefixes for element and attribute names.
       
  1777 
       
  1778     Note that startPrefixMapping() and endPrefixMapping() calls are
       
  1779     not guaranteed to be properly nested relative to each other: all
       
  1780     startPrefixMapping() events occur before the corresponding
       
  1781     startElement() event, and all endPrefixMapping() events occur
       
  1782     after the corresponding endElement() event, but their order is not
       
  1783     otherwise guaranteed.
       
  1784 
       
  1785     The argument \a prefix is the namespace prefix being declared and
       
  1786     the argument \a uri is the namespace URI the prefix is mapped to.
       
  1787 
       
  1788     If this function returns false the reader stops parsing and
       
  1789     reports an error. The reader uses the function errorString() to
       
  1790     get the error message.
       
  1791 
       
  1792     \sa endPrefixMapping(), {Namespace Support via Features}
       
  1793 */
       
  1794 
       
  1795 /*!
       
  1796     \fn bool QXmlContentHandler::endPrefixMapping(const QString& prefix)
       
  1797 
       
  1798     The reader calls this function to signal the end of a prefix
       
  1799     mapping for the prefix \a prefix.
       
  1800 
       
  1801     If this function returns false the reader stops parsing and
       
  1802     reports an error. The reader uses the function errorString() to
       
  1803     get the error message.
       
  1804 
       
  1805     \sa startPrefixMapping(), {Namespace Support via Features}
       
  1806 */
       
  1807 
       
  1808 /*!
       
  1809     \fn bool QXmlContentHandler::startElement(const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts)
       
  1810 
       
  1811     The reader calls this function when it has parsed a start element
       
  1812     tag.
       
  1813 
       
  1814     There is a corresponding endElement() call when the corresponding
       
  1815     end element tag is read. The startElement() and endElement() calls
       
  1816     are always nested correctly. Empty element tags (e.g. \c{<x/>})
       
  1817     cause a startElement() call to be immediately followed by an
       
  1818     endElement() call.
       
  1819 
       
  1820     The attribute list provided only contains attributes with explicit
       
  1821     values. The attribute list contains attributes used for namespace
       
  1822     declaration (i.e. attributes starting with xmlns) only if the
       
  1823     namespace-prefix property of the reader is true.
       
  1824 
       
  1825     The argument \a namespaceURI is the namespace URI, or
       
  1826     an empty string if the element has no namespace URI or if no
       
  1827     namespace processing is done. \a localName is the local name
       
  1828     (without prefix), or an empty string if no namespace processing is
       
  1829     done, \a qName is the qualified name (with prefix) and \a atts are
       
  1830     the attributes attached to the element. If there are no
       
  1831     attributes, \a atts is an empty attributes object.
       
  1832 
       
  1833     If this function returns false the reader stops parsing and
       
  1834     reports an error. The reader uses the function errorString() to
       
  1835     get the error message.
       
  1836 
       
  1837     \sa endElement(), {Namespace Support via Features}
       
  1838 */
       
  1839 
       
  1840 /*!
       
  1841     \fn bool QXmlContentHandler::endElement(const QString& namespaceURI, const QString& localName, const QString& qName)
       
  1842 
       
  1843     The reader calls this function when it has parsed an end element
       
  1844     tag with the qualified name \a qName, the local name \a localName
       
  1845     and the namespace URI \a namespaceURI.
       
  1846 
       
  1847     If this function returns false the reader stops parsing and
       
  1848     reports an error. The reader uses the function errorString() to
       
  1849     get the error message.
       
  1850 
       
  1851     \sa startElement(), {Namespace Support via Features}
       
  1852 */
       
  1853 
       
  1854 /*!
       
  1855     \fn bool QXmlContentHandler::characters(const QString& ch)
       
  1856 
       
  1857     The reader calls this function when it has parsed a chunk of
       
  1858     character data (either normal character data or character data
       
  1859     inside a CDATA section; if you need to distinguish between those
       
  1860     two types you must use QXmlLexicalHandler::startCDATA() and
       
  1861     QXmlLexicalHandler::endCDATA()). The character data is reported in
       
  1862     \a ch.
       
  1863 
       
  1864     Some readers report whitespace in element content using the
       
  1865     ignorableWhitespace() function rather than using this one.
       
  1866 
       
  1867     A reader may report the character data of an element in more than
       
  1868     one chunk; e.g. a reader might want to report "a\<b" in three
       
  1869     characters() events ("a ", "\<" and " b").
       
  1870 
       
  1871     If this function returns false the reader stops parsing and
       
  1872     reports an error. The reader uses the function errorString() to
       
  1873     get the error message.
       
  1874 */
       
  1875 
       
  1876 /*!
       
  1877     \fn bool QXmlContentHandler::ignorableWhitespace(const QString& ch)
       
  1878 
       
  1879     Some readers may use this function to report each chunk of
       
  1880     whitespace in element content. The whitespace is reported in \a ch.
       
  1881 
       
  1882     If this function returns false the reader stops parsing and
       
  1883     reports an error. The reader uses the function errorString() to
       
  1884     get the error message.
       
  1885 */
       
  1886 
       
  1887 /*!
       
  1888     \fn bool QXmlContentHandler::processingInstruction(const QString& target, const QString& data)
       
  1889 
       
  1890     The reader calls this function when it has parsed a processing
       
  1891     instruction.
       
  1892 
       
  1893     \a target is the target name of the processing instruction and \a
       
  1894     data is the data in the processing instruction.
       
  1895 
       
  1896     If this function returns false the reader stops parsing and
       
  1897     reports an error. The reader uses the function errorString() to
       
  1898     get the error message.
       
  1899 */
       
  1900 
       
  1901 /*!
       
  1902     \fn bool QXmlContentHandler::skippedEntity(const QString& name)
       
  1903 
       
  1904     Some readers may skip entities if they have not seen the
       
  1905     declarations (e.g. because they are in an external DTD). If they
       
  1906     do so they report that they skipped the entity called \a name by
       
  1907     calling this function.
       
  1908 
       
  1909     If this function returns false the reader stops parsing and
       
  1910     reports an error. The reader uses the function errorString() to
       
  1911     get the error message.
       
  1912 */
       
  1913 
       
  1914 /*!
       
  1915     \fn QString QXmlContentHandler::errorString() const
       
  1916 
       
  1917     The reader calls this function to get an error string, e.g. if any
       
  1918     of the handler functions returns false.
       
  1919 */
       
  1920 
       
  1921 
       
  1922 /*!
       
  1923     \class QXmlErrorHandler
       
  1924     \reentrant
       
  1925     \brief The QXmlErrorHandler class provides an interface to report
       
  1926     errors in XML data.
       
  1927 
       
  1928     \inmodule QtXml
       
  1929     \ingroup xml-tools
       
  1930 
       
  1931     If you want your application to report errors to the user or to
       
  1932     perform customized error handling, you should subclass this class.
       
  1933 
       
  1934     You can set the error handler with QXmlReader::setErrorHandler().
       
  1935 
       
  1936     Errors can be reported using warning(), error() and fatalError(),
       
  1937     with the error text being reported with errorString().
       
  1938 
       
  1939     \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver,
       
  1940         QXmlLexicalHandler, {Introduction to SAX2}
       
  1941 */
       
  1942 
       
  1943 /*!
       
  1944     \fn QXmlErrorHandler::~QXmlErrorHandler()
       
  1945 
       
  1946     Destroys the error handler.
       
  1947 */
       
  1948 
       
  1949 /*!
       
  1950     \fn bool QXmlErrorHandler::warning(const QXmlParseException& exception)
       
  1951 
       
  1952     A reader might use this function to report a warning. Warnings are
       
  1953     conditions that are not errors or fatal errors as defined by the
       
  1954     XML 1.0 specification. Details of the warning are stored in \a
       
  1955     exception.
       
  1956 
       
  1957     If this function returns false the reader stops parsing and
       
  1958     reports an error. The reader uses the function errorString() to
       
  1959     get the error message.
       
  1960 */
       
  1961 
       
  1962 /*!
       
  1963     \fn bool QXmlErrorHandler::error(const QXmlParseException& exception)
       
  1964 
       
  1965     A reader might use this function to report a recoverable error. A
       
  1966     recoverable error corresponds to the definiton of "error" in
       
  1967     section 1.2 of the XML 1.0 specification. Details of the error are
       
  1968     stored in \a exception.
       
  1969 
       
  1970     The reader must continue to provide normal parsing events after
       
  1971     invoking this function.
       
  1972 
       
  1973     If this function returns false the reader stops parsing and
       
  1974     reports an error. The reader uses the function errorString() to
       
  1975     get the error message.
       
  1976 */
       
  1977 
       
  1978 /*!
       
  1979 \fn bool QXmlErrorHandler::fatalError(const QXmlParseException& exception)
       
  1980 
       
  1981 A reader must use this function to report a non-recoverable error.
       
  1982 Details of the error are stored in \a exception.
       
  1983 
       
  1984 If this function returns true the reader might try to go on
       
  1985 parsing and reporting further errors, but no regular parsing
       
  1986 events are reported.
       
  1987 */
       
  1988 
       
  1989 /*!
       
  1990     \fn QString QXmlErrorHandler::errorString() const
       
  1991 
       
  1992     The reader calls this function to get an error string if any of
       
  1993     the handler functions returns false.
       
  1994 */
       
  1995 
       
  1996 
       
  1997 /*!
       
  1998     \class QXmlDTDHandler
       
  1999     \reentrant
       
  2000     \brief The QXmlDTDHandler class provides an interface to report
       
  2001     DTD content of XML data.
       
  2002 
       
  2003     \inmodule QtXml
       
  2004     \ingroup xml-tools
       
  2005 
       
  2006     If an application needs information about notations and unparsed
       
  2007     entities, it can implement this interface and register an instance
       
  2008     with QXmlReader::setDTDHandler().
       
  2009 
       
  2010     Note that this interface includes only those DTD events that the
       
  2011     XML recommendation requires processors to report, i.e. notation
       
  2012     and unparsed entity declarations using notationDecl() and
       
  2013     unparsedEntityDecl() respectively.
       
  2014 
       
  2015     \sa QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver, QXmlErrorHandler,
       
  2016         QXmlLexicalHandler, {Introduction to SAX2}
       
  2017 */
       
  2018 
       
  2019 /*!
       
  2020     \fn QXmlDTDHandler::~QXmlDTDHandler()
       
  2021 
       
  2022     Destroys the DTD handler.
       
  2023 */
       
  2024 
       
  2025 /*!
       
  2026     \fn bool QXmlDTDHandler::notationDecl(const QString& name, const QString& publicId, const QString& systemId)
       
  2027 
       
  2028     The reader calls this function when it has parsed a notation
       
  2029     declaration.
       
  2030 
       
  2031     The argument \a name is the notation name, \a publicId is the
       
  2032     notation's public identifier and \a systemId is the notation's
       
  2033     system identifier.
       
  2034 
       
  2035     If this function returns false the reader stops parsing and
       
  2036     reports an error. The reader uses the function errorString() to
       
  2037     get the error message.
       
  2038 */
       
  2039 
       
  2040 /*!
       
  2041     \fn bool QXmlDTDHandler::unparsedEntityDecl(const QString& name, const QString& publicId, const QString& systemId, const QString& notationName)
       
  2042 
       
  2043     The reader calls this function when it finds an unparsed entity
       
  2044     declaration.
       
  2045 
       
  2046     The argument \a name is the unparsed entity's name, \a publicId is
       
  2047     the entity's public identifier, \a systemId is the entity's system
       
  2048     identifier and \a notationName is the name of the associated
       
  2049     notation.
       
  2050 
       
  2051     If this function returns false the reader stops parsing and
       
  2052     reports an error. The reader uses the function errorString() to
       
  2053     get the error message.
       
  2054 */
       
  2055 
       
  2056 /*!
       
  2057     \fn QString QXmlDTDHandler::errorString() const
       
  2058 
       
  2059     The reader calls this function to get an error string if any of
       
  2060     the handler functions returns false.
       
  2061 */
       
  2062 
       
  2063 
       
  2064 /*!
       
  2065     \class QXmlEntityResolver
       
  2066     \reentrant
       
  2067     \brief The QXmlEntityResolver class provides an interface to
       
  2068     resolve external entities contained in XML data.
       
  2069 
       
  2070     \inmodule QtXml
       
  2071     \ingroup xml-tools
       
  2072 
       
  2073     If an application needs to implement customized handling for
       
  2074     external entities, it must implement this interface, i.e.
       
  2075     resolveEntity(), and register it with
       
  2076     QXmlReader::setEntityResolver().
       
  2077 
       
  2078     \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlErrorHandler,
       
  2079         QXmlLexicalHandler, {Introduction to SAX2}
       
  2080 */
       
  2081 
       
  2082 /*!
       
  2083     \fn QXmlEntityResolver::~QXmlEntityResolver()
       
  2084 
       
  2085     Destroys the entity resolver.
       
  2086 */
       
  2087 
       
  2088 /*!
       
  2089     \fn bool QXmlEntityResolver::resolveEntity(const QString& publicId, const QString& systemId, QXmlInputSource*& ret)
       
  2090 
       
  2091     The reader calls this function before it opens any external
       
  2092     entity, except the top-level document entity. The application may
       
  2093     request the reader to resolve the entity itself (\a ret is 0) or
       
  2094     to use an entirely different input source (\a ret points to the
       
  2095     input source).
       
  2096 
       
  2097     The reader deletes the input source \a ret when it no longer needs
       
  2098     it, so you should allocate it on the heap with \c new.
       
  2099 
       
  2100     The argument \a publicId is the public identifier of the external
       
  2101     entity, \a systemId is the system identifier of the external
       
  2102     entity and \a ret is the return value of this function. If \a ret
       
  2103     is 0 the reader should resolve the entity itself, if it is
       
  2104     non-zero it must point to an input source which the reader uses
       
  2105     instead.
       
  2106 
       
  2107     If this function returns false the reader stops parsing and
       
  2108     reports an error. The reader uses the function errorString() to
       
  2109     get the error message.
       
  2110 */
       
  2111 
       
  2112 /*!
       
  2113     \fn QString QXmlEntityResolver::errorString() const
       
  2114 
       
  2115     The reader calls this function to get an error string if any of
       
  2116     the handler functions returns false.
       
  2117 */
       
  2118 
       
  2119 
       
  2120 /*!
       
  2121     \class QXmlLexicalHandler
       
  2122     \reentrant
       
  2123     \brief The QXmlLexicalHandler class provides an interface to
       
  2124     report the lexical content of XML data.
       
  2125 
       
  2126     \inmodule QtXml
       
  2127     \ingroup xml-tools
       
  2128 
       
  2129     The events in the lexical handler apply to the entire document,
       
  2130     not just to the document element, and all lexical handler events
       
  2131     appear between the content handler's startDocument and endDocument
       
  2132     events.
       
  2133 
       
  2134     You can set the lexical handler with
       
  2135     QXmlReader::setLexicalHandler().
       
  2136 
       
  2137     This interface's design is based on the SAX2 extension
       
  2138     LexicalHandler.
       
  2139 
       
  2140     The interface provides the startDTD(), endDTD(), startEntity(),
       
  2141     endEntity(), startCDATA(), endCDATA() and comment() functions.
       
  2142 
       
  2143     \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver,
       
  2144         QXmlErrorHandler, {Introduction to SAX2}
       
  2145 */
       
  2146 
       
  2147 /*!
       
  2148     \fn QXmlLexicalHandler::~QXmlLexicalHandler()
       
  2149 
       
  2150     Destroys the lexical handler.
       
  2151 */
       
  2152 
       
  2153 /*!
       
  2154     \fn bool QXmlLexicalHandler::startDTD(const QString& name, const QString& publicId, const QString& systemId)
       
  2155 
       
  2156     The reader calls this function to report the start of a DTD
       
  2157     declaration, if any. It reports the name of the document type in
       
  2158     \a name, the public identifier in \a publicId and the system
       
  2159     identifier in \a systemId.
       
  2160 
       
  2161     If the public identifier is missing, \a publicId is set to
       
  2162     an empty string. If the system identifier is missing, \a systemId is
       
  2163     set to an empty string. Note that it is not valid XML to have a
       
  2164     public identifier but no system identifier; in such cases a parse
       
  2165     error will occur.
       
  2166 
       
  2167     All declarations reported through QXmlDTDHandler or
       
  2168     QXmlDeclHandler appear between the startDTD() and endDTD() calls.
       
  2169 
       
  2170     If this function returns false the reader stops parsing and
       
  2171     reports an error. The reader uses the function errorString() to
       
  2172     get the error message.
       
  2173 
       
  2174     \sa endDTD()
       
  2175 */
       
  2176 
       
  2177 /*!
       
  2178     \fn bool QXmlLexicalHandler::endDTD()
       
  2179 
       
  2180     The reader calls this function to report the end of a DTD
       
  2181     declaration, if any.
       
  2182 
       
  2183     If this function returns false the reader stops parsing and
       
  2184     reports an error. The reader uses the function errorString() to
       
  2185     get the error message.
       
  2186 
       
  2187     \sa startDTD()
       
  2188 */
       
  2189 
       
  2190 /*!
       
  2191     \fn bool QXmlLexicalHandler::startEntity(const QString& name)
       
  2192 
       
  2193     The reader calls this function to report the start of an entity
       
  2194     called \a name.
       
  2195 
       
  2196     Note that if the entity is unknown, the reader reports it through
       
  2197     QXmlContentHandler::skippedEntity() and not through this
       
  2198     function.
       
  2199 
       
  2200     If this function returns false the reader stops parsing and
       
  2201     reports an error. The reader uses the function errorString() to
       
  2202     get the error message.
       
  2203 
       
  2204     \sa endEntity(), QXmlSimpleReader::setFeature()
       
  2205 */
       
  2206 
       
  2207 /*!
       
  2208     \fn bool QXmlLexicalHandler::endEntity(const QString& name)
       
  2209 
       
  2210     The reader calls this function to report the end of an entity
       
  2211     called \a name.
       
  2212 
       
  2213     For every startEntity() call, there is a corresponding endEntity()
       
  2214     call. The calls to startEntity() and endEntity() are properly
       
  2215     nested.
       
  2216 
       
  2217     If this function returns false the reader stops parsing and
       
  2218     reports an error. The reader uses the function errorString() to
       
  2219     get the error message.
       
  2220 
       
  2221     \sa startEntity(), QXmlContentHandler::skippedEntity(), QXmlSimpleReader::setFeature()
       
  2222 */
       
  2223 
       
  2224 /*!
       
  2225     \fn bool QXmlLexicalHandler::startCDATA()
       
  2226 
       
  2227     The reader calls this function to report the start of a CDATA
       
  2228     section. The content of the CDATA section is reported through the
       
  2229     QXmlContentHandler::characters() function. This function is
       
  2230     intended only to report the boundary.
       
  2231 
       
  2232     If this function returns false the reader stops parsing and
       
  2233     reports an error. The reader uses the function errorString() to
       
  2234     get the error message.
       
  2235 
       
  2236     \sa endCDATA()
       
  2237 */
       
  2238 
       
  2239 /*!
       
  2240     \fn bool QXmlLexicalHandler::endCDATA()
       
  2241 
       
  2242     The reader calls this function to report the end of a CDATA
       
  2243     section.
       
  2244 
       
  2245     If this function returns false the reader stops parsing and reports
       
  2246     an error. The reader uses the function errorString() to get the error
       
  2247     message.
       
  2248 
       
  2249     \sa startCDATA(), QXmlContentHandler::characters()
       
  2250 */
       
  2251 
       
  2252 /*!
       
  2253     \fn bool QXmlLexicalHandler::comment(const QString& ch)
       
  2254 
       
  2255     The reader calls this function to report an XML comment anywhere
       
  2256     in the document. It reports the text of the comment in \a ch.
       
  2257 
       
  2258     If this function returns false the reader stops parsing and
       
  2259     reports an error. The reader uses the function errorString() to
       
  2260     get the error message.
       
  2261 */
       
  2262 
       
  2263 /*!
       
  2264     \fn QString QXmlLexicalHandler::errorString() const
       
  2265 
       
  2266     The reader calls this function to get an error string if any of
       
  2267     the handler functions returns false.
       
  2268 */
       
  2269 
       
  2270 
       
  2271 /*!
       
  2272     \class QXmlDeclHandler
       
  2273     \reentrant
       
  2274     \brief The QXmlDeclHandler class provides an interface to report declaration
       
  2275     content of XML data.
       
  2276 
       
  2277     \inmodule QtXml
       
  2278     \ingroup xml-tools
       
  2279 
       
  2280     You can set the declaration handler with
       
  2281     QXmlReader::setDeclHandler().
       
  2282 
       
  2283     This interface is based on the SAX2 extension DeclHandler.
       
  2284 
       
  2285     The interface provides attributeDecl(), internalEntityDecl() and
       
  2286     externalEntityDecl() functions.
       
  2287 
       
  2288     \sa QXmlDTDHandler, QXmlContentHandler, QXmlEntityResolver, QXmlErrorHandler,
       
  2289         QXmlLexicalHandler, {Introduction to SAX2}
       
  2290 */
       
  2291 
       
  2292 /*!
       
  2293     \fn QXmlDeclHandler::~QXmlDeclHandler()
       
  2294 
       
  2295     Destroys the declaration handler.
       
  2296 */
       
  2297 
       
  2298 /*!
       
  2299     \fn bool QXmlDeclHandler::attributeDecl(const QString& eName, const QString& aName, const QString& type, const QString& valueDefault, const QString& value)
       
  2300 
       
  2301     The reader calls this function to report an attribute type
       
  2302     declaration. Only the effective (first) declaration for an
       
  2303     attribute is reported.
       
  2304 
       
  2305     The reader passes the name of the associated element in \a eName
       
  2306     and the name of the attribute in \a aName. It passes a string that
       
  2307     represents the attribute type in \a type and a string that
       
  2308     represents the attribute default in \a valueDefault. This string
       
  2309     is one of "#IMPLIED", "#REQUIRED", "#FIXED" or an empty string (if
       
  2310     none of the others applies). The reader passes the attribute's
       
  2311     default value in \a value. If no default value is specified in the
       
  2312     XML file, \a value is an empty string.
       
  2313 
       
  2314     If this function returns false the reader stops parsing and
       
  2315     reports an error. The reader uses the function errorString() to
       
  2316     get the error message.
       
  2317 */
       
  2318 
       
  2319 /*!
       
  2320     \fn bool QXmlDeclHandler::internalEntityDecl(const QString& name, const QString& value)
       
  2321 
       
  2322     The reader calls this function to report an internal entity
       
  2323     declaration. Only the effective (first) declaration is reported.
       
  2324 
       
  2325     The reader passes the name of the entity in \a name and the value
       
  2326     of the entity in \a value.
       
  2327 
       
  2328     If this function returns false the reader stops parsing and
       
  2329     reports an error. The reader uses the function errorString() to
       
  2330     get the error message.
       
  2331 */
       
  2332 
       
  2333 /*!
       
  2334     \fn bool QXmlDeclHandler::externalEntityDecl(const QString& name, const QString& publicId, const QString& systemId)
       
  2335 
       
  2336     The reader calls this function to report a parsed external entity
       
  2337     declaration. Only the effective (first) declaration for each
       
  2338     entity is reported.
       
  2339 
       
  2340     The reader passes the name of the entity in \a name, the public
       
  2341     identifier in \a publicId and the system identifier in \a
       
  2342     systemId. If there is no public identifier specified, it passes
       
  2343     an empty string in \a publicId.
       
  2344 
       
  2345     If this function returns false the reader stops parsing and
       
  2346     reports an error. The reader uses the function errorString() to
       
  2347     get the error message.
       
  2348 */
       
  2349 
       
  2350 /*!
       
  2351     \fn QString QXmlDeclHandler::errorString() const
       
  2352 
       
  2353     The reader calls this function to get an error string if any of
       
  2354     the handler functions returns false.
       
  2355 */
       
  2356 
       
  2357 
       
  2358 /*!
       
  2359     \class QXmlDefaultHandler
       
  2360     \reentrant
       
  2361     \brief The QXmlDefaultHandler class provides a default implementation of all
       
  2362     the XML handler classes.
       
  2363 
       
  2364     \inmodule QtXml
       
  2365     \ingroup xml-tools
       
  2366 
       
  2367     This class gathers together the features of
       
  2368     the specialized handler classes, making it a convenient
       
  2369     starting point when implementing custom handlers for
       
  2370     subclasses of QXmlReader, particularly QXmlSimpleReader.
       
  2371     The virtual functions from each of the base classes are
       
  2372     reimplemented in this class, providing sensible default behavior
       
  2373     for many common cases. By subclassing this class, and
       
  2374     overriding these functions, you can concentrate
       
  2375     on implementing the parts of the handler relevant to your
       
  2376     application.
       
  2377 
       
  2378     The XML reader must be told which handler to use for different
       
  2379     kinds of events during parsing. This means that, although
       
  2380     QXmlDefaultHandler provides default implementations of functions
       
  2381     inherited from all its base classes, we can still use specialized
       
  2382     handlers for particular kinds of events.
       
  2383 
       
  2384     For example, QXmlDefaultHandler subclasses both
       
  2385     QXmlContentHandler and QXmlErrorHandler, so by subclassing
       
  2386     it we can use the same handler for both of the following
       
  2387     reader functions:
       
  2388 
       
  2389     \snippet doc/src/snippets/xml/rsslisting/rsslisting.cpp 0
       
  2390 
       
  2391     Since the reader will inform the handler of parsing errors, it is
       
  2392     necessary to reimplement QXmlErrorHandler::fatalError() if, for
       
  2393     example, we want to stop parsing when such an error occurs:
       
  2394 
       
  2395     \snippet doc/src/snippets/xml/rsslisting/handler.cpp 0
       
  2396 
       
  2397     The above function returns false, which tells the reader to stop
       
  2398     parsing. To continue to use the same reader,
       
  2399     it is necessary to create a new handler instance, and set up the
       
  2400     reader to use it in the manner described above.
       
  2401 
       
  2402     It is useful to examine some of the functions inherited by
       
  2403     QXmlDefaultHandler, and consider why they might be
       
  2404     reimplemented in a custom handler.
       
  2405     Custom handlers will typically reimplement
       
  2406     QXmlContentHandler::startDocument() to prepare the handler for
       
  2407     new content. Document elements and the text within them can be
       
  2408     processed by reimplementing QXmlContentHandler::startElement(),
       
  2409     QXmlContentHandler::endElement(), and
       
  2410     QXmlContentHandler::characters().
       
  2411     You may want to reimplement QXmlContentHandler::endDocument()
       
  2412     to perform some finalization or validation on the content once the
       
  2413     document has been read completely.
       
  2414 
       
  2415     \sa QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver,
       
  2416         QXmlErrorHandler, QXmlLexicalHandler, {Introduction to SAX2}
       
  2417 */
       
  2418 
       
  2419 /*!
       
  2420     \fn QXmlDefaultHandler::QXmlDefaultHandler()
       
  2421 
       
  2422     Constructs a handler for use with subclasses of QXmlReader.
       
  2423 */
       
  2424 /*!
       
  2425     \fn QXmlDefaultHandler::~QXmlDefaultHandler()
       
  2426 
       
  2427     Destroys the handler.
       
  2428 */
       
  2429 
       
  2430 /*!
       
  2431     \reimp
       
  2432 
       
  2433     This reimplementation does nothing.
       
  2434 */
       
  2435 void QXmlDefaultHandler::setDocumentLocator(QXmlLocator*)
       
  2436 {
       
  2437 }
       
  2438 
       
  2439 /*!
       
  2440     \reimp
       
  2441 
       
  2442     This reimplementation does nothing.
       
  2443 */
       
  2444 bool QXmlDefaultHandler::startDocument()
       
  2445 {
       
  2446     return true;
       
  2447 }
       
  2448 
       
  2449 /*!
       
  2450     \reimp
       
  2451 
       
  2452     This reimplementation does nothing.
       
  2453 */
       
  2454 bool QXmlDefaultHandler::endDocument()
       
  2455 {
       
  2456     return true;
       
  2457 }
       
  2458 
       
  2459 /*!
       
  2460     \reimp
       
  2461 
       
  2462     This reimplementation does nothing.
       
  2463 */
       
  2464 bool QXmlDefaultHandler::startPrefixMapping(const QString&, const QString&)
       
  2465 {
       
  2466     return true;
       
  2467 }
       
  2468 
       
  2469 /*!
       
  2470     \reimp
       
  2471 
       
  2472     This reimplementation does nothing.
       
  2473 */
       
  2474 bool QXmlDefaultHandler::endPrefixMapping(const QString&)
       
  2475 {
       
  2476     return true;
       
  2477 }
       
  2478 
       
  2479 /*!
       
  2480     \reimp
       
  2481 
       
  2482     This reimplementation does nothing.
       
  2483 */
       
  2484 bool QXmlDefaultHandler::startElement(const QString&, const QString&,
       
  2485         const QString&, const QXmlAttributes&)
       
  2486 {
       
  2487     return true;
       
  2488 }
       
  2489 
       
  2490 /*!
       
  2491     \reimp
       
  2492 
       
  2493     This reimplementation does nothing.
       
  2494 */
       
  2495 bool QXmlDefaultHandler::endElement(const QString&, const QString&,
       
  2496         const QString&)
       
  2497 {
       
  2498     return true;
       
  2499 }
       
  2500 
       
  2501 /*!
       
  2502     \reimp
       
  2503 
       
  2504     This reimplementation does nothing.
       
  2505 */
       
  2506 bool QXmlDefaultHandler::characters(const QString&)
       
  2507 {
       
  2508     return true;
       
  2509 }
       
  2510 
       
  2511 /*!
       
  2512     \reimp
       
  2513 
       
  2514     This reimplementation does nothing.
       
  2515 */
       
  2516 bool QXmlDefaultHandler::ignorableWhitespace(const QString&)
       
  2517 {
       
  2518     return true;
       
  2519 }
       
  2520 
       
  2521 /*!
       
  2522     \reimp
       
  2523 
       
  2524     This reimplementation does nothing.
       
  2525 */
       
  2526 bool QXmlDefaultHandler::processingInstruction(const QString&,
       
  2527         const QString&)
       
  2528 {
       
  2529     return true;
       
  2530 }
       
  2531 
       
  2532 /*!
       
  2533     \reimp
       
  2534 
       
  2535     This reimplementation does nothing.
       
  2536 */
       
  2537 bool QXmlDefaultHandler::skippedEntity(const QString&)
       
  2538 {
       
  2539     return true;
       
  2540 }
       
  2541 
       
  2542 /*!
       
  2543     \reimp
       
  2544 
       
  2545     This reimplementation does nothing.
       
  2546 */
       
  2547 bool QXmlDefaultHandler::warning(const QXmlParseException&)
       
  2548 {
       
  2549     return true;
       
  2550 }
       
  2551 
       
  2552 /*!
       
  2553     \reimp
       
  2554 
       
  2555     This reimplementation does nothing.
       
  2556 */
       
  2557 bool QXmlDefaultHandler::error(const QXmlParseException&)
       
  2558 {
       
  2559     return true;
       
  2560 }
       
  2561 
       
  2562 /*!
       
  2563     \reimp
       
  2564 
       
  2565     This reimplementation does nothing.
       
  2566 */
       
  2567 bool QXmlDefaultHandler::fatalError(const QXmlParseException&)
       
  2568 {
       
  2569     return true;
       
  2570 }
       
  2571 
       
  2572 /*!
       
  2573     \reimp
       
  2574 
       
  2575     This reimplementation does nothing.
       
  2576 */
       
  2577 bool QXmlDefaultHandler::notationDecl(const QString&, const QString&,
       
  2578         const QString&)
       
  2579 {
       
  2580     return true;
       
  2581 }
       
  2582 
       
  2583 /*!
       
  2584     \reimp
       
  2585 
       
  2586     This reimplementation does nothing.
       
  2587 */
       
  2588 bool QXmlDefaultHandler::unparsedEntityDecl(const QString&, const QString&,
       
  2589         const QString&, const QString&)
       
  2590 {
       
  2591     return true;
       
  2592 }
       
  2593 
       
  2594 /*!
       
  2595     \reimp
       
  2596 
       
  2597     Sets \a ret to 0, so that the reader uses the system identifier
       
  2598     provided in the XML document.
       
  2599 */
       
  2600 bool QXmlDefaultHandler::resolveEntity(const QString&, const QString&,
       
  2601         QXmlInputSource*& ret)
       
  2602 {
       
  2603     ret = 0;
       
  2604     return true;
       
  2605 }
       
  2606 
       
  2607 /*!
       
  2608     \reimp
       
  2609 
       
  2610     Returns the default error string.
       
  2611 */
       
  2612 QString QXmlDefaultHandler::errorString() const
       
  2613 {
       
  2614     return QString::fromLatin1(XMLERR_ERRORBYCONSUMER);
       
  2615 }
       
  2616 
       
  2617 /*!
       
  2618     \reimp
       
  2619 
       
  2620     This reimplementation does nothing.
       
  2621 */
       
  2622 bool QXmlDefaultHandler::startDTD(const QString&, const QString&, const QString&)
       
  2623 {
       
  2624     return true;
       
  2625 }
       
  2626 
       
  2627 /*!
       
  2628     \reimp
       
  2629 
       
  2630     This reimplementation does nothing.
       
  2631 */
       
  2632 bool QXmlDefaultHandler::endDTD()
       
  2633 {
       
  2634     return true;
       
  2635 }
       
  2636 
       
  2637 /*!
       
  2638     \reimp
       
  2639 
       
  2640     This reimplementation does nothing.
       
  2641 */
       
  2642 bool QXmlDefaultHandler::startEntity(const QString&)
       
  2643 {
       
  2644     return true;
       
  2645 }
       
  2646 
       
  2647 /*!
       
  2648     \reimp
       
  2649 
       
  2650     This reimplementation does nothing.
       
  2651 */
       
  2652 bool QXmlDefaultHandler::endEntity(const QString&)
       
  2653 {
       
  2654     return true;
       
  2655 }
       
  2656 
       
  2657 /*!
       
  2658     \reimp
       
  2659 
       
  2660     This reimplementation does nothing.
       
  2661 */
       
  2662 bool QXmlDefaultHandler::startCDATA()
       
  2663 {
       
  2664     return true;
       
  2665 }
       
  2666 
       
  2667 /*!
       
  2668     \reimp
       
  2669 
       
  2670     This reimplementation does nothing.
       
  2671 */
       
  2672 bool QXmlDefaultHandler::endCDATA()
       
  2673 {
       
  2674     return true;
       
  2675 }
       
  2676 
       
  2677 /*!
       
  2678     \reimp
       
  2679 
       
  2680     This reimplementation does nothing.
       
  2681 */
       
  2682 bool QXmlDefaultHandler::comment(const QString&)
       
  2683 {
       
  2684     return true;
       
  2685 }
       
  2686 
       
  2687 /*!
       
  2688     \reimp
       
  2689 
       
  2690     This reimplementation does nothing.
       
  2691 */
       
  2692 bool QXmlDefaultHandler::attributeDecl(const QString&, const QString&, const QString&, const QString&, const QString&)
       
  2693 {
       
  2694     return true;
       
  2695 }
       
  2696 
       
  2697 /*!
       
  2698     \reimp
       
  2699 
       
  2700     This reimplementation does nothing.
       
  2701 */
       
  2702 bool QXmlDefaultHandler::internalEntityDecl(const QString&, const QString&)
       
  2703 {
       
  2704     return true;
       
  2705 }
       
  2706 
       
  2707 /*!
       
  2708     \reimp
       
  2709 
       
  2710     This reimplementation does nothing.
       
  2711 */
       
  2712 bool QXmlDefaultHandler::externalEntityDecl(const QString&, const QString&, const QString&)
       
  2713 {
       
  2714     return true;
       
  2715 }
       
  2716 
       
  2717 
       
  2718 /*********************************************
       
  2719  *
       
  2720  * QXmlSimpleReaderPrivate
       
  2721  *
       
  2722  *********************************************/
       
  2723 
       
  2724 inline bool QXmlSimpleReaderPrivate::atEnd()
       
  2725 {
       
  2726     return (c.unicode()|0x0001) == 0xffff;
       
  2727 }
       
  2728 
       
  2729 inline void QXmlSimpleReaderPrivate::stringClear()
       
  2730 {
       
  2731     stringValueLen = 0; stringArrayPos = 0;
       
  2732 }
       
  2733 inline void QXmlSimpleReaderPrivate::nameClear()
       
  2734 {
       
  2735     nameValueLen = 0; nameArrayPos = 0;
       
  2736 }
       
  2737 
       
  2738 inline void QXmlSimpleReaderPrivate::refClear()
       
  2739 {
       
  2740     refValueLen = 0; refArrayPos = 0;
       
  2741 }
       
  2742 
       
  2743 QXmlSimpleReaderPrivate::QXmlSimpleReaderPrivate(QXmlSimpleReader *reader)
       
  2744 {
       
  2745     q_ptr = reader;
       
  2746     parseStack = 0;
       
  2747 
       
  2748     locator.reset(new QXmlSimpleReaderLocator(reader));
       
  2749     entityRes  = 0;
       
  2750     dtdHnd     = 0;
       
  2751     contentHnd = 0;
       
  2752     errorHnd   = 0;
       
  2753     lexicalHnd = 0;
       
  2754     declHnd    = 0;
       
  2755 
       
  2756     // default feature settings
       
  2757     useNamespaces = true;
       
  2758     useNamespacePrefixes = false;
       
  2759     reportWhitespaceCharData = true;
       
  2760     reportEntities = false;
       
  2761 }
       
  2762 
       
  2763 QXmlSimpleReaderPrivate::~QXmlSimpleReaderPrivate()
       
  2764 {
       
  2765     delete parseStack;
       
  2766 }
       
  2767 
       
  2768 void QXmlSimpleReaderPrivate::initIncrementalParsing()
       
  2769 {
       
  2770     if(parseStack)
       
  2771         parseStack->clear();
       
  2772     else
       
  2773         parseStack = new QStack<ParseState>;
       
  2774 }
       
  2775 
       
  2776 /*********************************************
       
  2777  *
       
  2778  * QXmlSimpleReader
       
  2779  *
       
  2780  *********************************************/
       
  2781 
       
  2782 /*!
       
  2783     \class QXmlReader
       
  2784     \reentrant
       
  2785     \brief The QXmlReader class provides an interface for XML readers (i.e.
       
  2786     parsers).
       
  2787 
       
  2788     \inmodule QtXml
       
  2789     \ingroup xml-tools
       
  2790 
       
  2791     This abstract class provides an interface for all of Qt's XML
       
  2792     readers. Currently there is only one implementation of a reader
       
  2793     included in Qt's XML module: QXmlSimpleReader. In future releases
       
  2794     there might be more readers with different properties available
       
  2795     (e.g. a validating parser).
       
  2796 
       
  2797     The design of the XML classes follows the \link
       
  2798     http://www.saxproject.org/ SAX2 Java interface\endlink, with
       
  2799     the names adapted to fit Qt naming conventions. It should be very
       
  2800     easy for anybody who has worked with SAX2 to get started with the
       
  2801     Qt XML classes.
       
  2802 
       
  2803     All readers use the class QXmlInputSource to read the input
       
  2804     document. Since you are normally interested in particular content
       
  2805     in the XML document, the reader reports the content through
       
  2806     special handler classes (QXmlDTDHandler, QXmlDeclHandler,
       
  2807     QXmlContentHandler, QXmlEntityResolver, QXmlErrorHandler and
       
  2808     QXmlLexicalHandler), which you must subclass, if you want to
       
  2809     process the contents.
       
  2810 
       
  2811     Since the handler classes only describe interfaces you must
       
  2812     implement all the functions. We provide the QXmlDefaultHandler
       
  2813     class to make this easier: it implements a default behavior (do
       
  2814     nothing) for all functions, so you can subclass it and just
       
  2815     implement the functions you are interested in.
       
  2816 
       
  2817     Features and properties of the reader can be set with setFeature()
       
  2818     and setProperty() respectively. You can set the reader to use your
       
  2819     own subclasses with setEntityResolver(), setDTDHandler(),
       
  2820     setContentHandler(), setErrorHandler(), setLexicalHandler() and
       
  2821     setDeclHandler(). The parse itself is started with a call to
       
  2822     parse().
       
  2823 
       
  2824     \sa QXmlSimpleReader
       
  2825 */
       
  2826 
       
  2827 /*!
       
  2828     \fn QXmlReader::~QXmlReader()
       
  2829 
       
  2830     Destroys the reader.
       
  2831 */
       
  2832 
       
  2833 /*!
       
  2834     \fn bool QXmlReader::feature(const QString& name, bool *ok) const
       
  2835 
       
  2836     If the reader has the feature called \a name, the feature's value
       
  2837     is returned. If no such feature exists the return value is
       
  2838     undefined.
       
  2839 
       
  2840     If \a ok is not 0: \c{*}\a{ok}  is set to true if the reader has the
       
  2841     feature called \a name; otherwise \c{*}\a{ok} is set to false.
       
  2842 
       
  2843     \sa setFeature(), hasFeature()
       
  2844 */
       
  2845 
       
  2846 /*!
       
  2847     \fn void QXmlReader::setFeature(const QString& name, bool value)
       
  2848 
       
  2849     Sets the feature called \a name to the given \a value. If the
       
  2850     reader doesn't have the feature nothing happens.
       
  2851 
       
  2852     \sa feature(), hasFeature()
       
  2853 */
       
  2854 
       
  2855 /*!
       
  2856     \fn bool QXmlReader::hasFeature(const QString& name) const
       
  2857 
       
  2858     Returns \c true if the reader has the feature called \a name;
       
  2859     otherwise returns false.
       
  2860 
       
  2861     \sa feature(), setFeature()
       
  2862 */
       
  2863 
       
  2864 /*!
       
  2865     \fn void* QXmlReader::property(const QString& name, bool *ok) const
       
  2866 
       
  2867     If the reader has the property \a name, this function returns the
       
  2868     value of the property; otherwise the return value is undefined.
       
  2869 
       
  2870     If \a ok is not 0: if the reader has the \a name property
       
  2871     \c{*}\a{ok} is set to true; otherwise \c{*}\a{ok} is set to false.
       
  2872 
       
  2873     \sa setProperty(), hasProperty()
       
  2874 */
       
  2875 
       
  2876 /*!
       
  2877     \fn void QXmlReader::setProperty(const QString& name, void* value)
       
  2878 
       
  2879     Sets the property \a name to \a value. If the reader doesn't have
       
  2880     the property nothing happens.
       
  2881 
       
  2882     \sa property(), hasProperty()
       
  2883 */
       
  2884 
       
  2885 /*!
       
  2886     \fn bool QXmlReader::hasProperty(const QString& name) const
       
  2887 
       
  2888     Returns true if the reader has the property \a name; otherwise
       
  2889     returns false.
       
  2890 
       
  2891     \sa property(), setProperty()
       
  2892 */
       
  2893 
       
  2894 /*!
       
  2895     \fn void QXmlReader::setEntityResolver(QXmlEntityResolver* handler)
       
  2896 
       
  2897     Sets the entity resolver to \a handler.
       
  2898 
       
  2899     \sa entityResolver()
       
  2900 */
       
  2901 
       
  2902 /*!
       
  2903     \fn QXmlEntityResolver* QXmlReader::entityResolver() const
       
  2904 
       
  2905     Returns the entity resolver or 0 if none was set.
       
  2906 
       
  2907     \sa setEntityResolver()
       
  2908 */
       
  2909 
       
  2910 /*!
       
  2911     \fn void QXmlReader::setDTDHandler(QXmlDTDHandler* handler)
       
  2912 
       
  2913     Sets the DTD handler to \a handler.
       
  2914 
       
  2915     \sa DTDHandler()
       
  2916 */
       
  2917 
       
  2918 /*!
       
  2919     \fn QXmlDTDHandler* QXmlReader::DTDHandler() const
       
  2920 
       
  2921     Returns the DTD handler or 0 if none was set.
       
  2922 
       
  2923     \sa setDTDHandler()
       
  2924 */
       
  2925 
       
  2926 /*!
       
  2927     \fn void QXmlReader::setContentHandler(QXmlContentHandler* handler)
       
  2928 
       
  2929     Sets the content handler to \a handler.
       
  2930 
       
  2931     \sa contentHandler()
       
  2932 */
       
  2933 
       
  2934 /*!
       
  2935     \fn QXmlContentHandler* QXmlReader::contentHandler() const
       
  2936 
       
  2937     Returns the content handler or 0 if none was set.
       
  2938 
       
  2939     \sa setContentHandler()
       
  2940 */
       
  2941 
       
  2942 /*!
       
  2943     \fn void QXmlReader::setErrorHandler(QXmlErrorHandler* handler)
       
  2944 
       
  2945     Sets the error handler to \a handler. Clears the error handler if
       
  2946     \a handler is 0.
       
  2947 
       
  2948     \sa errorHandler()
       
  2949 */
       
  2950 
       
  2951 /*!
       
  2952     \fn QXmlErrorHandler* QXmlReader::errorHandler() const
       
  2953 
       
  2954     Returns the error handler or 0 if none is set.
       
  2955 
       
  2956     \sa setErrorHandler()
       
  2957 */
       
  2958 
       
  2959 /*!
       
  2960     \fn void QXmlReader::setLexicalHandler(QXmlLexicalHandler* handler)
       
  2961 
       
  2962     Sets the lexical handler to \a handler.
       
  2963 
       
  2964     \sa lexicalHandler()
       
  2965 */
       
  2966 
       
  2967 /*!
       
  2968     \fn QXmlLexicalHandler* QXmlReader::lexicalHandler() const
       
  2969 
       
  2970     Returns the lexical handler or 0 if none was set.
       
  2971 
       
  2972     \sa setLexicalHandler()
       
  2973 */
       
  2974 
       
  2975 /*!
       
  2976     \fn void QXmlReader::setDeclHandler(QXmlDeclHandler* handler)
       
  2977 
       
  2978     Sets the declaration handler to \a handler.
       
  2979 
       
  2980     \sa declHandler()
       
  2981 */
       
  2982 
       
  2983 /*!
       
  2984     \fn QXmlDeclHandler* QXmlReader::declHandler() const
       
  2985 
       
  2986     Returns the declaration handler or 0 if none was set.
       
  2987 
       
  2988     \sa setDeclHandler()
       
  2989 */
       
  2990 
       
  2991 /*!
       
  2992   \fn bool QXmlReader::parse(const QXmlInputSource &input)
       
  2993 
       
  2994   \obsolete
       
  2995 
       
  2996   Parses the given \a input.
       
  2997 */
       
  2998 
       
  2999 /*!
       
  3000     \fn bool QXmlReader::parse(const QXmlInputSource *input)
       
  3001 
       
  3002     Reads an XML document from \a input and parses it. Returns true if
       
  3003     the parsing was successful; otherwise returns false.
       
  3004 */
       
  3005 
       
  3006 
       
  3007 /*!
       
  3008     \class QXmlSimpleReader
       
  3009     \nonreentrant
       
  3010     \brief The QXmlSimpleReader class provides an implementation of a
       
  3011     simple XML parser.
       
  3012 
       
  3013     \inmodule QtXml
       
  3014     \ingroup xml-tools
       
  3015 
       
  3016 
       
  3017     This XML reader is suitable for a wide range of applications. It
       
  3018     is able to parse well-formed XML and can report the namespaces of
       
  3019     elements to a content handler; however, it does not parse any
       
  3020     external entities. For historical reasons, Attribute Value
       
  3021     Normalization and End-of-Line Handling as described in the XML 1.0
       
  3022     specification is not performed.
       
  3023 
       
  3024     The easiest pattern of use for this class is to create a reader
       
  3025     instance, define an input source, specify the handlers to be used
       
  3026     by the reader, and parse the data.
       
  3027 
       
  3028     For example, we could use a QFile to supply the input. Here, we
       
  3029     create a reader, and define an input source to be used by the
       
  3030     reader:
       
  3031 
       
  3032     \snippet doc/src/snippets/xml/simpleparse/main.cpp 0
       
  3033 
       
  3034     A handler lets us perform actions when the reader encounters
       
  3035     certain types of content, or if errors in the input are found. The
       
  3036     reader must be told which handler to use for each type of
       
  3037     event. For many common applications, we can create a custom
       
  3038     handler by subclassing QXmlDefaultHandler, and use this to handle
       
  3039     both error and content events:
       
  3040 
       
  3041     \snippet doc/src/snippets/xml/simpleparse/main.cpp 1
       
  3042 
       
  3043     If you don't set at least the content and error handlers, the
       
  3044     parser will fall back on its default behavior---and will do
       
  3045     nothing.
       
  3046 
       
  3047     The most convenient way to handle the input is to read it in a
       
  3048     single pass using the parse() function with an argument that
       
  3049     specifies the input source:
       
  3050 
       
  3051     \snippet doc/src/snippets/xml/simpleparse/main.cpp 2
       
  3052 
       
  3053     If you can't parse the entire input in one go (for example, it is
       
  3054     huge, or is being delivered over a network connection), data can
       
  3055     be fed to the parser in pieces. This is achieved by telling
       
  3056     parse() to work incrementally, and making subsequent calls to the
       
  3057     parseContinue() function, until all the data has been processed.
       
  3058 
       
  3059     A common way to perform incremental parsing is to connect the \c
       
  3060     readyRead() signal of a \l{QNetworkReply} {network reply} a slot,
       
  3061     and handle the incoming data there. See QNetworkAccessManager.
       
  3062     
       
  3063     Aspects of the parsing behavior can be adapted using setFeature()
       
  3064     and setProperty().
       
  3065     
       
  3066     QXmlSimpleReader is not reentrant. If you want to use the class
       
  3067     in threaded code, lock the code using QXmlSimpleReader with a
       
  3068     locking mechanism, such as a QMutex.
       
  3069 
       
  3070     \snippet doc/src/snippets/code/src_xml_sax_qxml.cpp 0
       
  3071 */
       
  3072 
       
  3073 static inline bool is_S(QChar ch)
       
  3074 {
       
  3075     ushort uc = ch.unicode();
       
  3076     return (uc == ' ' || uc == '\t' || uc == '\n' || uc == '\r');
       
  3077 }
       
  3078 
       
  3079 enum NameChar { NameBeginning, NameNotBeginning, NotName };
       
  3080 
       
  3081 static const char Begi = (char)NameBeginning;
       
  3082 static const char NtBg = (char)NameNotBeginning;
       
  3083 static const char NotN = (char)NotName;
       
  3084 
       
  3085 static const char nameCharTable[128] =
       
  3086 {
       
  3087 // 0x00
       
  3088     NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
       
  3089     NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
       
  3090 // 0x10
       
  3091     NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
       
  3092     NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
       
  3093 // 0x20 (0x2D is '-', 0x2E is '.')
       
  3094     NotN, NotN, NotN, NotN, NotN, NotN, NotN, NotN,
       
  3095     NotN, NotN, NotN, NotN, NotN, NtBg, NtBg, NotN,
       
  3096 // 0x30 (0x30..0x39 are '0'..'9', 0x3A is ':')
       
  3097     NtBg, NtBg, NtBg, NtBg, NtBg, NtBg, NtBg, NtBg,
       
  3098     NtBg, NtBg, Begi, NotN, NotN, NotN, NotN, NotN,
       
  3099 // 0x40 (0x41..0x5A are 'A'..'Z')
       
  3100     NotN, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
       
  3101     Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
       
  3102 // 0x50 (0x5F is '_')
       
  3103     Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
       
  3104     Begi, Begi, Begi, NotN, NotN, NotN, NotN, Begi,
       
  3105 // 0x60 (0x61..0x7A are 'a'..'z')
       
  3106     NotN, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
       
  3107     Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
       
  3108 // 0x70
       
  3109     Begi, Begi, Begi, Begi, Begi, Begi, Begi, Begi,
       
  3110     Begi, Begi, Begi, NotN, NotN, NotN, NotN, NotN
       
  3111 };
       
  3112 
       
  3113 static inline NameChar fastDetermineNameChar(QChar ch)
       
  3114 {
       
  3115     ushort uc = ch.unicode();
       
  3116     if (!(uc & ~0x7f)) // uc < 128
       
  3117         return (NameChar)nameCharTable[uc];
       
  3118 
       
  3119     QChar::Category cat = ch.category();
       
  3120     // ### some these categories might be slightly wrong
       
  3121     if ((cat >= QChar::Letter_Uppercase && cat <= QChar::Letter_Other)
       
  3122         || cat == QChar::Number_Letter)
       
  3123         return NameBeginning;
       
  3124     if ((cat >= QChar::Number_DecimalDigit && cat <= QChar::Number_Other)
       
  3125                 || (cat >= QChar::Mark_NonSpacing && cat <= QChar::Mark_Enclosing))
       
  3126         return NameNotBeginning;
       
  3127     return NotName;
       
  3128 }
       
  3129 
       
  3130 static NameChar determineNameChar(QChar ch)
       
  3131 {
       
  3132     return fastDetermineNameChar(ch);
       
  3133 }
       
  3134 
       
  3135 /*!
       
  3136     Constructs a simple XML reader.
       
  3137 
       
  3138 */
       
  3139 QXmlSimpleReader::QXmlSimpleReader()
       
  3140     : d_ptr(new QXmlSimpleReaderPrivate(this))
       
  3141 {
       
  3142 }
       
  3143 
       
  3144 /*!
       
  3145     Destroys the simple XML reader.
       
  3146 */
       
  3147 QXmlSimpleReader::~QXmlSimpleReader()
       
  3148 {
       
  3149 }
       
  3150 
       
  3151 /*!
       
  3152     \reimp
       
  3153 */
       
  3154 bool QXmlSimpleReader::feature(const QString& name, bool *ok) const
       
  3155 {
       
  3156     const QXmlSimpleReaderPrivate *d = d_func();
       
  3157 
       
  3158     // Qt5 ###: Change these strings to qt.nokia.com
       
  3159     if (ok != 0)
       
  3160         *ok = true;
       
  3161     if (name == QLatin1String("http://xml.org/sax/features/namespaces")) {
       
  3162         return d->useNamespaces;
       
  3163     } else if (name == QLatin1String("http://xml.org/sax/features/namespace-prefixes")) {
       
  3164         return d->useNamespacePrefixes;
       
  3165     } else if (name == QLatin1String("http://trolltech.com/xml/features/report-whitespace-only-CharData")) { // Shouldn't change in Qt 4
       
  3166         return d->reportWhitespaceCharData;
       
  3167     } else if (name == QLatin1String("http://trolltech.com/xml/features/report-start-end-entity")) { // Shouldn't change in Qt 4
       
  3168         return d->reportEntities;
       
  3169     } else {
       
  3170         qWarning("Unknown feature %s", name.toLatin1().data());
       
  3171         if (ok != 0)
       
  3172             *ok = false;
       
  3173     }
       
  3174     return false;
       
  3175 }
       
  3176 
       
  3177 /*!
       
  3178     Turns on the feature \a name if \a enable is true; otherwise turns it off.
       
  3179 
       
  3180     The \a name parameter must be one of the following strings:
       
  3181     \table
       
  3182     \header \i Feature \i Default \i Notes
       
  3183     \row \i \e http://xml.org/sax/features/namespaces
       
  3184          \i true
       
  3185          \i If enabled, namespaces are reported to the content handler.
       
  3186     \row \i \e http://xml.org/sax/features/namespace-prefixes
       
  3187          \i false
       
  3188          \i If enabled, the original prefixed names
       
  3189             and attributes used for namespace declarations are
       
  3190             reported.
       
  3191     \row \i \e http://trolltech.com/xml/features/report-whitespace-only-CharData
       
  3192          \i true
       
  3193          \i If enabled, CharData that consist of
       
  3194             only whitespace characters are reported
       
  3195             using QXmlContentHandler::characters(). If disabled, whitespace is silently
       
  3196             discarded.
       
  3197     \row \i \e http://trolltech.com/xml/features/report-start-end-entity
       
  3198          \i false
       
  3199          \i If enabled, the parser reports
       
  3200             QXmlContentHandler::startEntity() and
       
  3201             QXmlContentHandler::endEntity() events, so character data
       
  3202             might be reported in chunks.
       
  3203             If disabled, the parser does not report these events, but
       
  3204             silently substitutes the entities, and reports the character
       
  3205             data in one chunk.
       
  3206     \endtable
       
  3207 
       
  3208     \sa feature(), hasFeature(), {SAX2 Features}
       
  3209 */
       
  3210 void QXmlSimpleReader::setFeature(const QString& name, bool enable)
       
  3211 {
       
  3212     Q_D(QXmlSimpleReader);
       
  3213     // Qt5 ###: Change these strings to qt.nokia.com
       
  3214     if (name == QLatin1String("http://xml.org/sax/features/namespaces")) {
       
  3215         d->useNamespaces = enable;
       
  3216     } else if (name == QLatin1String("http://xml.org/sax/features/namespace-prefixes")) {
       
  3217         d->useNamespacePrefixes = enable;
       
  3218     } else if (name == QLatin1String("http://trolltech.com/xml/features/report-whitespace-only-CharData")) { // Shouldn't change in Qt 4
       
  3219         d->reportWhitespaceCharData = enable;
       
  3220     } else if (name == QLatin1String("http://trolltech.com/xml/features/report-start-end-entity")) { // Shouldn't change in Qt 4
       
  3221         d->reportEntities = enable;
       
  3222     } else {
       
  3223         qWarning("Unknown feature %s", name.toLatin1().data());
       
  3224     }
       
  3225 }
       
  3226 
       
  3227 /*! \reimp
       
  3228 */
       
  3229 bool QXmlSimpleReader::hasFeature(const QString& name) const
       
  3230 {
       
  3231     // Qt5 ###: Change these strings to qt.nokia.com
       
  3232     if (name == QLatin1String("http://xml.org/sax/features/namespaces")
       
  3233         || name == QLatin1String("http://xml.org/sax/features/namespace-prefixes")
       
  3234         || name == QLatin1String("http://trolltech.com/xml/features/report-whitespace-only-CharData") // Shouldn't change in Qt 4
       
  3235         || name == QLatin1String("http://trolltech.com/xml/features/report-start-end-entity")) { // Shouldn't change in Qt 4
       
  3236         return true;
       
  3237     } else {
       
  3238         return false;
       
  3239     }
       
  3240 }
       
  3241 
       
  3242 /*! \reimp
       
  3243 */
       
  3244 void* QXmlSimpleReader::property(const QString&, bool *ok) const
       
  3245 {
       
  3246     if (ok != 0)
       
  3247         *ok = false;
       
  3248     return 0;
       
  3249 }
       
  3250 
       
  3251 /*! \reimp
       
  3252 */
       
  3253 void QXmlSimpleReader::setProperty(const QString&, void*)
       
  3254 {
       
  3255 }
       
  3256 
       
  3257 /*!
       
  3258     \reimp
       
  3259 */
       
  3260 bool QXmlSimpleReader::hasProperty(const QString&) const
       
  3261 {
       
  3262     return false;
       
  3263 }
       
  3264 
       
  3265 /*!
       
  3266     \reimp
       
  3267 */
       
  3268 void QXmlSimpleReader::setEntityResolver(QXmlEntityResolver* handler)
       
  3269 {
       
  3270     Q_D(QXmlSimpleReader);
       
  3271     d->entityRes = handler;
       
  3272 }
       
  3273 
       
  3274 /*!
       
  3275     \reimp
       
  3276 */
       
  3277 QXmlEntityResolver* QXmlSimpleReader::entityResolver() const
       
  3278 {
       
  3279     const QXmlSimpleReaderPrivate *d = d_func();
       
  3280     return d->entityRes;
       
  3281 }
       
  3282 
       
  3283 /*!
       
  3284     \reimp
       
  3285 */
       
  3286 void QXmlSimpleReader::setDTDHandler(QXmlDTDHandler* handler)
       
  3287 {
       
  3288     Q_D(QXmlSimpleReader);
       
  3289     d->dtdHnd = handler;
       
  3290 }
       
  3291 
       
  3292 /*!
       
  3293     \reimp
       
  3294 */
       
  3295 QXmlDTDHandler* QXmlSimpleReader::DTDHandler() const
       
  3296 {
       
  3297     const QXmlSimpleReaderPrivate *d = d_func();
       
  3298     return d->dtdHnd;
       
  3299 }
       
  3300 
       
  3301 /*!
       
  3302     \reimp
       
  3303 */
       
  3304 void QXmlSimpleReader::setContentHandler(QXmlContentHandler* handler)
       
  3305 {
       
  3306     Q_D(QXmlSimpleReader);
       
  3307     d->contentHnd = handler;
       
  3308 }
       
  3309 
       
  3310 /*!
       
  3311     \reimp
       
  3312 */
       
  3313 QXmlContentHandler* QXmlSimpleReader::contentHandler() const
       
  3314 {
       
  3315     const QXmlSimpleReaderPrivate *d = d_func();
       
  3316     return d->contentHnd;
       
  3317 }
       
  3318 
       
  3319 /*!
       
  3320     \reimp
       
  3321 */
       
  3322 void QXmlSimpleReader::setErrorHandler(QXmlErrorHandler* handler)
       
  3323 {
       
  3324     Q_D(QXmlSimpleReader);
       
  3325     d->errorHnd = handler;
       
  3326 }
       
  3327 
       
  3328 /*!
       
  3329     \reimp
       
  3330 */
       
  3331 QXmlErrorHandler* QXmlSimpleReader::errorHandler() const
       
  3332 {
       
  3333     const QXmlSimpleReaderPrivate *d = d_func();
       
  3334     return d->errorHnd;
       
  3335 }
       
  3336 
       
  3337 /*!
       
  3338     \reimp
       
  3339 */
       
  3340 void QXmlSimpleReader::setLexicalHandler(QXmlLexicalHandler* handler)
       
  3341 {
       
  3342     Q_D(QXmlSimpleReader);
       
  3343     d->lexicalHnd = handler;
       
  3344 }
       
  3345 
       
  3346 /*!
       
  3347     \reimp
       
  3348 */
       
  3349 QXmlLexicalHandler* QXmlSimpleReader::lexicalHandler() const
       
  3350 {
       
  3351     const QXmlSimpleReaderPrivate *d = d_func();
       
  3352     return d->lexicalHnd;
       
  3353 }
       
  3354 
       
  3355 /*!
       
  3356     \reimp
       
  3357 */
       
  3358 void QXmlSimpleReader::setDeclHandler(QXmlDeclHandler* handler)
       
  3359 {
       
  3360     Q_D(QXmlSimpleReader);
       
  3361     d->declHnd = handler;
       
  3362 }
       
  3363 
       
  3364 /*!
       
  3365     \reimp
       
  3366 */
       
  3367 QXmlDeclHandler* QXmlSimpleReader::declHandler() const
       
  3368 {
       
  3369     const QXmlSimpleReaderPrivate *d = d_func();
       
  3370     return d->declHnd;
       
  3371 }
       
  3372 
       
  3373 
       
  3374 
       
  3375 /*!
       
  3376     \reimp
       
  3377 */
       
  3378 bool QXmlSimpleReader::parse(const QXmlInputSource& input)
       
  3379 {
       
  3380     return parse(&input, false);
       
  3381 }
       
  3382 
       
  3383 /*!
       
  3384     Reads an XML document from \a input and parses it in one pass (non-incrementally).
       
  3385     Returns true if the parsing was successful; otherwise returns false.
       
  3386 */
       
  3387 bool QXmlSimpleReader::parse(const QXmlInputSource* input)
       
  3388 {
       
  3389     return parse(input, false);
       
  3390 }
       
  3391 
       
  3392 /*!
       
  3393     Reads an XML document from \a input and parses it. Returns true
       
  3394     if the parsing is completed successfully; otherwise returns false,
       
  3395     indicating that an error occurred.
       
  3396 
       
  3397     If \a incremental is false, this function will return false if the XML
       
  3398     file is not read completely. The parsing cannot be continued in this
       
  3399     case.
       
  3400 
       
  3401     If \a incremental is true, the parser does not return false if
       
  3402     it reaches the end of the \a input before reaching the end
       
  3403     of the XML file. Instead, it stores the state of the parser so that
       
  3404     parsing can be continued later when more data is available.
       
  3405     In such a case, you can use the function parseContinue() to
       
  3406     continue with parsing. This class stores a pointer to the input
       
  3407     source \a input and the parseContinue() function tries to read from
       
  3408     that input source. Therefore, you should not delete the input
       
  3409     source \a input until you no longer need to call parseContinue().
       
  3410 
       
  3411     If this function is called with \a incremental set to true
       
  3412     while an incremental parse is in progress, a new parsing
       
  3413     session will be started, and the previous session will be lost.
       
  3414 
       
  3415     \sa parseContinue(), QTcpSocket
       
  3416 */
       
  3417 bool QXmlSimpleReader::parse(const QXmlInputSource *input, bool incremental)
       
  3418 {
       
  3419     Q_D(QXmlSimpleReader);
       
  3420 
       
  3421     if (incremental) {
       
  3422         d->initIncrementalParsing();
       
  3423     } else {
       
  3424         delete d->parseStack;
       
  3425         d->parseStack = 0;
       
  3426     }
       
  3427     d->init(input);
       
  3428 
       
  3429     // call the handler
       
  3430     if (d->contentHnd) {
       
  3431         d->contentHnd->setDocumentLocator(d->locator.data());
       
  3432         if (!d->contentHnd->startDocument()) {
       
  3433             d->reportParseError(d->contentHnd->errorString());
       
  3434             d->tags.clear();
       
  3435             return false;
       
  3436         }
       
  3437     }
       
  3438     qt_xml_skipped_entity_in_content = false;
       
  3439     return d->parseBeginOrContinue(0, incremental);
       
  3440 }
       
  3441 
       
  3442 /*!
       
  3443     Continues incremental parsing, taking input from the
       
  3444     QXmlInputSource that was specified with the most recent
       
  3445     call to parse(). To use this function, you \e must have called
       
  3446     parse() with the incremental argument set to true.
       
  3447 
       
  3448     Returns false if a parsing error occurs; otherwise returns true,
       
  3449     even if the end of the XML file has not been reached. You can
       
  3450     continue parsing at a later stage by calling this function again
       
  3451     when there is more data available to parse.
       
  3452 
       
  3453     Calling this function when there is no data available in the input
       
  3454     source indicates to the reader that the end of the XML file has
       
  3455     been reached. If the input supplied up to this point was
       
  3456     not well-formed then a parsing error occurs, and false is returned.
       
  3457     If the input supplied was well-formed, true is returned.
       
  3458     It is important to end the input in this way because it allows you
       
  3459     to reuse the reader to parse other XML files.
       
  3460 
       
  3461     Calling this function after the end of file has been reached, but
       
  3462     without available data will cause false to be returned whether the
       
  3463     previous input was well-formed or not.
       
  3464 
       
  3465     \sa parse(), QXmlInputSource::data(), QXmlInputSource::next()
       
  3466 */
       
  3467 bool QXmlSimpleReader::parseContinue()
       
  3468 {
       
  3469     Q_D(QXmlSimpleReader);
       
  3470     if (d->parseStack == 0 || d->parseStack->isEmpty())
       
  3471         return false;
       
  3472     d->initData();
       
  3473     int state = d->parseStack->pop().state;
       
  3474     return d->parseBeginOrContinue(state, true);
       
  3475 }
       
  3476 
       
  3477 /*
       
  3478   Common part of parse() and parseContinue()
       
  3479 */
       
  3480 bool QXmlSimpleReaderPrivate::parseBeginOrContinue(int state, bool incremental)
       
  3481 {
       
  3482     bool atEndOrig = atEnd();
       
  3483 
       
  3484     if (state==0) {
       
  3485         if (!parseProlog()) {
       
  3486             if (incremental && error.isNull()) {
       
  3487                 pushParseState(0, 0);
       
  3488                 return true;
       
  3489             } else {
       
  3490                 tags.clear();
       
  3491                 return false;
       
  3492             }
       
  3493         }
       
  3494         state = 1;
       
  3495     }
       
  3496     if (state==1) {
       
  3497         if (!parseElement()) {
       
  3498             if (incremental && error.isNull()) {
       
  3499                 pushParseState(0, 1);
       
  3500                 return true;
       
  3501             } else {
       
  3502                 tags.clear();
       
  3503                 return false;
       
  3504             }
       
  3505         }
       
  3506         state = 2;
       
  3507     }
       
  3508     // parse Misc*
       
  3509     while (!atEnd()) {
       
  3510         if (!parseMisc()) {
       
  3511             if (incremental && error.isNull()) {
       
  3512                 pushParseState(0, 2);
       
  3513                 return true;
       
  3514             } else {
       
  3515                 tags.clear();
       
  3516                 return false;
       
  3517             }
       
  3518         }
       
  3519     }
       
  3520     if (!atEndOrig && incremental) {
       
  3521         // we parsed something at all, so be prepared to come back later
       
  3522         pushParseState(0, 2);
       
  3523         return true;
       
  3524     }
       
  3525     // is stack empty?
       
  3526     if (!tags.isEmpty() && !error.isNull()) {
       
  3527         reportParseError(QLatin1String(XMLERR_UNEXPECTEDEOF));
       
  3528         tags.clear();
       
  3529         return false;
       
  3530     }
       
  3531     // call the handler
       
  3532     if (contentHnd) {
       
  3533         delete parseStack;
       
  3534         parseStack = 0;
       
  3535         if (!contentHnd->endDocument()) {
       
  3536             reportParseError(contentHnd->errorString());
       
  3537             return false;
       
  3538         }
       
  3539     }
       
  3540     return true;
       
  3541 }
       
  3542 
       
  3543 //
       
  3544 // The following private parse functions have another semantics for the return
       
  3545 // value: They return true iff parsing has finished successfully (i.e. the end
       
  3546 // of the XML file must be reached!). If one of these functions return false,
       
  3547 // there is only an error when d->error.isNULL() is also false.
       
  3548 //
       
  3549 
       
  3550 /*
       
  3551   For the incremental parsing, it is very important that the parse...()
       
  3552   functions have a certain structure. Since it might be hard to understand how
       
  3553   they work, here is a description of the layout of these functions:
       
  3554 
       
  3555     bool QXmlSimpleReader::parse...()
       
  3556     {
       
  3557 (1)        const signed char Init             = 0;
       
  3558         ...
       
  3559 
       
  3560 (2)        const signed char Inp...           = 0;
       
  3561         ...
       
  3562 
       
  3563 (3)        static const signed char table[3][2] = {
       
  3564         ...
       
  3565         };
       
  3566         signed char state;
       
  3567         signed char input;
       
  3568 
       
  3569 (4)        if (d->parseStack == 0 || d->parseStack->isEmpty()) {
       
  3570 (4a)        ...
       
  3571         } else {
       
  3572 (4b)        ...
       
  3573         }
       
  3574 
       
  3575         for (; ;) {
       
  3576 (5)            switch (state) {
       
  3577             ...
       
  3578             }
       
  3579 
       
  3580 (6)
       
  3581 (6a)            if (atEnd()) {
       
  3582                 unexpectedEof(&QXmlSimpleReader::parseNmtoken, state);
       
  3583                 return false;
       
  3584             }
       
  3585 (6b)            if (determineNameChar(c) != NotName) {
       
  3586             ...
       
  3587             }
       
  3588 (7)            state = table[state][input];
       
  3589 
       
  3590 (8)            switch (state) {
       
  3591             ...
       
  3592             }
       
  3593         }
       
  3594     }
       
  3595 
       
  3596   Explanation:
       
  3597   ad 1: constants for the states (used in the transition table)
       
  3598   ad 2: constants for the input (used in the transition table)
       
  3599   ad 3: the transition table for the state machine
       
  3600   ad 4: test if we are in a parseContinue() step
       
  3601         a) if no, do inititalizations
       
  3602         b) if yes, restore the state and call parse functions recursively
       
  3603   ad 5: Do some actions according to the state; from the logical execution
       
  3604         order, this code belongs after 8 (see there for an explanation)
       
  3605   ad 6: Check the character that is at the actual "cursor" position:
       
  3606         a) If we reached the EOF, report either error or push the state (in the
       
  3607            case of incremental parsing).
       
  3608         b) Otherwise, set the input character constant for the transition
       
  3609            table.
       
  3610   ad 7: Get the new state according to the input that was read.
       
  3611   ad 8: Do some actions according to the state. The last line in every case
       
  3612         statement reads new data (i.e. it move the cursor). This can also be
       
  3613         done by calling another parse...() function. If you need processing for
       
  3614         this state after that, you have to put it into the switch statement 5.
       
  3615         This ensures that you have a well defined re-entry point, when you ran
       
  3616         out of data.
       
  3617 */
       
  3618 
       
  3619 /*
       
  3620   Parses the prolog [22].
       
  3621 */
       
  3622 
       
  3623 bool QXmlSimpleReaderPrivate::parseProlog()
       
  3624 {
       
  3625     const signed char Init             = 0;
       
  3626     const signed char EatWS            = 1; // eat white spaces
       
  3627     const signed char Lt               = 2; // '<' read
       
  3628     const signed char Em               = 3; // '!' read
       
  3629     const signed char DocType          = 4; // read doctype
       
  3630     const signed char Comment          = 5; // read comment
       
  3631     const signed char CommentR         = 6; // same as Comment, but already reported
       
  3632     const signed char PInstr           = 7; // read PI
       
  3633     const signed char PInstrR          = 8; // same as PInstr, but already reported
       
  3634     const signed char Done             = 9;
       
  3635 
       
  3636     const signed char InpWs            = 0;
       
  3637     const signed char InpLt            = 1; // <
       
  3638     const signed char InpQm            = 2; // ?
       
  3639     const signed char InpEm            = 3; // !
       
  3640     const signed char InpD             = 4; // D
       
  3641     const signed char InpDash          = 5; // -
       
  3642     const signed char InpUnknown       = 6;
       
  3643 
       
  3644     static const signed char table[9][7] = {
       
  3645      /*  InpWs   InpLt  InpQm  InpEm  InpD      InpDash  InpUnknown */
       
  3646         { EatWS,  Lt,    -1,    -1,    -1,       -1,       -1      }, // Init
       
  3647         { -1,     Lt,    -1,    -1,    -1,       -1,       -1      }, // EatWS
       
  3648         { -1,     -1,    PInstr,Em,    Done,     -1,       Done    }, // Lt
       
  3649         { -1,     -1,    -1,    -1,    DocType,  Comment,  -1      }, // Em
       
  3650         { EatWS,  Lt,    -1,    -1,    -1,       -1,       -1      }, // DocType
       
  3651         { EatWS,  Lt,    -1,    -1,    -1,       -1,       -1      }, // Comment
       
  3652         { EatWS,  Lt,    -1,    -1,    -1,       -1,       -1      }, // CommentR
       
  3653         { EatWS,  Lt,    -1,    -1,    -1,       -1,       -1      }, // PInstr
       
  3654         { EatWS,  Lt,    -1,    -1,    -1,       -1,       -1      }  // PInstrR
       
  3655     };
       
  3656     signed char state;
       
  3657     signed char input;
       
  3658 
       
  3659     if (parseStack == 0 || parseStack->isEmpty()) {
       
  3660         xmldecl_possible = true;
       
  3661         doctype_read = false;
       
  3662         state = Init;
       
  3663     } else {
       
  3664         state = parseStack->pop().state;
       
  3665 #if defined(QT_QXML_DEBUG)
       
  3666         qDebug("QXmlSimpleReader: parseProlog (cont) in state %d", state);
       
  3667 #endif
       
  3668         if (!parseStack->isEmpty()) {
       
  3669             ParseFunction function = parseStack->top().function;
       
  3670             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  3671                 parseStack->pop();
       
  3672 #if defined(QT_QXML_DEBUG)
       
  3673                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  3674 #endif
       
  3675             }
       
  3676             if (!(this->*function)()) {
       
  3677                 parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
       
  3678                 return false;
       
  3679             }
       
  3680         }
       
  3681     }
       
  3682 
       
  3683     for (;;) {
       
  3684         switch (state) {
       
  3685             case DocType:
       
  3686                 if (doctype_read) {
       
  3687                     reportParseError(QLatin1String(XMLERR_MORETHANONEDOCTYPE));
       
  3688                     return false;
       
  3689                 } else {
       
  3690                     doctype_read = false;
       
  3691                 }
       
  3692                 break;
       
  3693             case Comment:
       
  3694                 if (lexicalHnd) {
       
  3695                     if (!lexicalHnd->comment(string())) {
       
  3696                         reportParseError(lexicalHnd->errorString());
       
  3697                         return false;
       
  3698                     }
       
  3699                 }
       
  3700                 state = CommentR;
       
  3701                 break;
       
  3702             case PInstr:
       
  3703                 // call the handler
       
  3704                 if (contentHnd) {
       
  3705                     if (xmldecl_possible && !xmlVersion.isEmpty()) {
       
  3706                         QString value(QLatin1String("version='"));
       
  3707                         value += xmlVersion;
       
  3708                         value += QLatin1Char('\'');
       
  3709                         if (!encoding.isEmpty()) {
       
  3710                             value += QLatin1String(" encoding='");
       
  3711                             value += encoding;
       
  3712                             value += QLatin1Char('\'');
       
  3713                         }
       
  3714                         if (standalone == QXmlSimpleReaderPrivate::Yes) {
       
  3715                             value += QLatin1String(" standalone='yes'");
       
  3716                         } else if (standalone == QXmlSimpleReaderPrivate::No) {
       
  3717                             value += QLatin1String(" standalone='no'");
       
  3718                         }
       
  3719                         if (!contentHnd->processingInstruction(QLatin1String("xml"), value)) {
       
  3720                             reportParseError(contentHnd->errorString());
       
  3721                             return false;
       
  3722                         }
       
  3723                     } else {
       
  3724                         if (!contentHnd->processingInstruction(name(), string())) {
       
  3725                             reportParseError(contentHnd->errorString());
       
  3726                             return false;
       
  3727                         }
       
  3728                     }
       
  3729                 }
       
  3730                 // XML declaration only on first position possible
       
  3731                 xmldecl_possible = false;
       
  3732                 state = PInstrR;
       
  3733                 break;
       
  3734             case Done:
       
  3735                 return true;
       
  3736             case -1:
       
  3737                 reportParseError(QLatin1String(XMLERR_ERRORPARSINGELEMENT));
       
  3738                 return false;
       
  3739         }
       
  3740 
       
  3741         if (atEnd()) {
       
  3742             unexpectedEof(&QXmlSimpleReaderPrivate::parseProlog, state);
       
  3743             return false;
       
  3744         }
       
  3745         if (is_S(c)) {
       
  3746             input = InpWs;
       
  3747         } else if (c == QLatin1Char('<')) {
       
  3748             input = InpLt;
       
  3749         } else if (c == QLatin1Char('?')) {
       
  3750             input = InpQm;
       
  3751         } else if (c == QLatin1Char('!')) {
       
  3752             input = InpEm;
       
  3753         } else if (c == QLatin1Char('D')) {
       
  3754             input = InpD;
       
  3755         } else if (c == QLatin1Char('-')) {
       
  3756             input = InpDash;
       
  3757         } else {
       
  3758             input = InpUnknown;
       
  3759         }
       
  3760         state = table[state][input];
       
  3761 
       
  3762         switch (state) {
       
  3763             case EatWS:
       
  3764                 // XML declaration only on first position possible
       
  3765                 xmldecl_possible = false;
       
  3766                 if (!eat_ws()) {
       
  3767                     parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
       
  3768                     return false;
       
  3769                 }
       
  3770                 break;
       
  3771             case Lt:
       
  3772                 next();
       
  3773                 break;
       
  3774             case Em:
       
  3775                 // XML declaration only on first position possible
       
  3776                 xmldecl_possible = false;
       
  3777                 next();
       
  3778                 break;
       
  3779             case DocType:
       
  3780                 if (!parseDoctype()) {
       
  3781                     parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
       
  3782                     return false;
       
  3783                 }
       
  3784                 break;
       
  3785             case Comment:
       
  3786             case CommentR:
       
  3787                 if (!parseComment()) {
       
  3788                     parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
       
  3789                     return false;
       
  3790                 }
       
  3791                 break;
       
  3792             case PInstr:
       
  3793             case PInstrR:
       
  3794                 parsePI_xmldecl = xmldecl_possible;
       
  3795                 if (!parsePI()) {
       
  3796                     parseFailed(&QXmlSimpleReaderPrivate::parseProlog, state);
       
  3797                     return false;
       
  3798                 }
       
  3799                 break;
       
  3800         }
       
  3801     }
       
  3802     return false;
       
  3803 }
       
  3804 
       
  3805 /*
       
  3806   Parse an element [39].
       
  3807 
       
  3808   Precondition: the opening '<' is already read.
       
  3809 */
       
  3810 bool QXmlSimpleReaderPrivate::parseElement()
       
  3811 {
       
  3812     const int Init             =  0;
       
  3813     const int ReadName         =  1;
       
  3814     const int Ws1              =  2;
       
  3815     const int STagEnd          =  3;
       
  3816     const int STagEnd2         =  4;
       
  3817     const int ETagBegin        =  5;
       
  3818     const int ETagBegin2       =  6;
       
  3819     const int Ws2              =  7;
       
  3820     const int EmptyTag         =  8;
       
  3821     const int Attrib           =  9;
       
  3822     const int AttribPro        = 10; // like Attrib, but processAttribute was already called
       
  3823     const int Ws3              = 11;
       
  3824     const int Done             = 12;
       
  3825 
       
  3826     const int InpWs            = 0; // whitespace
       
  3827     const int InpNameBe        = 1; // NameBeginning
       
  3828     const int InpGt            = 2; // >
       
  3829     const int InpSlash         = 3; // /
       
  3830     const int InpUnknown       = 4;
       
  3831 
       
  3832     static const int table[12][5] = {
       
  3833      /*  InpWs      InpNameBe    InpGt        InpSlash     InpUnknown */
       
  3834         { -1,        ReadName,    -1,          -1,          -1        }, // Init
       
  3835         { Ws1,       Attrib,      STagEnd,     EmptyTag,    -1        }, // ReadName
       
  3836         { -1,        Attrib,      STagEnd,     EmptyTag,    -1        }, // Ws1
       
  3837         { STagEnd2,  STagEnd2,    STagEnd2,    STagEnd2,    STagEnd2  }, // STagEnd
       
  3838         { -1,        -1,          -1,          ETagBegin,   -1        }, // STagEnd2
       
  3839         { -1,        ETagBegin2,  -1,          -1,          -1        }, // ETagBegin
       
  3840         { Ws2,       -1,          Done,        -1,          -1        }, // ETagBegin2
       
  3841         { -1,        -1,          Done,        -1,          -1        }, // Ws2
       
  3842         { -1,        -1,          Done,        -1,          -1        }, // EmptyTag
       
  3843         { Ws3,       Attrib,      STagEnd,     EmptyTag,    -1        }, // Attrib
       
  3844         { Ws3,       Attrib,      STagEnd,     EmptyTag,    -1        }, // AttribPro
       
  3845         { -1,        Attrib,      STagEnd,     EmptyTag,    -1        }  // Ws3
       
  3846     };
       
  3847     int state;
       
  3848     int input;
       
  3849 
       
  3850     if (parseStack == 0 || parseStack->isEmpty()) {
       
  3851         state = Init;
       
  3852     } else {
       
  3853         state = parseStack->pop().state;
       
  3854 #if defined(QT_QXML_DEBUG)
       
  3855         qDebug("QXmlSimpleReader: parseElement (cont) in state %d", state);
       
  3856 #endif
       
  3857         if (!parseStack->isEmpty()) {
       
  3858             ParseFunction function = parseStack->top().function;
       
  3859             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  3860                 parseStack->pop();
       
  3861 #if defined(QT_QXML_DEBUG)
       
  3862                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  3863 #endif
       
  3864             }
       
  3865             if (!(this->*function)()) {
       
  3866                 parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
       
  3867                 return false;
       
  3868             }
       
  3869         }
       
  3870     }
       
  3871 
       
  3872     for (;;) {
       
  3873         switch (state) {
       
  3874             case ReadName:
       
  3875                 // store it on the stack
       
  3876                 tags.push(name());
       
  3877                 // empty the attributes
       
  3878                 attList.clear();
       
  3879                 if (useNamespaces)
       
  3880                     namespaceSupport.pushContext();
       
  3881                 break;
       
  3882             case ETagBegin2:
       
  3883                 if (!processElementETagBegin2())
       
  3884                     return false;
       
  3885                 break;
       
  3886             case Attrib:
       
  3887                 if (!processElementAttribute())
       
  3888                     return false;
       
  3889                 state = AttribPro;
       
  3890                 break;
       
  3891             case Done:
       
  3892                 return true;
       
  3893             case -1:
       
  3894                 reportParseError(QLatin1String(XMLERR_ERRORPARSINGELEMENT));
       
  3895                 return false;
       
  3896         }
       
  3897 
       
  3898         if (atEnd()) {
       
  3899             unexpectedEof(&QXmlSimpleReaderPrivate::parseElement, state);
       
  3900             return false;
       
  3901         }
       
  3902         if (fastDetermineNameChar(c) == NameBeginning) {
       
  3903             input = InpNameBe;
       
  3904         } else if (c == QLatin1Char('>')) {
       
  3905             input = InpGt;
       
  3906         } else if (is_S(c)) {
       
  3907             input = InpWs;
       
  3908         } else if (c == QLatin1Char('/')) {
       
  3909             input = InpSlash;
       
  3910         } else {
       
  3911             input = InpUnknown;
       
  3912         }
       
  3913         state = table[state][input];
       
  3914 
       
  3915         switch (state) {
       
  3916             case ReadName:
       
  3917                 parseName_useRef = false;
       
  3918                 if (!parseName()) {
       
  3919                     parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
       
  3920                     return false;
       
  3921                 }
       
  3922                 break;
       
  3923             case Ws1:
       
  3924             case Ws2:
       
  3925             case Ws3:
       
  3926                 if (!eat_ws()) {
       
  3927                     parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
       
  3928                     return false;
       
  3929                 }
       
  3930                 break;
       
  3931             case STagEnd:
       
  3932                 // call the handler
       
  3933                 if (contentHnd) {
       
  3934                     const QString &tagsTop = tags.top();
       
  3935                     if (useNamespaces) {
       
  3936                         QString uri, lname;
       
  3937                         namespaceSupport.processName(tagsTop, false, uri, lname);
       
  3938                         if (!contentHnd->startElement(uri, lname, tagsTop, attList)) {
       
  3939                             reportParseError(contentHnd->errorString());
       
  3940                             return false;
       
  3941                         }
       
  3942                     } else {
       
  3943                         if (!contentHnd->startElement(QString(), QString(), tagsTop, attList)) {
       
  3944                             reportParseError(contentHnd->errorString());
       
  3945                             return false;
       
  3946                         }
       
  3947                     }
       
  3948                 }
       
  3949                 next();
       
  3950                 break;
       
  3951             case STagEnd2:
       
  3952                 if (!parseContent()) {
       
  3953                     parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
       
  3954                     return false;
       
  3955                 }
       
  3956                 break;
       
  3957             case ETagBegin:
       
  3958                 next();
       
  3959                 break;
       
  3960             case ETagBegin2:
       
  3961                 // get the name of the tag
       
  3962                 parseName_useRef = false;
       
  3963                 if (!parseName()) {
       
  3964                     parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
       
  3965                     return false;
       
  3966                 }
       
  3967                 break;
       
  3968             case EmptyTag:
       
  3969                 if  (tags.isEmpty()) {
       
  3970                     reportParseError(QLatin1String(XMLERR_TAGMISMATCH));
       
  3971                     return false;
       
  3972                 }
       
  3973                 if (!processElementEmptyTag())
       
  3974                     return false;
       
  3975                 next();
       
  3976                 break;
       
  3977             case Attrib:
       
  3978             case AttribPro:
       
  3979                 // get name and value of attribute
       
  3980                 if (!parseAttribute()) {
       
  3981                     parseFailed(&QXmlSimpleReaderPrivate::parseElement, state);
       
  3982                     return false;
       
  3983                 }
       
  3984                 break;
       
  3985             case Done:
       
  3986                 next();
       
  3987                 break;
       
  3988         }
       
  3989     }
       
  3990     return false;
       
  3991 }
       
  3992 
       
  3993 /*
       
  3994   Helper to break down the size of the code in the case statement.
       
  3995   Return false on error, otherwise true.
       
  3996 */
       
  3997 bool QXmlSimpleReaderPrivate::processElementEmptyTag()
       
  3998 {
       
  3999     QString uri, lname;
       
  4000     // pop the stack and call the handler
       
  4001     if (contentHnd) {
       
  4002         if (useNamespaces) {
       
  4003             // report startElement first...
       
  4004             namespaceSupport.processName(tags.top(), false, uri, lname);
       
  4005             if (!contentHnd->startElement(uri, lname, tags.top(), attList)) {
       
  4006                 reportParseError(contentHnd->errorString());
       
  4007                 return false;
       
  4008             }
       
  4009             // ... followed by endElement...
       
  4010             if (!contentHnd->endElement(uri, lname, tags.pop())) {
       
  4011                 reportParseError(contentHnd->errorString());
       
  4012                 return false;
       
  4013             }
       
  4014             // ... followed by endPrefixMapping
       
  4015             QStringList prefixesBefore, prefixesAfter;
       
  4016             if (contentHnd) {
       
  4017                 prefixesBefore = namespaceSupport.prefixes();
       
  4018             }
       
  4019             namespaceSupport.popContext();
       
  4020             // call the handler for prefix mapping
       
  4021             prefixesAfter = namespaceSupport.prefixes();
       
  4022             for (QStringList::Iterator it = prefixesBefore.begin(); it != prefixesBefore.end(); ++it) {
       
  4023                 if (!prefixesAfter.contains(*it)) {
       
  4024                     if (!contentHnd->endPrefixMapping(*it)) {
       
  4025                         reportParseError(contentHnd->errorString());
       
  4026                         return false;
       
  4027                     }
       
  4028                 }
       
  4029             }
       
  4030         } else {
       
  4031             // report startElement first...
       
  4032             if (!contentHnd->startElement(QString(), QString(), tags.top(), attList)) {
       
  4033                 reportParseError(contentHnd->errorString());
       
  4034                 return false;
       
  4035             }
       
  4036             // ... followed by endElement
       
  4037             if (!contentHnd->endElement(QString(), QString(), tags.pop())) {
       
  4038                 reportParseError(contentHnd->errorString());
       
  4039                 return false;
       
  4040             }
       
  4041         }
       
  4042     } else {
       
  4043         tags.pop_back();
       
  4044         namespaceSupport.popContext();
       
  4045     }
       
  4046     return true;
       
  4047 }
       
  4048 /*
       
  4049   Helper to break down the size of the code in the case statement.
       
  4050   Return false on error, otherwise true.
       
  4051 */
       
  4052 bool QXmlSimpleReaderPrivate::processElementETagBegin2()
       
  4053 {
       
  4054     const QString &name = QXmlSimpleReaderPrivate::name();
       
  4055 
       
  4056     // pop the stack and compare it with the name
       
  4057     if (tags.pop() != name) {
       
  4058         reportParseError(QLatin1String(XMLERR_TAGMISMATCH));
       
  4059         return false;
       
  4060     }
       
  4061     // call the handler
       
  4062     if (contentHnd) {
       
  4063         QString uri, lname;
       
  4064 
       
  4065         if (useNamespaces)
       
  4066             namespaceSupport.processName(name, false, uri, lname);
       
  4067         if (!contentHnd->endElement(uri, lname, name)) {
       
  4068             reportParseError(contentHnd->errorString());
       
  4069             return false;
       
  4070         }
       
  4071     }
       
  4072     if (useNamespaces) {
       
  4073         NamespaceMap prefixesBefore, prefixesAfter;
       
  4074         if (contentHnd)
       
  4075             prefixesBefore = namespaceSupport.d->ns;
       
  4076 
       
  4077         namespaceSupport.popContext();
       
  4078         // call the handler for prefix mapping
       
  4079         if (contentHnd) {
       
  4080             prefixesAfter = namespaceSupport.d->ns;
       
  4081             if (prefixesBefore.size() != prefixesAfter.size()) {
       
  4082                 for (NamespaceMap::const_iterator it = prefixesBefore.constBegin(); it != prefixesBefore.constEnd(); ++it) {
       
  4083                     if (!it.key().isEmpty() && !prefixesAfter.contains(it.key())) {
       
  4084                         if (!contentHnd->endPrefixMapping(it.key())) {
       
  4085                             reportParseError(contentHnd->errorString());
       
  4086                             return false;
       
  4087                         }
       
  4088                     }
       
  4089                 }
       
  4090             }
       
  4091         }
       
  4092     }
       
  4093     return true;
       
  4094 }
       
  4095 /*
       
  4096   Helper to break down the size of the code in the case statement.
       
  4097   Return false on error, otherwise true.
       
  4098 */
       
  4099 bool QXmlSimpleReaderPrivate::processElementAttribute()
       
  4100 {
       
  4101     QString uri, lname, prefix;
       
  4102     const QString &name = QXmlSimpleReaderPrivate::name();
       
  4103     const QString &string = QXmlSimpleReaderPrivate::string();
       
  4104 
       
  4105     // add the attribute to the list
       
  4106     if (useNamespaces) {
       
  4107         // is it a namespace declaration?
       
  4108         namespaceSupport.splitName(name, prefix, lname);
       
  4109         if (prefix == QLatin1String("xmlns")) {
       
  4110             // namespace declaration
       
  4111             namespaceSupport.setPrefix(lname, string);
       
  4112             if (useNamespacePrefixes) {
       
  4113                 // according to http://www.w3.org/2000/xmlns/, the "prefix"
       
  4114                 // xmlns maps to the namespace name
       
  4115                 // http://www.w3.org/2000/xmlns/
       
  4116                 attList.append(name, QLatin1String("http://www.w3.org/2000/xmlns/"), lname, string);
       
  4117             }
       
  4118             // call the handler for prefix mapping
       
  4119             if (contentHnd) {
       
  4120                 if (!contentHnd->startPrefixMapping(lname, string)) {
       
  4121                     reportParseError(contentHnd->errorString());
       
  4122                     return false;
       
  4123                 }
       
  4124             }
       
  4125         } else {
       
  4126             // no namespace delcaration
       
  4127             namespaceSupport.processName(name, true, uri, lname);
       
  4128             attList.append(name, uri, lname, string);
       
  4129         }
       
  4130     } else {
       
  4131         // no namespace support
       
  4132         attList.append(name, uri, lname, string);
       
  4133     }
       
  4134     return true;
       
  4135 }
       
  4136 
       
  4137 /*
       
  4138   Parse a content [43].
       
  4139 
       
  4140   A content is only used between tags. If a end tag is found the < is already
       
  4141   read and the head stand on the '/' of the end tag '</name>'.
       
  4142 */
       
  4143 bool QXmlSimpleReaderPrivate::parseContent()
       
  4144 {
       
  4145     const signed char Init             =  0;
       
  4146     const signed char ChD              =  1; // CharData
       
  4147     const signed char ChD1             =  2; // CharData help state
       
  4148     const signed char ChD2             =  3; // CharData help state
       
  4149     const signed char Ref              =  4; // Reference
       
  4150     const signed char Lt               =  5; // '<' read
       
  4151     const signed char PInstr           =  6; // PI
       
  4152     const signed char PInstrR          =  7; // same as PInstr, but already reported
       
  4153     const signed char Elem             =  8; // Element
       
  4154     const signed char Em               =  9; // '!' read
       
  4155     const signed char Com              = 10; // Comment
       
  4156     const signed char ComR             = 11; // same as Com, but already reported
       
  4157     const signed char CDS              = 12; // CDSect
       
  4158     const signed char CDS1             = 13; // read a CDSect
       
  4159     const signed char CDS2             = 14; // read a CDSect (help state)
       
  4160     const signed char CDS3             = 15; // read a CDSect (help state)
       
  4161     const signed char Done             = 16; // finished reading content
       
  4162 
       
  4163     const signed char InpLt            = 0; // <
       
  4164     const signed char InpGt            = 1; // >
       
  4165     const signed char InpSlash         = 2; // /
       
  4166     const signed char InpQMark         = 3; // ?
       
  4167     const signed char InpEMark         = 4; // !
       
  4168     const signed char InpAmp           = 5; // &
       
  4169     const signed char InpDash          = 6; // -
       
  4170     const signed char InpOpenB         = 7; // [
       
  4171     const signed char InpCloseB        = 8; //]
       
  4172     const signed char InpUnknown       = 9;
       
  4173 
       
  4174     static const signed char mapCLT2FSMChar[] = {
       
  4175         InpUnknown, // white space
       
  4176         InpUnknown, // %
       
  4177         InpAmp,     // &
       
  4178         InpGt,      // >
       
  4179         InpLt,      // <
       
  4180         InpSlash,   // /
       
  4181         InpQMark,   // ?
       
  4182         InpEMark,   // !
       
  4183         InpDash,    // -
       
  4184         InpCloseB,  //]
       
  4185         InpOpenB,   // [
       
  4186         InpUnknown, // =
       
  4187         InpUnknown, // "
       
  4188         InpUnknown, // '
       
  4189         InpUnknown  // unknown
       
  4190     };
       
  4191 
       
  4192     static const signed char table[16][10] = {
       
  4193      /*  InpLt  InpGt  InpSlash  InpQMark  InpEMark  InpAmp  InpDash  InpOpenB  InpCloseB  InpUnknown */
       
  4194         { Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD1,      ChD  }, // Init
       
  4195         { Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD1,      ChD  }, // ChD
       
  4196         { Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD2,      ChD  }, // ChD1
       
  4197         { Lt,    -1,    ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD2,      ChD  }, // ChD2
       
  4198         { Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD,       ChD  }, // Ref (same as Init)
       
  4199         { -1,    -1,    Done,     PInstr,   Em,       -1,     -1,      -1,       -1,        Elem }, // Lt
       
  4200         { Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD,       ChD  }, // PInstr (same as Init)
       
  4201         { Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD,       ChD  }, // PInstrR
       
  4202         { Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD,       ChD  }, // Elem (same as Init)
       
  4203         { -1,    -1,    -1,       -1,       -1,       -1,     Com,     CDS,      -1,        -1   }, // Em
       
  4204         { Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD,       ChD  }, // Com (same as Init)
       
  4205         { Lt,    ChD,   ChD,      ChD,      ChD,      Ref,    ChD,     ChD,      ChD,       ChD  }, // ComR
       
  4206         { CDS1,  CDS1,  CDS1,     CDS1,     CDS1,     CDS1,   CDS1,    CDS1,     CDS2,      CDS1 }, // CDS
       
  4207         { CDS1,  CDS1,  CDS1,     CDS1,     CDS1,     CDS1,   CDS1,    CDS1,     CDS2,      CDS1 }, // CDS1
       
  4208         { CDS1,  CDS1,  CDS1,     CDS1,     CDS1,     CDS1,   CDS1,    CDS1,     CDS3,      CDS1 }, // CDS2
       
  4209         { CDS1,  Init,  CDS1,     CDS1,     CDS1,     CDS1,   CDS1,    CDS1,     CDS3,      CDS1 }  // CDS3
       
  4210     };
       
  4211     signed char state;
       
  4212     signed char input;
       
  4213 
       
  4214     if (parseStack == 0 || parseStack->isEmpty()) {
       
  4215         contentCharDataRead = false;
       
  4216         state = Init;
       
  4217     } else {
       
  4218         state = parseStack->pop().state;
       
  4219 #if defined(QT_QXML_DEBUG)
       
  4220         qDebug("QXmlSimpleReader: parseContent (cont) in state %d", state);
       
  4221 #endif
       
  4222         if (!parseStack->isEmpty()) {
       
  4223             ParseFunction function = parseStack->top().function;
       
  4224             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  4225                 parseStack->pop();
       
  4226 #if defined(QT_QXML_DEBUG)
       
  4227                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  4228 #endif
       
  4229             }
       
  4230             if (!(this->*function)()) {
       
  4231                 parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
       
  4232                 return false;
       
  4233             }
       
  4234         }
       
  4235     }
       
  4236 
       
  4237     for (;;) {
       
  4238         switch (state) {
       
  4239             case Ref:
       
  4240                 if (!contentCharDataRead)
       
  4241                     contentCharDataRead = parseReference_charDataRead;
       
  4242                 break;
       
  4243             case PInstr:
       
  4244                 if (contentHnd) {
       
  4245                     if (!contentHnd->processingInstruction(name(),string())) {
       
  4246                         reportParseError(contentHnd->errorString());
       
  4247                         return false;
       
  4248                     }
       
  4249                 }
       
  4250                 state = PInstrR;
       
  4251                 break;
       
  4252             case Com:
       
  4253                 if (lexicalHnd) {
       
  4254                     if (!lexicalHnd->comment(string())) {
       
  4255                         reportParseError(lexicalHnd->errorString());
       
  4256                         return false;
       
  4257                     }
       
  4258                 }
       
  4259                 state = ComR;
       
  4260                 break;
       
  4261             case CDS:
       
  4262                 stringClear();
       
  4263                 break;
       
  4264             case CDS2:
       
  4265                 if (!atEnd() && c != QLatin1Char(']'))
       
  4266                     stringAddC(QLatin1Char(']'));
       
  4267                 break;
       
  4268             case CDS3:
       
  4269                 // test if this skipping was legal
       
  4270                 if (!atEnd()) {
       
  4271                     if (c == QLatin1Char('>')) {
       
  4272                         // the end of the CDSect
       
  4273                         if (lexicalHnd) {
       
  4274                             if (!lexicalHnd->startCDATA()) {
       
  4275                                 reportParseError(lexicalHnd->errorString());
       
  4276                                 return false;
       
  4277                             }
       
  4278                         }
       
  4279                         if (contentHnd) {
       
  4280                             if (!contentHnd->characters(string())) {
       
  4281                                 reportParseError(contentHnd->errorString());
       
  4282                                 return false;
       
  4283                             }
       
  4284                         }
       
  4285                         if (lexicalHnd) {
       
  4286                             if (!lexicalHnd->endCDATA()) {
       
  4287                                 reportParseError(lexicalHnd->errorString());
       
  4288                                 return false;
       
  4289                             }
       
  4290                         }
       
  4291                     } else if (c == QLatin1Char(']')) {
       
  4292                         // three or more ']'
       
  4293                         stringAddC(QLatin1Char(']'));
       
  4294                     } else {
       
  4295                         // after ']]' comes another character
       
  4296                         stringAddC(QLatin1Char(']'));
       
  4297                         stringAddC(QLatin1Char(']'));
       
  4298                     }
       
  4299                 }
       
  4300                 break;
       
  4301             case Done:
       
  4302                 // call the handler for CharData
       
  4303                 if (contentHnd) {
       
  4304                     if (contentCharDataRead) {
       
  4305                         if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
       
  4306                             if (!contentHnd->characters(string())) {
       
  4307                                 reportParseError(contentHnd->errorString());
       
  4308                                 return false;
       
  4309                             }
       
  4310                         }
       
  4311                     }
       
  4312                 }
       
  4313                 // Done
       
  4314                 return true;
       
  4315             case -1:
       
  4316                 // Error
       
  4317                 reportParseError(QLatin1String(XMLERR_ERRORPARSINGCONTENT));
       
  4318                 return false;
       
  4319         }
       
  4320 
       
  4321         // get input (use lookup-table instead of nested ifs for performance
       
  4322         // reasons)
       
  4323         if (atEnd()) {
       
  4324             unexpectedEof(&QXmlSimpleReaderPrivate::parseContent, state);
       
  4325             return false;
       
  4326         }
       
  4327         if (c.row()) {
       
  4328             input = InpUnknown;
       
  4329         } else {
       
  4330             input = mapCLT2FSMChar[charLookupTable[c.cell()]];
       
  4331         }
       
  4332         state = table[state][input];
       
  4333 
       
  4334         switch (state) {
       
  4335             case Init:
       
  4336                 // skip the ending '>' of a CDATASection
       
  4337                 next();
       
  4338                 break;
       
  4339             case ChD:
       
  4340                 // on first call: clear string
       
  4341                 if (!contentCharDataRead) {
       
  4342                     contentCharDataRead = true;
       
  4343                     stringClear();
       
  4344                 }
       
  4345                 stringAddC();
       
  4346                 if (reportEntities) {
       
  4347                     if (!reportEndEntities())
       
  4348                         return false;
       
  4349                 }
       
  4350                 next();
       
  4351                 break;
       
  4352             case ChD1:
       
  4353                 // on first call: clear string
       
  4354                 if (!contentCharDataRead) {
       
  4355                     contentCharDataRead = true;
       
  4356                     stringClear();
       
  4357                 }
       
  4358                 stringAddC();
       
  4359                 if (reportEntities) {
       
  4360                     if (!reportEndEntities())
       
  4361                         return false;
       
  4362                 }
       
  4363                 next();
       
  4364                 break;
       
  4365             case ChD2:
       
  4366                 stringAddC();
       
  4367                 if (reportEntities) {
       
  4368                     if (!reportEndEntities())
       
  4369                         return false;
       
  4370                 }
       
  4371                 next();
       
  4372                 break;
       
  4373             case Ref:
       
  4374                 if (!contentCharDataRead) {
       
  4375                     // reference may be CharData; so clear string to be safe
       
  4376                     stringClear();
       
  4377                     parseReference_context = InContent;
       
  4378                     if (!parseReference()) {
       
  4379                         parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
       
  4380                         return false;
       
  4381                     }
       
  4382                 } else {
       
  4383                     if (reportEntities) {
       
  4384                         // report character data in chunks
       
  4385                         if (contentHnd) {
       
  4386                             if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
       
  4387                                 if (!contentHnd->characters(string())) {
       
  4388                                     reportParseError(contentHnd->errorString());
       
  4389                                     return false;
       
  4390                                 }
       
  4391                             }
       
  4392                         }
       
  4393                         stringClear();
       
  4394                     }
       
  4395                     parseReference_context = InContent;
       
  4396                     if (!parseReference()) {
       
  4397                         parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
       
  4398                         return false;
       
  4399                     }
       
  4400                 }
       
  4401                 break;
       
  4402             case Lt:
       
  4403                 // call the handler for CharData
       
  4404                 if (contentHnd) {
       
  4405                     if (contentCharDataRead) {
       
  4406                         if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
       
  4407                             if (!contentHnd->characters(string())) {
       
  4408                                 reportParseError(contentHnd->errorString());
       
  4409                                 return false;
       
  4410                             }
       
  4411                         }
       
  4412                     }
       
  4413                 }
       
  4414                 contentCharDataRead = false;
       
  4415                 next();
       
  4416                 break;
       
  4417             case PInstr:
       
  4418             case PInstrR:
       
  4419                 parsePI_xmldecl = false;
       
  4420                 if (!parsePI()) {
       
  4421                     parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
       
  4422                     return false;
       
  4423                 }
       
  4424                 break;
       
  4425             case Elem:
       
  4426                 if (!parseElement()) {
       
  4427                     parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
       
  4428                     return false;
       
  4429                 }
       
  4430                 break;
       
  4431             case Em:
       
  4432                 next();
       
  4433                 break;
       
  4434             case Com:
       
  4435             case ComR:
       
  4436                 if (!parseComment()) {
       
  4437                     parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
       
  4438                     return false;
       
  4439                 }
       
  4440                 break;
       
  4441             case CDS:
       
  4442                 parseString_s = QLatin1String("[CDATA[");
       
  4443                 if (!parseString()) {
       
  4444                     parseFailed(&QXmlSimpleReaderPrivate::parseContent, state);
       
  4445                     return false;
       
  4446                 }
       
  4447                 break;
       
  4448             case CDS1:
       
  4449                 stringAddC();
       
  4450                 next();
       
  4451                 break;
       
  4452             case CDS2:
       
  4453                 // skip ']'
       
  4454                 next();
       
  4455                 break;
       
  4456             case CDS3:
       
  4457                 // skip ']'...
       
  4458                 next();
       
  4459                 break;
       
  4460         }
       
  4461     }
       
  4462     return false;
       
  4463 }
       
  4464 
       
  4465 bool QXmlSimpleReaderPrivate::reportEndEntities()
       
  4466 {
       
  4467     int count = (int)xmlRefStack.count();
       
  4468     while (count != 0 && xmlRefStack.top().isEmpty()) {
       
  4469         if (contentHnd) {
       
  4470             if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
       
  4471                 if (!contentHnd->characters(string())) {
       
  4472                     reportParseError(contentHnd->errorString());
       
  4473                     return false;
       
  4474                 }
       
  4475             }
       
  4476         }
       
  4477         stringClear();
       
  4478         if (lexicalHnd) {
       
  4479             if (!lexicalHnd->endEntity(xmlRefStack.top().name)) {
       
  4480                 reportParseError(lexicalHnd->errorString());
       
  4481                 return false;
       
  4482             }
       
  4483         }
       
  4484         xmlRefStack.pop_back();
       
  4485         count--;
       
  4486     }
       
  4487     return true;
       
  4488 }
       
  4489 
       
  4490 /*
       
  4491   Parse Misc [27].
       
  4492 */
       
  4493 bool QXmlSimpleReaderPrivate::parseMisc()
       
  4494 {
       
  4495     const signed char Init             = 0;
       
  4496     const signed char Lt               = 1; // '<' was read
       
  4497     const signed char Comment          = 2; // read comment
       
  4498     const signed char eatWS            = 3; // eat whitespaces
       
  4499     const signed char PInstr           = 4; // read PI
       
  4500     const signed char Comment2         = 5; // read comment
       
  4501 
       
  4502     const signed char InpWs            = 0; // S
       
  4503     const signed char InpLt            = 1; // <
       
  4504     const signed char InpQm            = 2; // ?
       
  4505     const signed char InpEm            = 3; // !
       
  4506     const signed char InpUnknown       = 4;
       
  4507 
       
  4508     static const signed char table[3][5] = {
       
  4509      /*  InpWs   InpLt  InpQm  InpEm     InpUnknown */
       
  4510         { eatWS,  Lt,    -1,    -1,       -1        }, // Init
       
  4511         { -1,     -1,    PInstr,Comment,  -1        }, // Lt
       
  4512         { -1,     -1,    -1,    -1,       Comment2  }  // Comment
       
  4513     };
       
  4514     signed char state;
       
  4515     signed char input;
       
  4516 
       
  4517     if (parseStack==0 || parseStack->isEmpty()) {
       
  4518         state = Init;
       
  4519     } else {
       
  4520         state = parseStack->pop().state;
       
  4521 #if defined(QT_QXML_DEBUG)
       
  4522         qDebug("QXmlSimpleReader: parseMisc (cont) in state %d", state);
       
  4523 #endif
       
  4524         if (!parseStack->isEmpty()) {
       
  4525             ParseFunction function = parseStack->top().function;
       
  4526             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  4527                 parseStack->pop();
       
  4528 #if defined(QT_QXML_DEBUG)
       
  4529                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  4530 #endif
       
  4531             }
       
  4532             if (!(this->*function)()) {
       
  4533                 parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state);
       
  4534                 return false;
       
  4535             }
       
  4536         }
       
  4537     }
       
  4538 
       
  4539     for (;;) {
       
  4540         switch (state) {
       
  4541             case eatWS:
       
  4542                 return true;
       
  4543             case PInstr:
       
  4544                 if (contentHnd) {
       
  4545                     if (!contentHnd->processingInstruction(name(),string())) {
       
  4546                         reportParseError(contentHnd->errorString());
       
  4547                         return false;
       
  4548                     }
       
  4549                 }
       
  4550                 return true;
       
  4551             case Comment2:
       
  4552                 if (lexicalHnd) {
       
  4553                     if (!lexicalHnd->comment(string())) {
       
  4554                         reportParseError(lexicalHnd->errorString());
       
  4555                         return false;
       
  4556                     }
       
  4557                 }
       
  4558                 return true;
       
  4559             case -1:
       
  4560                 // Error
       
  4561                 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
       
  4562                 return false;
       
  4563         }
       
  4564 
       
  4565         if (atEnd()) {
       
  4566             unexpectedEof(&QXmlSimpleReaderPrivate::parseMisc, state);
       
  4567             return false;
       
  4568         }
       
  4569         if (is_S(c)) {
       
  4570             input = InpWs;
       
  4571         } else if (c == QLatin1Char('<')) {
       
  4572             input = InpLt;
       
  4573         } else if (c == QLatin1Char('?')) {
       
  4574             input = InpQm;
       
  4575         } else if (c == QLatin1Char('!')) {
       
  4576             input = InpEm;
       
  4577         } else {
       
  4578             input = InpUnknown;
       
  4579         }
       
  4580         state = table[state][input];
       
  4581 
       
  4582         switch (state) {
       
  4583             case eatWS:
       
  4584                 if (!eat_ws()) {
       
  4585                     parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state);
       
  4586                     return false;
       
  4587                 }
       
  4588                 break;
       
  4589             case Lt:
       
  4590                 next();
       
  4591                 break;
       
  4592             case PInstr:
       
  4593                 parsePI_xmldecl = false;
       
  4594                 if (!parsePI()) {
       
  4595                     parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state);
       
  4596                     return false;
       
  4597                 }
       
  4598                 break;
       
  4599             case Comment:
       
  4600                 next();
       
  4601                 break;
       
  4602             case Comment2:
       
  4603                 if (!parseComment()) {
       
  4604                     parseFailed(&QXmlSimpleReaderPrivate::parseMisc, state);
       
  4605                     return false;
       
  4606                 }
       
  4607                 break;
       
  4608         }
       
  4609     }
       
  4610     return false;
       
  4611 }
       
  4612 
       
  4613 /*
       
  4614   Parse a processing instruction [16].
       
  4615 
       
  4616   If xmldec is true, it tries to parse a PI or a XML declaration [23].
       
  4617 
       
  4618   Precondition: the beginning '<' of the PI is already read and the head stand
       
  4619   on the '?' of '<?'.
       
  4620 
       
  4621   If this funktion was successful, the head-position is on the first
       
  4622   character after the PI.
       
  4623 */
       
  4624 bool QXmlSimpleReaderPrivate::parsePI()
       
  4625 {
       
  4626     const signed char Init             =  0;
       
  4627     const signed char QmI              =  1; // ? was read
       
  4628     const signed char Name             =  2; // read Name
       
  4629     const signed char XMLDecl          =  3; // read XMLDecl
       
  4630     const signed char Ws1              =  4; // eat ws after "xml" of XMLDecl
       
  4631     const signed char PInstr           =  5; // read PI
       
  4632     const signed char Ws2              =  6; // eat ws after Name of PI
       
  4633     const signed char Version          =  7; // read versionInfo
       
  4634     const signed char Ws3              =  8; // eat ws after versionInfo
       
  4635     const signed char EorSD            =  9; // read EDecl or SDDecl
       
  4636     const signed char Ws4              = 10; // eat ws after EDecl or SDDecl
       
  4637     const signed char SD               = 11; // read SDDecl
       
  4638     const signed char Ws5              = 12; // eat ws after SDDecl
       
  4639     const signed char ADone            = 13; // almost done
       
  4640     const signed char Char             = 14; // Char was read
       
  4641     const signed char Qm               = 15; // Qm was read
       
  4642     const signed char Done             = 16; // finished reading content
       
  4643 
       
  4644     const signed char InpWs            = 0; // whitespace
       
  4645     const signed char InpNameBe        = 1; // NameBeginning
       
  4646     const signed char InpGt            = 2; // >
       
  4647     const signed char InpQm            = 3; // ?
       
  4648     const signed char InpUnknown       = 4;
       
  4649 
       
  4650     static const signed char table[16][5] = {
       
  4651      /*  InpWs,  InpNameBe  InpGt  InpQm   InpUnknown  */
       
  4652         { -1,     -1,        -1,    QmI,    -1     }, // Init
       
  4653         { -1,     Name,      -1,    -1,     -1     }, // QmI
       
  4654         { -1,     -1,        -1,    -1,     -1     }, // Name (this state is left not through input)
       
  4655         { Ws1,    -1,        -1,    -1,     -1     }, // XMLDecl
       
  4656         { -1,     Version,   -1,    -1,     -1     }, // Ws1
       
  4657         { Ws2,    -1,        -1,    Qm,     -1     }, // PInstr
       
  4658         { Char,   Char,      Char,  Qm,     Char   }, // Ws2
       
  4659         { Ws3,    -1,        -1,    ADone,  -1     }, // Version
       
  4660         { -1,     EorSD,     -1,    ADone,  -1     }, // Ws3
       
  4661         { Ws4,    -1,        -1,    ADone,  -1     }, // EorSD
       
  4662         { -1,     SD,        -1,    ADone,  -1     }, // Ws4
       
  4663         { Ws5,    -1,        -1,    ADone,  -1     }, // SD
       
  4664         { -1,     -1,        -1,    ADone,  -1     }, // Ws5
       
  4665         { -1,     -1,        Done,  -1,     -1     }, // ADone
       
  4666         { Char,   Char,      Char,  Qm,     Char   }, // Char
       
  4667         { Char,   Char,      Done,  Qm,     Char   }, // Qm
       
  4668     };
       
  4669     signed char state;
       
  4670     signed char input;
       
  4671 
       
  4672     if (parseStack==0 || parseStack->isEmpty()) {
       
  4673         state = Init;
       
  4674     } else {
       
  4675         state = parseStack->pop().state;
       
  4676 #if defined(QT_QXML_DEBUG)
       
  4677         qDebug("QXmlSimpleReader: parsePI (cont) in state %d", state);
       
  4678 #endif
       
  4679         if (!parseStack->isEmpty()) {
       
  4680             ParseFunction function = parseStack->top().function;
       
  4681             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  4682                 parseStack->pop();
       
  4683 #if defined(QT_QXML_DEBUG)
       
  4684                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  4685 #endif
       
  4686             }
       
  4687             if (!(this->*function)()) {
       
  4688                 parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
       
  4689                 return false;
       
  4690             }
       
  4691         }
       
  4692     }
       
  4693 
       
  4694     for (;;) {
       
  4695         switch (state) {
       
  4696             case Name:
       
  4697                 // test what name was read and determine the next state
       
  4698                 // (not very beautiful, I admit)
       
  4699                 if (name().toLower() == QLatin1String("xml")) {
       
  4700                     if (parsePI_xmldecl && name() == QLatin1String("xml")) {
       
  4701                         state = XMLDecl;
       
  4702                     } else {
       
  4703                         reportParseError(QLatin1String(XMLERR_INVALIDNAMEFORPI));
       
  4704                         return false;
       
  4705                     }
       
  4706                 } else {
       
  4707                     state = PInstr;
       
  4708                     stringClear();
       
  4709                 }
       
  4710                 break;
       
  4711             case Version:
       
  4712                 // get version (syntax like an attribute)
       
  4713                 if (name() != QLatin1String("version")) {
       
  4714                     reportParseError(QLatin1String(XMLERR_VERSIONEXPECTED));
       
  4715                     return false;
       
  4716                 }
       
  4717                 xmlVersion = string();
       
  4718                 break;
       
  4719             case EorSD:
       
  4720                 // get the EDecl or SDDecl (syntax like an attribute)
       
  4721                 if (name() == QLatin1String("standalone")) {
       
  4722                     if (string()== QLatin1String("yes")) {
       
  4723                         standalone = QXmlSimpleReaderPrivate::Yes;
       
  4724                     } else if (string() == QLatin1String("no")) {
       
  4725                         standalone = QXmlSimpleReaderPrivate::No;
       
  4726                     } else {
       
  4727                         reportParseError(QLatin1String(XMLERR_WRONGVALUEFORSDECL));
       
  4728                         return false;
       
  4729                     }
       
  4730                 } else if (name() == QLatin1String("encoding")) {
       
  4731                     encoding = string();
       
  4732                 } else {
       
  4733                     reportParseError(QLatin1String(XMLERR_EDECLORSDDECLEXPECTED));
       
  4734                     return false;
       
  4735                 }
       
  4736                 break;
       
  4737             case SD:
       
  4738                 if (name() != QLatin1String("standalone")) {
       
  4739                     reportParseError(QLatin1String(XMLERR_SDDECLEXPECTED));
       
  4740                     return false;
       
  4741                 }
       
  4742                 if (string() == QLatin1String("yes")) {
       
  4743                     standalone = QXmlSimpleReaderPrivate::Yes;
       
  4744                 } else if (string() == QLatin1String("no")) {
       
  4745                     standalone = QXmlSimpleReaderPrivate::No;
       
  4746                 } else {
       
  4747                     reportParseError(QLatin1String(XMLERR_WRONGVALUEFORSDECL));
       
  4748                     return false;
       
  4749                 }
       
  4750                 break;
       
  4751             case Qm:
       
  4752                 // test if the skipping was legal
       
  4753                 if (!atEnd() && c != QLatin1Char('>'))
       
  4754                     stringAddC(QLatin1Char('?'));
       
  4755                 break;
       
  4756             case Done:
       
  4757                 return true;
       
  4758             case -1:
       
  4759                 // Error
       
  4760                 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
       
  4761                 return false;
       
  4762         }
       
  4763 
       
  4764         if (atEnd()) {
       
  4765             unexpectedEof(&QXmlSimpleReaderPrivate::parsePI, state);
       
  4766             return false;
       
  4767         }
       
  4768         if (is_S(c)) {
       
  4769             input = InpWs;
       
  4770         } else if (determineNameChar(c) == NameBeginning) {
       
  4771             input = InpNameBe;
       
  4772         } else if (c == QLatin1Char('>')) {
       
  4773             input = InpGt;
       
  4774         } else if (c == QLatin1Char('?')) {
       
  4775             input = InpQm;
       
  4776         } else {
       
  4777             input = InpUnknown;
       
  4778         }
       
  4779         state = table[state][input];
       
  4780 
       
  4781         switch (state) {
       
  4782             case QmI:
       
  4783                 next();
       
  4784                 break;
       
  4785             case Name:
       
  4786                 parseName_useRef = false;
       
  4787                 if (!parseName()) {
       
  4788                     parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
       
  4789                     return false;
       
  4790                 }
       
  4791                 break;
       
  4792             case Ws1:
       
  4793             case Ws2:
       
  4794             case Ws3:
       
  4795             case Ws4:
       
  4796             case Ws5:
       
  4797                 if (!eat_ws()) {
       
  4798                     parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
       
  4799                     return false;
       
  4800                 }
       
  4801                 break;
       
  4802             case Version:
       
  4803                 if (!parseAttribute()) {
       
  4804                     parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
       
  4805                     return false;
       
  4806                 }
       
  4807                 break;
       
  4808             case EorSD:
       
  4809                 if (!parseAttribute()) {
       
  4810                     parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
       
  4811                     return false;
       
  4812                 }
       
  4813                 break;
       
  4814             case SD:
       
  4815                 // get the SDDecl (syntax like an attribute)
       
  4816                 if (standalone != QXmlSimpleReaderPrivate::Unknown) {
       
  4817                     // already parsed the standalone declaration
       
  4818                     reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
       
  4819                     return false;
       
  4820                 }
       
  4821                 if (!parseAttribute()) {
       
  4822                     parseFailed(&QXmlSimpleReaderPrivate::parsePI, state);
       
  4823                     return false;
       
  4824                 }
       
  4825                 break;
       
  4826             case ADone:
       
  4827                 next();
       
  4828                 break;
       
  4829             case Char:
       
  4830                 stringAddC();
       
  4831                 next();
       
  4832                 break;
       
  4833             case Qm:
       
  4834                 // skip the '?'
       
  4835                 next();
       
  4836                 break;
       
  4837             case Done:
       
  4838                 next();
       
  4839                 break;
       
  4840         }
       
  4841     }
       
  4842     return false;
       
  4843 }
       
  4844 
       
  4845 /*
       
  4846   Parse a document type definition (doctypedecl [28]).
       
  4847 
       
  4848   Precondition: the beginning '<!' of the doctype is already read the head
       
  4849   stands on the 'D' of '<!DOCTYPE'.
       
  4850 
       
  4851   If this function was successful, the head-position is on the first
       
  4852   character after the document type definition.
       
  4853 */
       
  4854 bool QXmlSimpleReaderPrivate::parseDoctype()
       
  4855 {
       
  4856     const signed char Init             =  0;
       
  4857     const signed char Doctype          =  1; // read the doctype
       
  4858     const signed char Ws1              =  2; // eat_ws
       
  4859     const signed char Doctype2         =  3; // read the doctype, part 2
       
  4860     const signed char Ws2              =  4; // eat_ws
       
  4861     const signed char Sys              =  5; // read SYSTEM or PUBLIC
       
  4862     const signed char Ws3              =  6; // eat_ws
       
  4863     const signed char MP               =  7; // markupdecl or PEReference
       
  4864     const signed char MPR              =  8; // same as MP, but already reported
       
  4865     const signed char PER              =  9; // PERReference
       
  4866     const signed char Mup              = 10; // markupdecl
       
  4867     const signed char Ws4              = 11; // eat_ws
       
  4868     const signed char MPE              = 12; // end of markupdecl or PEReference
       
  4869     const signed char Done             = 13;
       
  4870 
       
  4871     const signed char InpWs            = 0;
       
  4872     const signed char InpD             = 1; // 'D'
       
  4873     const signed char InpS             = 2; // 'S' or 'P'
       
  4874     const signed char InpOB            = 3; // [
       
  4875     const signed char InpCB            = 4; //]
       
  4876     const signed char InpPer           = 5; // %
       
  4877     const signed char InpGt            = 6; // >
       
  4878     const signed char InpUnknown       = 7;
       
  4879 
       
  4880     static const signed char table[13][8] = {
       
  4881      /*  InpWs,  InpD       InpS       InpOB  InpCB  InpPer InpGt  InpUnknown */
       
  4882         { -1,     Doctype,   -1,        -1,    -1,    -1,    -1,    -1        }, // Init
       
  4883         { Ws1,    -1,        -1,        -1,    -1,    -1,    -1,    -1        }, // Doctype
       
  4884         { -1,     Doctype2,  Doctype2,  -1,    -1,    -1,    -1,    Doctype2  }, // Ws1
       
  4885         { Ws2,    -1,        Sys,       MP,    -1,    -1,    Done,  -1        }, // Doctype2
       
  4886         { -1,     -1,        Sys,       MP,    -1,    -1,    Done,  -1        }, // Ws2
       
  4887         { Ws3,    -1,        -1,        MP,    -1,    -1,    Done,  -1        }, // Sys
       
  4888         { -1,     -1,        -1,        MP,    -1,    -1,    Done,  -1        }, // Ws3
       
  4889         { -1,     -1,        -1,        -1,    MPE,   PER,   -1,    Mup       }, // MP
       
  4890         { -1,     -1,        -1,        -1,    MPE,   PER,   -1,    Mup       }, // MPR
       
  4891         { Ws4,    -1,        -1,        -1,    MPE,   PER,   -1,    Mup       }, // PER
       
  4892         { Ws4,    -1,        -1,        -1,    MPE,   PER,   -1,    Mup       }, // Mup
       
  4893         { -1,     -1,        -1,        -1,    MPE,   PER,   -1,    Mup       }, // Ws4
       
  4894         { -1,     -1,        -1,        -1,    -1,    -1,    Done,  -1        }  // MPE
       
  4895     };
       
  4896     signed char state;
       
  4897     signed char input;
       
  4898 
       
  4899     if (parseStack==0 || parseStack->isEmpty()) {
       
  4900         startDTDwasReported = false;
       
  4901         systemId.clear();
       
  4902         publicId.clear();
       
  4903         state = Init;
       
  4904     } else {
       
  4905         state = parseStack->pop().state;
       
  4906 #if defined(QT_QXML_DEBUG)
       
  4907         qDebug("QXmlSimpleReader: parseDoctype (cont) in state %d", state);
       
  4908 #endif
       
  4909         if (!parseStack->isEmpty()) {
       
  4910             ParseFunction function = parseStack->top().function;
       
  4911             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  4912                 parseStack->pop();
       
  4913 #if defined(QT_QXML_DEBUG)
       
  4914                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  4915 #endif
       
  4916             }
       
  4917             if (!(this->*function)()) {
       
  4918                 parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
       
  4919                 return false;
       
  4920             }
       
  4921         }
       
  4922     }
       
  4923 
       
  4924     for (;;) {
       
  4925         switch (state) {
       
  4926             case Doctype2:
       
  4927                 doctype = name();
       
  4928                 break;
       
  4929             case MP:
       
  4930                 if (!startDTDwasReported && lexicalHnd ) {
       
  4931                     startDTDwasReported = true;
       
  4932                     if (!lexicalHnd->startDTD(doctype, publicId, systemId)) {
       
  4933                         reportParseError(lexicalHnd->errorString());
       
  4934                         return false;
       
  4935                     }
       
  4936                 }
       
  4937                 state = MPR;
       
  4938                 break;
       
  4939             case Done:
       
  4940                 return true;
       
  4941             case -1:
       
  4942                 // Error
       
  4943                 reportParseError(QLatin1String(XMLERR_ERRORPARSINGDOCTYPE));
       
  4944                 return false;
       
  4945         }
       
  4946 
       
  4947         if (atEnd()) {
       
  4948             unexpectedEof(&QXmlSimpleReaderPrivate::parseDoctype, state);
       
  4949             return false;
       
  4950         }
       
  4951         if (is_S(c)) {
       
  4952             input = InpWs;
       
  4953         } else if (c == QLatin1Char('D')) {
       
  4954             input = InpD;
       
  4955         } else if (c == QLatin1Char('S')) {
       
  4956             input = InpS;
       
  4957         } else if (c == QLatin1Char('P')) {
       
  4958             input = InpS;
       
  4959         } else if (c == QLatin1Char('[')) {
       
  4960             input = InpOB;
       
  4961         } else if (c == QLatin1Char(']')) {
       
  4962             input = InpCB;
       
  4963         } else if (c == QLatin1Char('%')) {
       
  4964             input = InpPer;
       
  4965         } else if (c == QLatin1Char('>')) {
       
  4966             input = InpGt;
       
  4967         } else {
       
  4968             input = InpUnknown;
       
  4969         }
       
  4970         state = table[state][input];
       
  4971 
       
  4972         switch (state) {
       
  4973             case Doctype:
       
  4974                 parseString_s = QLatin1String("DOCTYPE");
       
  4975                 if (!parseString()) {
       
  4976                     parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
       
  4977                     return false;
       
  4978                 }
       
  4979                 break;
       
  4980             case Ws1:
       
  4981             case Ws2:
       
  4982             case Ws3:
       
  4983             case Ws4:
       
  4984                 if (!eat_ws()) {
       
  4985                     parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
       
  4986                     return false;
       
  4987                 }
       
  4988                 break;
       
  4989             case Doctype2:
       
  4990                 parseName_useRef = false;
       
  4991                 if (!parseName()) {
       
  4992                     parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
       
  4993                     return false;
       
  4994                 }
       
  4995                 break;
       
  4996             case Sys:
       
  4997                 parseExternalID_allowPublicID = false;
       
  4998                 if (!parseExternalID()) {
       
  4999                     parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
       
  5000                     return false;
       
  5001                 }
       
  5002                 thisPublicId = publicId;
       
  5003                 thisSystemId = systemId;
       
  5004                 break;
       
  5005             case MP:
       
  5006             case MPR:
       
  5007                 if (!next_eat_ws()) {
       
  5008                     parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
       
  5009                     return false;
       
  5010                 }
       
  5011                 break;
       
  5012             case PER:
       
  5013                 parsePEReference_context = InDTD;
       
  5014                 if (!parsePEReference()) {
       
  5015                     parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
       
  5016                     return false;
       
  5017                 }
       
  5018                 break;
       
  5019             case Mup:
       
  5020                 if (!parseMarkupdecl()) {
       
  5021                     parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
       
  5022                     return false;
       
  5023                 }
       
  5024                 break;
       
  5025             case MPE:
       
  5026                 if (!next_eat_ws()) {
       
  5027                     parseFailed(&QXmlSimpleReaderPrivate::parseDoctype, state);
       
  5028                     return false;
       
  5029                 }
       
  5030                 break;
       
  5031             case Done:
       
  5032                 if (lexicalHnd) {
       
  5033                     if (!startDTDwasReported) {
       
  5034                         startDTDwasReported = true;
       
  5035                         if (!lexicalHnd->startDTD(doctype, publicId, systemId)) {
       
  5036                             reportParseError(lexicalHnd->errorString());
       
  5037                             return false;
       
  5038                         }
       
  5039                     }
       
  5040                     if (!lexicalHnd->endDTD()) {
       
  5041                         reportParseError(lexicalHnd->errorString());
       
  5042                         return false;
       
  5043                     }
       
  5044                 }
       
  5045                 next();
       
  5046                 break;
       
  5047         }
       
  5048     }
       
  5049     return false;
       
  5050 }
       
  5051 
       
  5052 /*
       
  5053   Parse a ExternalID [75].
       
  5054 
       
  5055   If allowPublicID is true parse ExternalID [75] or PublicID [83].
       
  5056 */
       
  5057 bool QXmlSimpleReaderPrivate::parseExternalID()
       
  5058 {
       
  5059     const signed char Init             =  0;
       
  5060     const signed char Sys              =  1; // parse 'SYSTEM'
       
  5061     const signed char SysWS            =  2; // parse the whitespace after 'SYSTEM'
       
  5062     const signed char SysSQ            =  3; // parse SystemLiteral with '
       
  5063     const signed char SysSQ2           =  4; // parse SystemLiteral with '
       
  5064     const signed char SysDQ            =  5; // parse SystemLiteral with "
       
  5065     const signed char SysDQ2           =  6; // parse SystemLiteral with "
       
  5066     const signed char Pub              =  7; // parse 'PUBLIC'
       
  5067     const signed char PubWS            =  8; // parse the whitespace after 'PUBLIC'
       
  5068     const signed char PubSQ            =  9; // parse PubidLiteral with '
       
  5069     const signed char PubSQ2           = 10; // parse PubidLiteral with '
       
  5070     const signed char PubDQ            = 11; // parse PubidLiteral with "
       
  5071     const signed char PubDQ2           = 12; // parse PubidLiteral with "
       
  5072     const signed char PubE             = 13; // finished parsing the PubidLiteral
       
  5073     const signed char PubWS2           = 14; // parse the whitespace after the PubidLiteral
       
  5074     const signed char PDone            = 15; // done if allowPublicID is true
       
  5075     const signed char Done             = 16;
       
  5076 
       
  5077     const signed char InpSQ            = 0; // '
       
  5078     const signed char InpDQ            = 1; // "
       
  5079     const signed char InpS             = 2; // S
       
  5080     const signed char InpP             = 3; // P
       
  5081     const signed char InpWs            = 4; // white space
       
  5082     const signed char InpUnknown       = 5;
       
  5083 
       
  5084     static const signed char table[15][6] = {
       
  5085      /*  InpSQ    InpDQ    InpS     InpP     InpWs     InpUnknown */
       
  5086         { -1,      -1,      Sys,     Pub,     -1,       -1      }, // Init
       
  5087         { -1,      -1,      -1,      -1,      SysWS,    -1      }, // Sys
       
  5088         { SysSQ,   SysDQ,   -1,      -1,      -1,       -1      }, // SysWS
       
  5089         { Done,    SysSQ2,  SysSQ2,  SysSQ2,  SysSQ2,   SysSQ2  }, // SysSQ
       
  5090         { Done,    SysSQ2,  SysSQ2,  SysSQ2,  SysSQ2,   SysSQ2  }, // SysSQ2
       
  5091         { SysDQ2,  Done,    SysDQ2,  SysDQ2,  SysDQ2,   SysDQ2  }, // SysDQ
       
  5092         { SysDQ2,  Done,    SysDQ2,  SysDQ2,  SysDQ2,   SysDQ2  }, // SysDQ2
       
  5093         { -1,      -1,      -1,      -1,      PubWS,    -1      }, // Pub
       
  5094         { PubSQ,   PubDQ,   -1,      -1,      -1,       -1      }, // PubWS
       
  5095         { PubE,    -1,      PubSQ2,  PubSQ2,  PubSQ2,   PubSQ2  }, // PubSQ
       
  5096         { PubE,    -1,      PubSQ2,  PubSQ2,  PubSQ2,   PubSQ2  }, // PubSQ2
       
  5097         { -1,      PubE,    PubDQ2,  PubDQ2,  PubDQ2,   PubDQ2  }, // PubDQ
       
  5098         { -1,      PubE,    PubDQ2,  PubDQ2,  PubDQ2,   PubDQ2  }, // PubDQ2
       
  5099         { PDone,   PDone,   PDone,   PDone,   PubWS2,   PDone   }, // PubE
       
  5100         { SysSQ,   SysDQ,   PDone,   PDone,   PDone,    PDone   }  // PubWS2
       
  5101     };
       
  5102     signed char state;
       
  5103     signed char input;
       
  5104 
       
  5105     if (parseStack==0 || parseStack->isEmpty()) {
       
  5106         systemId.clear();
       
  5107         publicId.clear();
       
  5108         state = Init;
       
  5109     } else {
       
  5110         state = parseStack->pop().state;
       
  5111 #if defined(QT_QXML_DEBUG)
       
  5112         qDebug("QXmlSimpleReader: parseExternalID (cont) in state %d", state);
       
  5113 #endif
       
  5114         if (!parseStack->isEmpty()) {
       
  5115             ParseFunction function = parseStack->top().function;
       
  5116             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  5117                 parseStack->pop();
       
  5118 #if defined(QT_QXML_DEBUG)
       
  5119                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  5120 #endif
       
  5121             }
       
  5122             if (!(this->*function)()) {
       
  5123                 parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state);
       
  5124                 return false;
       
  5125             }
       
  5126         }
       
  5127     }
       
  5128 
       
  5129     for (;;) {
       
  5130         switch (state) {
       
  5131             case PDone:
       
  5132                 if (parseExternalID_allowPublicID) {
       
  5133                     publicId = string();
       
  5134                     return true;
       
  5135                 } else {
       
  5136                     reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
       
  5137                     return false;
       
  5138                 }
       
  5139             case Done:
       
  5140                 return true;
       
  5141             case -1:
       
  5142                 // Error
       
  5143                 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
       
  5144                 return false;
       
  5145         }
       
  5146 
       
  5147         if (atEnd()) {
       
  5148             unexpectedEof(&QXmlSimpleReaderPrivate::parseExternalID, state);
       
  5149             return false;
       
  5150         }
       
  5151         if (is_S(c)) {
       
  5152             input = InpWs;
       
  5153         } else if (c == QLatin1Char('\'')) {
       
  5154             input = InpSQ;
       
  5155         } else if (c == QLatin1Char('"')) {
       
  5156             input = InpDQ;
       
  5157         } else if (c == QLatin1Char('S')) {
       
  5158             input = InpS;
       
  5159         } else if (c == QLatin1Char('P')) {
       
  5160             input = InpP;
       
  5161         } else {
       
  5162             input = InpUnknown;
       
  5163         }
       
  5164         state = table[state][input];
       
  5165 
       
  5166         switch (state) {
       
  5167             case Sys:
       
  5168                 parseString_s = QLatin1String("SYSTEM");
       
  5169                 if (!parseString()) {
       
  5170                     parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state);
       
  5171                     return false;
       
  5172                 }
       
  5173                 break;
       
  5174             case SysWS:
       
  5175                 if (!eat_ws()) {
       
  5176                     parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state);
       
  5177                     return false;
       
  5178                 }
       
  5179                 break;
       
  5180             case SysSQ:
       
  5181             case SysDQ:
       
  5182                 stringClear();
       
  5183                 next();
       
  5184                 break;
       
  5185             case SysSQ2:
       
  5186             case SysDQ2:
       
  5187                 stringAddC();
       
  5188                 next();
       
  5189                 break;
       
  5190             case Pub:
       
  5191                 parseString_s = QLatin1String("PUBLIC");
       
  5192                 if (!parseString()) {
       
  5193                     parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state);
       
  5194                     return false;
       
  5195                 }
       
  5196                 break;
       
  5197             case PubWS:
       
  5198                 if (!eat_ws()) {
       
  5199                     parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state);
       
  5200                     return false;
       
  5201                 }
       
  5202                 break;
       
  5203             case PubSQ:
       
  5204             case PubDQ:
       
  5205                 stringClear();
       
  5206                 next();
       
  5207                 break;
       
  5208             case PubSQ2:
       
  5209             case PubDQ2:
       
  5210                 stringAddC();
       
  5211                 next();
       
  5212                 break;
       
  5213             case PubE:
       
  5214                 next();
       
  5215                 break;
       
  5216             case PubWS2:
       
  5217                 publicId = string();
       
  5218                 if (!eat_ws()) {
       
  5219                     parseFailed(&QXmlSimpleReaderPrivate::parseExternalID, state);
       
  5220                     return false;
       
  5221                 }
       
  5222                 break;
       
  5223             case Done:
       
  5224                 systemId = string();
       
  5225                 next();
       
  5226                 break;
       
  5227         }
       
  5228     }
       
  5229     return false;
       
  5230 }
       
  5231 
       
  5232 /*
       
  5233   Parse a markupdecl [29].
       
  5234 */
       
  5235 bool QXmlSimpleReaderPrivate::parseMarkupdecl()
       
  5236 {
       
  5237     const signed char Init             = 0;
       
  5238     const signed char Lt               = 1; // < was read
       
  5239     const signed char Em               = 2; // ! was read
       
  5240     const signed char CE               = 3; // E was read
       
  5241     const signed char Qm               = 4; // ? was read
       
  5242     const signed char Dash             = 5; // - was read
       
  5243     const signed char CA               = 6; // A was read
       
  5244     const signed char CEL              = 7; // EL was read
       
  5245     const signed char CEN              = 8; // EN was read
       
  5246     const signed char CN               = 9; // N was read
       
  5247     const signed char Done             = 10;
       
  5248 
       
  5249     const signed char InpLt            = 0; // <
       
  5250     const signed char InpQm            = 1; // ?
       
  5251     const signed char InpEm            = 2; // !
       
  5252     const signed char InpDash          = 3; // -
       
  5253     const signed char InpA             = 4; // A
       
  5254     const signed char InpE             = 5; // E
       
  5255     const signed char InpL             = 6; // L
       
  5256     const signed char InpN             = 7; // N
       
  5257     const signed char InpUnknown       = 8;
       
  5258 
       
  5259     static const signed char table[4][9] = {
       
  5260      /*  InpLt  InpQm  InpEm  InpDash  InpA   InpE   InpL   InpN   InpUnknown */
       
  5261         { Lt,    -1,    -1,    -1,      -1,    -1,    -1,    -1,    -1     }, // Init
       
  5262         { -1,    Qm,    Em,    -1,      -1,    -1,    -1,    -1,    -1     }, // Lt
       
  5263         { -1,    -1,    -1,    Dash,    CA,    CE,    -1,    CN,    -1     }, // Em
       
  5264         { -1,    -1,    -1,    -1,      -1,    -1,    CEL,   CEN,   -1     }  // CE
       
  5265     };
       
  5266     signed char state;
       
  5267     signed char input;
       
  5268 
       
  5269     if (parseStack==0 || parseStack->isEmpty()) {
       
  5270         state = Init;
       
  5271     } else {
       
  5272         state = parseStack->pop().state;
       
  5273 #if defined(QT_QXML_DEBUG)
       
  5274         qDebug("QXmlSimpleReader: parseMarkupdecl (cont) in state %d", state);
       
  5275 #endif
       
  5276         if (!parseStack->isEmpty()) {
       
  5277             ParseFunction function = parseStack->top().function;
       
  5278             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  5279                 parseStack->pop();
       
  5280 #if defined(QT_QXML_DEBUG)
       
  5281                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  5282 #endif
       
  5283             }
       
  5284             if (!(this->*function)()) {
       
  5285                 parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
       
  5286                 return false;
       
  5287             }
       
  5288         }
       
  5289     }
       
  5290 
       
  5291     for (;;) {
       
  5292         switch (state) {
       
  5293             case Qm:
       
  5294                 if (contentHnd) {
       
  5295                     if (!contentHnd->processingInstruction(name(),string())) {
       
  5296                         reportParseError(contentHnd->errorString());
       
  5297                         return false;
       
  5298                     }
       
  5299                 }
       
  5300                 return true;
       
  5301             case Dash:
       
  5302                 if (lexicalHnd) {
       
  5303                     if (!lexicalHnd->comment(string())) {
       
  5304                         reportParseError(lexicalHnd->errorString());
       
  5305                         return false;
       
  5306                     }
       
  5307                 }
       
  5308                 return true;
       
  5309             case CA:
       
  5310                 return true;
       
  5311             case CEL:
       
  5312                 return true;
       
  5313             case CEN:
       
  5314                 return true;
       
  5315             case CN:
       
  5316                 return true;
       
  5317             case Done:
       
  5318                 return true;
       
  5319             case -1:
       
  5320                 // Error
       
  5321                 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
       
  5322                 return false;
       
  5323         }
       
  5324 
       
  5325         if (atEnd()) {
       
  5326             unexpectedEof(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
       
  5327             return false;
       
  5328         }
       
  5329         if        (c == QLatin1Char('<')) {
       
  5330             input = InpLt;
       
  5331         } else if (c == QLatin1Char('?')) {
       
  5332             input = InpQm;
       
  5333         } else if (c == QLatin1Char('!')) {
       
  5334             input = InpEm;
       
  5335         } else if (c == QLatin1Char('-')) {
       
  5336             input = InpDash;
       
  5337         } else if (c == QLatin1Char('A')) {
       
  5338             input = InpA;
       
  5339         } else if (c == QLatin1Char('E')) {
       
  5340             input = InpE;
       
  5341         } else if (c == QLatin1Char('L')) {
       
  5342             input = InpL;
       
  5343         } else if (c == QLatin1Char('N')) {
       
  5344             input = InpN;
       
  5345         } else {
       
  5346             input = InpUnknown;
       
  5347         }
       
  5348         state = table[state][input];
       
  5349 
       
  5350         switch (state) {
       
  5351             case Lt:
       
  5352                 next();
       
  5353                 break;
       
  5354             case Em:
       
  5355                 next();
       
  5356                 break;
       
  5357             case CE:
       
  5358                 next();
       
  5359                 break;
       
  5360             case Qm:
       
  5361                 parsePI_xmldecl = false;
       
  5362                 if (!parsePI()) {
       
  5363                     parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
       
  5364                     return false;
       
  5365                 }
       
  5366                 break;
       
  5367             case Dash:
       
  5368                 if (!parseComment()) {
       
  5369                     parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
       
  5370                     return false;
       
  5371                 }
       
  5372                 break;
       
  5373             case CA:
       
  5374                 if (!parseAttlistDecl()) {
       
  5375                     parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
       
  5376                     return false;
       
  5377                 }
       
  5378                 break;
       
  5379             case CEL:
       
  5380                 if (!parseElementDecl()) {
       
  5381                     parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
       
  5382                     return false;
       
  5383                 }
       
  5384                 break;
       
  5385             case CEN:
       
  5386                 if (!parseEntityDecl()) {
       
  5387                     parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
       
  5388                     return false;
       
  5389                 }
       
  5390                 break;
       
  5391             case CN:
       
  5392                 if (!parseNotationDecl()) {
       
  5393                     parseFailed(&QXmlSimpleReaderPrivate::parseMarkupdecl, state);
       
  5394                     return false;
       
  5395                 }
       
  5396                 break;
       
  5397         }
       
  5398     }
       
  5399     return false;
       
  5400 }
       
  5401 
       
  5402 /*
       
  5403   Parse a PEReference [69]
       
  5404 */
       
  5405 bool QXmlSimpleReaderPrivate::parsePEReference()
       
  5406 {
       
  5407     const signed char Init             = 0;
       
  5408     const signed char Next             = 1;
       
  5409     const signed char Name             = 2;
       
  5410     const signed char NameR            = 3; // same as Name, but already reported
       
  5411     const signed char Done             = 4;
       
  5412 
       
  5413     const signed char InpSemi          = 0; // ;
       
  5414     const signed char InpPer           = 1; // %
       
  5415     const signed char InpUnknown       = 2;
       
  5416 
       
  5417     static const signed char table[4][3] = {
       
  5418      /*  InpSemi  InpPer  InpUnknown */
       
  5419         { -1,      Next,   -1    }, // Init
       
  5420         { -1,      -1,     Name  }, // Next
       
  5421         { Done,    -1,     -1    }, // Name
       
  5422         { Done,    -1,     -1    }  // NameR
       
  5423     };
       
  5424     signed char state;
       
  5425     signed char input;
       
  5426 
       
  5427     if (parseStack==0 || parseStack->isEmpty()) {
       
  5428         state = Init;
       
  5429     } else {
       
  5430         state = parseStack->pop().state;
       
  5431 #if defined(QT_QXML_DEBUG)
       
  5432         qDebug("QXmlSimpleReader: parsePEReference (cont) in state %d", state);
       
  5433 #endif
       
  5434         if (!parseStack->isEmpty()) {
       
  5435             ParseFunction function = parseStack->top().function;
       
  5436             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  5437                 parseStack->pop();
       
  5438 #if defined(QT_QXML_DEBUG)
       
  5439                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  5440 #endif
       
  5441             }
       
  5442             if (!(this->*function)()) {
       
  5443                 parseFailed(&QXmlSimpleReaderPrivate::parsePEReference, state);
       
  5444                 return false;
       
  5445             }
       
  5446         }
       
  5447     }
       
  5448 
       
  5449     for (;;) {
       
  5450         switch (state) {
       
  5451             case Name:
       
  5452                 {
       
  5453                     bool skipIt = true;
       
  5454                     QString xmlRefString;
       
  5455 
       
  5456                     QMap<QString,QString>::Iterator it;
       
  5457                     it = parameterEntities.find(ref());
       
  5458                     if (it != parameterEntities.end()) {
       
  5459                         skipIt = false;
       
  5460                         xmlRefString = *it;
       
  5461                     } else if (entityRes) {
       
  5462                         QMap<QString,QXmlSimpleReaderPrivate::ExternParameterEntity>::Iterator it2;
       
  5463                         it2 = externParameterEntities.find(ref());
       
  5464                         QXmlInputSource *ret = 0;
       
  5465                         if (it2 != externParameterEntities.end()) {
       
  5466                             if (!entityRes->resolveEntity((*it2).publicId, (*it2).systemId, ret)) {
       
  5467                                 delete ret;
       
  5468                                 reportParseError(entityRes->errorString());
       
  5469                                 return false;
       
  5470                             }
       
  5471                             if (ret) {
       
  5472                                 xmlRefString = ret->data();
       
  5473                                 delete ret;
       
  5474                                 if (!stripTextDecl(xmlRefString)) {
       
  5475                                     reportParseError(QLatin1String(XMLERR_ERRORINTEXTDECL));
       
  5476                                     return false;
       
  5477                                 }
       
  5478                                 skipIt = false;
       
  5479                             }
       
  5480                         }
       
  5481                     }
       
  5482 
       
  5483                     if (skipIt) {
       
  5484                         if (contentHnd) {
       
  5485                             if (!contentHnd->skippedEntity(QLatin1Char('%') + ref())) {
       
  5486                                 reportParseError(contentHnd->errorString());
       
  5487                                 return false;
       
  5488                             }
       
  5489                         }
       
  5490                     } else {
       
  5491                         if (parsePEReference_context == InEntityValue) {
       
  5492                             // Included in literal
       
  5493                             if (!insertXmlRef(xmlRefString, ref(), true))
       
  5494                                 return false;
       
  5495                         } else if (parsePEReference_context == InDTD) {
       
  5496                             // Included as PE
       
  5497                             if (!insertXmlRef(QLatin1Char(' ') + xmlRefString + QLatin1Char(' '), ref(), false))
       
  5498                                 return false;
       
  5499                         }
       
  5500                     }
       
  5501                 }
       
  5502                 state = NameR;
       
  5503                 break;
       
  5504             case Done:
       
  5505                 return true;
       
  5506             case -1:
       
  5507                 // Error
       
  5508                 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
       
  5509                 return false;
       
  5510         }
       
  5511 
       
  5512         if (atEnd()) {
       
  5513             unexpectedEof(&QXmlSimpleReaderPrivate::parsePEReference, state);
       
  5514             return false;
       
  5515         }
       
  5516         if        (c == QLatin1Char(';')) {
       
  5517             input = InpSemi;
       
  5518         } else if (c == QLatin1Char('%')) {
       
  5519             input = InpPer;
       
  5520         } else {
       
  5521             input = InpUnknown;
       
  5522         }
       
  5523         state = table[state][input];
       
  5524 
       
  5525         switch (state) {
       
  5526             case Next:
       
  5527                 next();
       
  5528                 break;
       
  5529             case Name:
       
  5530             case NameR:
       
  5531                 parseName_useRef = true;
       
  5532                 if (!parseName()) {
       
  5533                     parseFailed(&QXmlSimpleReaderPrivate::parsePEReference, state);
       
  5534                     return false;
       
  5535                 }
       
  5536                 break;
       
  5537             case Done:
       
  5538                 next();
       
  5539                 break;
       
  5540         }
       
  5541     }
       
  5542     return false;
       
  5543 }
       
  5544 
       
  5545 /*
       
  5546   Parse a AttlistDecl [52].
       
  5547 
       
  5548   Precondition: the beginning '<!' is already read and the head
       
  5549   stands on the 'A' of '<!ATTLIST'
       
  5550 */
       
  5551 bool QXmlSimpleReaderPrivate::parseAttlistDecl()
       
  5552 {
       
  5553     const signed char Init             =  0;
       
  5554     const signed char Attlist          =  1; // parse the string "ATTLIST"
       
  5555     const signed char Ws               =  2; // whitespace read
       
  5556     const signed char Name             =  3; // parse name
       
  5557     const signed char Ws1              =  4; // whitespace read
       
  5558     const signed char Attdef           =  5; // parse the AttDef
       
  5559     const signed char Ws2              =  6; // whitespace read
       
  5560     const signed char Atttype          =  7; // parse the AttType
       
  5561     const signed char Ws3              =  8; // whitespace read
       
  5562     const signed char DDecH            =  9; // DefaultDecl with #
       
  5563     const signed char DefReq           = 10; // parse the string "REQUIRED"
       
  5564     const signed char DefImp           = 11; // parse the string "IMPLIED"
       
  5565     const signed char DefFix           = 12; // parse the string "FIXED"
       
  5566     const signed char Attval           = 13; // parse the AttValue
       
  5567     const signed char Ws4              = 14; // whitespace read
       
  5568     const signed char Done             = 15;
       
  5569 
       
  5570     const signed char InpWs            = 0; // white space
       
  5571     const signed char InpGt            = 1; // >
       
  5572     const signed char InpHash          = 2; // #
       
  5573     const signed char InpA             = 3; // A
       
  5574     const signed char InpI             = 4; // I
       
  5575     const signed char InpF             = 5; // F
       
  5576     const signed char InpR             = 6; // R
       
  5577     const signed char InpUnknown       = 7;
       
  5578 
       
  5579     static const signed char table[15][8] = {
       
  5580      /*  InpWs    InpGt    InpHash  InpA      InpI     InpF     InpR     InpUnknown */
       
  5581         { -1,      -1,      -1,      Attlist,  -1,      -1,      -1,      -1      }, // Init
       
  5582         { Ws,      -1,      -1,      -1,       -1,      -1,      -1,      -1      }, // Attlist
       
  5583         { -1,      -1,      -1,      Name,     Name,    Name,    Name,    Name    }, // Ws
       
  5584         { Ws1,     Done,    Attdef,  Attdef,   Attdef,  Attdef,  Attdef,  Attdef  }, // Name
       
  5585         { -1,      Done,    Attdef,  Attdef,   Attdef,  Attdef,  Attdef,  Attdef  }, // Ws1
       
  5586         { Ws2,     -1,      -1,      -1,       -1,      -1,      -1,      -1      }, // Attdef
       
  5587         { -1,      Atttype, Atttype, Atttype,  Atttype, Atttype, Atttype, Atttype }, // Ws2
       
  5588         { Ws3,     -1,      -1,      -1,       -1,      -1,      -1,      -1      }, // Attype
       
  5589         { -1,      Attval,  DDecH,   Attval,   Attval,  Attval,  Attval,  Attval  }, // Ws3
       
  5590         { -1,      -1,      -1,      -1,       DefImp,  DefFix,  DefReq,  -1      }, // DDecH
       
  5591         { Ws4,     Ws4,     -1,      -1,       -1,      -1,      -1,      -1      }, // DefReq
       
  5592         { Ws4,     Ws4,     -1,      -1,       -1,      -1,      -1,      -1      }, // DefImp
       
  5593         { Ws3,     -1,      -1,      -1,       -1,      -1,      -1,      -1      }, // DefFix
       
  5594         { Ws4,     Ws4,     -1,      -1,       -1,      -1,      -1,      -1      }, // Attval
       
  5595         { -1,      Done,    Attdef,  Attdef,   Attdef,  Attdef,  Attdef,  Attdef  }  // Ws4
       
  5596     };
       
  5597     signed char state;
       
  5598     signed char input;
       
  5599 
       
  5600     if (parseStack==0 || parseStack->isEmpty()) {
       
  5601         state = Init;
       
  5602     } else {
       
  5603         state = parseStack->pop().state;
       
  5604 #if defined(QT_QXML_DEBUG)
       
  5605         qDebug("QXmlSimpleReader: parseAttlistDecl (cont) in state %d", state);
       
  5606 #endif
       
  5607         if (!parseStack->isEmpty()) {
       
  5608             ParseFunction function = parseStack->top().function;
       
  5609             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  5610                 parseStack->pop();
       
  5611 #if defined(QT_QXML_DEBUG)
       
  5612                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  5613 #endif
       
  5614             }
       
  5615             if (!(this->*function)()) {
       
  5616                 parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
       
  5617                 return false;
       
  5618             }
       
  5619         }
       
  5620     }
       
  5621 
       
  5622     for (;;) {
       
  5623         switch (state) {
       
  5624             case Name:
       
  5625                 attDeclEName = name();
       
  5626                 break;
       
  5627             case Attdef:
       
  5628                 attDeclAName = name();
       
  5629                 break;
       
  5630             case Done:
       
  5631                 return true;
       
  5632             case -1:
       
  5633                 // Error
       
  5634                 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
       
  5635                 return false;
       
  5636         }
       
  5637 
       
  5638         if (atEnd()) {
       
  5639             unexpectedEof(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
       
  5640             return false;
       
  5641         }
       
  5642         if (is_S(c)) {
       
  5643             input = InpWs;
       
  5644         } else if (c == QLatin1Char('>')) {
       
  5645             input = InpGt;
       
  5646         } else if (c == QLatin1Char('#')) {
       
  5647             input = InpHash;
       
  5648         } else if (c == QLatin1Char('A')) {
       
  5649             input = InpA;
       
  5650         } else if (c == QLatin1Char('I')) {
       
  5651             input = InpI;
       
  5652         } else if (c == QLatin1Char('F')) {
       
  5653             input = InpF;
       
  5654         } else if (c == QLatin1Char('R')) {
       
  5655             input = InpR;
       
  5656         } else {
       
  5657             input = InpUnknown;
       
  5658         }
       
  5659         state = table[state][input];
       
  5660 
       
  5661         switch (state) {
       
  5662             case Attlist:
       
  5663                 parseString_s = QLatin1String("ATTLIST");
       
  5664                 if (!parseString()) {
       
  5665                     parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
       
  5666                     return false;
       
  5667                 }
       
  5668                 break;
       
  5669             case Ws:
       
  5670             case Ws1:
       
  5671             case Ws2:
       
  5672             case Ws3:
       
  5673                 if (!eat_ws()) {
       
  5674                     parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
       
  5675                     return false;
       
  5676                 }
       
  5677                 break;
       
  5678             case Name:
       
  5679                 parseName_useRef = false;
       
  5680                 if (!parseName()) {
       
  5681                     parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
       
  5682                     return false;
       
  5683                 }
       
  5684                 break;
       
  5685             case Attdef:
       
  5686                 parseName_useRef = false;
       
  5687                 if (!parseName()) {
       
  5688                     parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
       
  5689                     return false;
       
  5690                 }
       
  5691                 break;
       
  5692             case Atttype:
       
  5693                 if (!parseAttType()) {
       
  5694                     parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
       
  5695                     return false;
       
  5696                 }
       
  5697                 break;
       
  5698             case DDecH:
       
  5699                 next();
       
  5700                 break;
       
  5701             case DefReq:
       
  5702                 parseString_s = QLatin1String("REQUIRED");
       
  5703                 if (!parseString()) {
       
  5704                     parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
       
  5705                     return false;
       
  5706                 }
       
  5707                 break;
       
  5708             case DefImp:
       
  5709                 parseString_s = QLatin1String("IMPLIED");
       
  5710                 if (!parseString()) {
       
  5711                     parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
       
  5712                     return false;
       
  5713                 }
       
  5714                 break;
       
  5715             case DefFix:
       
  5716                 parseString_s = QLatin1String("FIXED");
       
  5717                 if (!parseString()) {
       
  5718                     parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
       
  5719                     return false;
       
  5720                 }
       
  5721                 break;
       
  5722             case Attval:
       
  5723                 if (!parseAttValue()) {
       
  5724                     parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
       
  5725                     return false;
       
  5726                 }
       
  5727                 break;
       
  5728             case Ws4:
       
  5729                 if (declHnd) {
       
  5730                     // ### not all values are computed yet...
       
  5731                     if (!declHnd->attributeDecl(attDeclEName, attDeclAName, QLatin1String(""), QLatin1String(""), QLatin1String(""))) {
       
  5732                         reportParseError(declHnd->errorString());
       
  5733                         return false;
       
  5734                     }
       
  5735                 }
       
  5736                 if (!eat_ws()) {
       
  5737                     parseFailed(&QXmlSimpleReaderPrivate::parseAttlistDecl, state);
       
  5738                     return false;
       
  5739                 }
       
  5740                 break;
       
  5741             case Done:
       
  5742                 next();
       
  5743                 break;
       
  5744         }
       
  5745     }
       
  5746     return false;
       
  5747 }
       
  5748 
       
  5749 /*
       
  5750   Parse a AttType [54]
       
  5751 */
       
  5752 bool QXmlSimpleReaderPrivate::parseAttType()
       
  5753 {
       
  5754     const signed char Init             =  0;
       
  5755     const signed char ST               =  1; // StringType
       
  5756     const signed char TTI              =  2; // TokenizedType starting with 'I'
       
  5757     const signed char TTI2             =  3; // TokenizedType helpstate
       
  5758     const signed char TTI3             =  4; // TokenizedType helpstate
       
  5759     const signed char TTE              =  5; // TokenizedType starting with 'E'
       
  5760     const signed char TTEY             =  6; // TokenizedType starting with 'ENTITY'
       
  5761     const signed char TTEI             =  7; // TokenizedType starting with 'ENTITI'
       
  5762     const signed char N                =  8; // N read (TokenizedType or Notation)
       
  5763     const signed char TTNM             =  9; // TokenizedType starting with 'NM'
       
  5764     const signed char TTNM2            = 10; // TokenizedType helpstate
       
  5765     const signed char NO               = 11; // Notation
       
  5766     const signed char NO2              = 12; // Notation helpstate
       
  5767     const signed char NO3              = 13; // Notation helpstate
       
  5768     const signed char NOName           = 14; // Notation, read name
       
  5769     const signed char NO4              = 15; // Notation helpstate
       
  5770     const signed char EN               = 16; // Enumeration
       
  5771     const signed char ENNmt            = 17; // Enumeration, read Nmtoken
       
  5772     const signed char EN2              = 18; // Enumeration helpstate
       
  5773     const signed char ADone            = 19; // almost done (make next and accept)
       
  5774     const signed char Done             = 20;
       
  5775 
       
  5776     const signed char InpWs            =  0; // whitespace
       
  5777     const signed char InpOp            =  1; // (
       
  5778     const signed char InpCp            =  2; //)
       
  5779     const signed char InpPipe          =  3; // |
       
  5780     const signed char InpC             =  4; // C
       
  5781     const signed char InpE             =  5; // E
       
  5782     const signed char InpI             =  6; // I
       
  5783     const signed char InpM             =  7; // M
       
  5784     const signed char InpN             =  8; // N
       
  5785     const signed char InpO             =  9; // O
       
  5786     const signed char InpR             = 10; // R
       
  5787     const signed char InpS             = 11; // S
       
  5788     const signed char InpY             = 12; // Y
       
  5789     const signed char InpUnknown       = 13;
       
  5790 
       
  5791     static const signed char table[19][14] = {
       
  5792      /*  InpWs    InpOp    InpCp    InpPipe  InpC     InpE     InpI     InpM     InpN     InpO     InpR     InpS     InpY     InpUnknown */
       
  5793         { -1,      EN,      -1,      -1,      ST,      TTE,     TTI,     -1,      N,       -1,      -1,      -1,      -1,      -1     }, // Init
       
  5794         { Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done   }, // ST
       
  5795         { Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    TTI2,    Done,    Done,    Done   }, // TTI
       
  5796         { Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    TTI3,    Done,    Done   }, // TTI2
       
  5797         { Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done   }, // TTI3
       
  5798         { -1,      -1,      -1,      -1,      -1,      -1,      TTEI,    -1,      -1,      -1,      -1,      -1,      TTEY,    -1     }, // TTE
       
  5799         { Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done   }, // TTEY
       
  5800         { Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done   }, // TTEI
       
  5801         { -1,      -1,      -1,      -1,      -1,      -1,      -1,      TTNM,    -1,      NO,      -1,      -1,      -1,      -1     }, // N
       
  5802         { Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    TTNM2,   Done,    Done   }, // TTNM
       
  5803         { Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done,    Done   }, // TTNM2
       
  5804         { NO2,     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1     }, // NO
       
  5805         { -1,      NO3,     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1     }, // NO2
       
  5806         { NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName,  NOName }, // NO3
       
  5807         { NO4,     -1,      ADone,   NO3,     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1     }, // NOName
       
  5808         { -1,      -1,      ADone,   NO3,     -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1     }, // NO4
       
  5809         { -1,      -1,      ENNmt,   -1,      ENNmt,   ENNmt,   ENNmt,   ENNmt,   ENNmt,   ENNmt,   ENNmt,   ENNmt,   ENNmt,   ENNmt  }, // EN
       
  5810         { EN2,     -1,      ADone,   EN,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1     }, // ENNmt
       
  5811         { -1,      -1,      ADone,   EN,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1     }  // EN2
       
  5812     };
       
  5813     signed char state;
       
  5814     signed char input;
       
  5815 
       
  5816     if (parseStack==0 || parseStack->isEmpty()) {
       
  5817         state = Init;
       
  5818     } else {
       
  5819         state = parseStack->pop().state;
       
  5820 #if defined(QT_QXML_DEBUG)
       
  5821         qDebug("QXmlSimpleReader: parseAttType (cont) in state %d", state);
       
  5822 #endif
       
  5823         if (!parseStack->isEmpty()) {
       
  5824             ParseFunction function = parseStack->top().function;
       
  5825             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  5826                 parseStack->pop();
       
  5827 #if defined(QT_QXML_DEBUG)
       
  5828                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  5829 #endif
       
  5830             }
       
  5831             if (!(this->*function)()) {
       
  5832                 parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
       
  5833                 return false;
       
  5834             }
       
  5835         }
       
  5836     }
       
  5837 
       
  5838     for (;;) {
       
  5839         switch (state) {
       
  5840             case ADone:
       
  5841                 return true;
       
  5842             case Done:
       
  5843                 return true;
       
  5844             case -1:
       
  5845                 // Error
       
  5846                 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
       
  5847                 return false;
       
  5848         }
       
  5849 
       
  5850         if (atEnd()) {
       
  5851             unexpectedEof(&QXmlSimpleReaderPrivate::parseAttType, state);
       
  5852             return false;
       
  5853         }
       
  5854         if (is_S(c)) {
       
  5855             input = InpWs;
       
  5856         } else if (c == QLatin1Char('(')) {
       
  5857             input = InpOp;
       
  5858         } else if (c == QLatin1Char(')')) {
       
  5859             input = InpCp;
       
  5860         } else if (c == QLatin1Char('|')) {
       
  5861             input = InpPipe;
       
  5862         } else if (c == QLatin1Char('C')) {
       
  5863             input = InpC;
       
  5864         } else if (c == QLatin1Char('E')) {
       
  5865             input = InpE;
       
  5866         } else if (c == QLatin1Char('I')) {
       
  5867             input = InpI;
       
  5868         } else if (c == QLatin1Char('M')) {
       
  5869             input = InpM;
       
  5870         } else if (c == QLatin1Char('N')) {
       
  5871             input = InpN;
       
  5872         } else if (c == QLatin1Char('O')) {
       
  5873             input = InpO;
       
  5874         } else if (c == QLatin1Char('R')) {
       
  5875             input = InpR;
       
  5876         } else if (c == QLatin1Char('S')) {
       
  5877             input = InpS;
       
  5878         } else if (c == QLatin1Char('Y')) {
       
  5879             input = InpY;
       
  5880         } else {
       
  5881             input = InpUnknown;
       
  5882         }
       
  5883         state = table[state][input];
       
  5884 
       
  5885         switch (state) {
       
  5886             case ST:
       
  5887                 parseString_s = QLatin1String("CDATA");
       
  5888                 if (!parseString()) {
       
  5889                     parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
       
  5890                     return false;
       
  5891                 }
       
  5892                 break;
       
  5893             case TTI:
       
  5894                 parseString_s = QLatin1String("ID");
       
  5895                 if (!parseString()) {
       
  5896                     parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
       
  5897                     return false;
       
  5898                 }
       
  5899                 break;
       
  5900             case TTI2:
       
  5901                 parseString_s = QLatin1String("REF");
       
  5902                 if (!parseString()) {
       
  5903                     parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
       
  5904                     return false;
       
  5905                 }
       
  5906                 break;
       
  5907             case TTI3:
       
  5908                 next(); // S
       
  5909                 break;
       
  5910             case TTE:
       
  5911                 parseString_s = QLatin1String("ENTIT");
       
  5912                 if (!parseString()) {
       
  5913                     parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
       
  5914                     return false;
       
  5915                 }
       
  5916                 break;
       
  5917             case TTEY:
       
  5918                 next(); // Y
       
  5919                 break;
       
  5920             case TTEI:
       
  5921                 parseString_s = QLatin1String("IES");
       
  5922                 if (!parseString()) {
       
  5923                     parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
       
  5924                     return false;
       
  5925                 }
       
  5926                 break;
       
  5927             case N:
       
  5928                 next(); // N
       
  5929                 break;
       
  5930             case TTNM:
       
  5931                 parseString_s = QLatin1String("MTOKEN");
       
  5932                 if (!parseString()) {
       
  5933                     parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
       
  5934                     return false;
       
  5935                 }
       
  5936                 break;
       
  5937             case TTNM2:
       
  5938                 next(); // S
       
  5939                 break;
       
  5940             case NO:
       
  5941                 parseString_s = QLatin1String("OTATION");
       
  5942                 if (!parseString()) {
       
  5943                     parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
       
  5944                     return false;
       
  5945                 }
       
  5946                 break;
       
  5947             case NO2:
       
  5948                 if (!eat_ws()) {
       
  5949                     parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
       
  5950                     return false;
       
  5951                 }
       
  5952                 break;
       
  5953             case NO3:
       
  5954                 if (!next_eat_ws()) {
       
  5955                     parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
       
  5956                     return false;
       
  5957                 }
       
  5958                 break;
       
  5959             case NOName:
       
  5960                 parseName_useRef = false;
       
  5961                 if (!parseName()) {
       
  5962                     parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
       
  5963                     return false;
       
  5964                 }
       
  5965                 break;
       
  5966             case NO4:
       
  5967                 if (!eat_ws()) {
       
  5968                     parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
       
  5969                     return false;
       
  5970                 }
       
  5971                 break;
       
  5972             case EN:
       
  5973                 if (!next_eat_ws()) {
       
  5974                     parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
       
  5975                     return false;
       
  5976                 }
       
  5977                 break;
       
  5978             case ENNmt:
       
  5979                 if (!parseNmtoken()) {
       
  5980                     parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
       
  5981                     return false;
       
  5982                 }
       
  5983                 break;
       
  5984             case EN2:
       
  5985                 if (!eat_ws()) {
       
  5986                     parseFailed(&QXmlSimpleReaderPrivate::parseAttType, state);
       
  5987                     return false;
       
  5988                 }
       
  5989                 break;
       
  5990             case ADone:
       
  5991                 next();
       
  5992                 break;
       
  5993         }
       
  5994     }
       
  5995     return false;
       
  5996 }
       
  5997 
       
  5998 /*
       
  5999   Parse a AttValue [10]
       
  6000 
       
  6001   Precondition: the head stands on the beginning " or '
       
  6002 
       
  6003   If this function was successful, the head stands on the first
       
  6004   character after the closing " or ' and the value of the attribute
       
  6005   is in string().
       
  6006 */
       
  6007 bool QXmlSimpleReaderPrivate::parseAttValue()
       
  6008 {
       
  6009     const signed char Init             = 0;
       
  6010     const signed char Dq               = 1; // double quotes were read
       
  6011     const signed char DqRef            = 2; // read references in double quotes
       
  6012     const signed char DqC              = 3; // signed character read in double quotes
       
  6013     const signed char Sq               = 4; // single quotes were read
       
  6014     const signed char SqRef            = 5; // read references in single quotes
       
  6015     const signed char SqC              = 6; // signed character read in single quotes
       
  6016     const signed char Done             = 7;
       
  6017 
       
  6018     const signed char InpDq            = 0; // "
       
  6019     const signed char InpSq            = 1; // '
       
  6020     const signed char InpAmp           = 2; // &
       
  6021     const signed char InpLt            = 3; // <
       
  6022     const signed char InpUnknown       = 4;
       
  6023 
       
  6024     static const signed char table[7][5] = {
       
  6025      /*  InpDq  InpSq  InpAmp  InpLt InpUnknown */
       
  6026         { Dq,    Sq,    -1,     -1,   -1    }, // Init
       
  6027         { Done,  DqC,   DqRef,  -1,   DqC   }, // Dq
       
  6028         { Done,  DqC,   DqRef,  -1,   DqC   }, // DqRef
       
  6029         { Done,  DqC,   DqRef,  -1,   DqC   }, // DqC
       
  6030         { SqC,   Done,  SqRef,  -1,   SqC   }, // Sq
       
  6031         { SqC,   Done,  SqRef,  -1,   SqC   }, // SqRef
       
  6032         { SqC,   Done,  SqRef,  -1,   SqC   }  // SqRef
       
  6033     };
       
  6034     signed char state;
       
  6035     signed char input;
       
  6036 
       
  6037     if (parseStack==0 || parseStack->isEmpty()) {
       
  6038         state = Init;
       
  6039     } else {
       
  6040         state = parseStack->pop().state;
       
  6041 #if defined(QT_QXML_DEBUG)
       
  6042         qDebug("QXmlSimpleReader: parseAttValue (cont) in state %d", state);
       
  6043 #endif
       
  6044         if (!parseStack->isEmpty()) {
       
  6045             ParseFunction function = parseStack->top().function;
       
  6046             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  6047                 parseStack->pop();
       
  6048 #if defined(QT_QXML_DEBUG)
       
  6049                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  6050 #endif
       
  6051             }
       
  6052             if (!(this->*function)()) {
       
  6053                 parseFailed(&QXmlSimpleReaderPrivate::parseAttValue, state);
       
  6054                 return false;
       
  6055             }
       
  6056         }
       
  6057     }
       
  6058 
       
  6059     for (;;) {
       
  6060         switch (state) {
       
  6061             case Done:
       
  6062                 return true;
       
  6063             case -1:
       
  6064                 // Error
       
  6065                 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
       
  6066                 return false;
       
  6067         }
       
  6068 
       
  6069         if (atEnd()) {
       
  6070             unexpectedEof(&QXmlSimpleReaderPrivate::parseAttValue, state);
       
  6071             return false;
       
  6072         }
       
  6073         if        (c == QLatin1Char('"')) {
       
  6074             input = InpDq;
       
  6075         } else if (c == QLatin1Char('\'')) {
       
  6076             input = InpSq;
       
  6077         } else if (c == QLatin1Char('&')) {
       
  6078             input = InpAmp;
       
  6079         } else if (c == QLatin1Char('<')) {
       
  6080             input = InpLt;
       
  6081         } else {
       
  6082             input = InpUnknown;
       
  6083         }
       
  6084         state = table[state][input];
       
  6085 
       
  6086         switch (state) {
       
  6087             case Dq:
       
  6088             case Sq:
       
  6089                 stringClear();
       
  6090                 next();
       
  6091                 break;
       
  6092             case DqRef:
       
  6093             case SqRef:
       
  6094                 parseReference_context = InAttributeValue;
       
  6095                 if (!parseReference()) {
       
  6096                     parseFailed(&QXmlSimpleReaderPrivate::parseAttValue, state);
       
  6097                     return false;
       
  6098                 }
       
  6099                 break;
       
  6100             case DqC:
       
  6101             case SqC:
       
  6102                 stringAddC();
       
  6103                 next();
       
  6104                 break;
       
  6105             case Done:
       
  6106                 next();
       
  6107                 break;
       
  6108         }
       
  6109     }
       
  6110     return false;
       
  6111 }
       
  6112 
       
  6113 /*
       
  6114   Parse a elementdecl [45].
       
  6115 
       
  6116   Precondition: the beginning '<!E' is already read and the head
       
  6117   stands on the 'L' of '<!ELEMENT'
       
  6118 */
       
  6119 bool QXmlSimpleReaderPrivate::parseElementDecl()
       
  6120 {
       
  6121     const signed char Init             =  0;
       
  6122     const signed char Elem             =  1; // parse the beginning string
       
  6123     const signed char Ws1              =  2; // whitespace required
       
  6124     const signed char Nam              =  3; // parse Name
       
  6125     const signed char Ws2              =  4; // whitespace required
       
  6126     const signed char Empty            =  5; // read EMPTY
       
  6127     const signed char Any              =  6; // read ANY
       
  6128     const signed char Cont             =  7; // read contentspec (except ANY or EMPTY)
       
  6129     const signed char Mix              =  8; // read Mixed
       
  6130     const signed char Mix2             =  9; //
       
  6131     const signed char Mix3             = 10; //
       
  6132     const signed char MixN1            = 11; //
       
  6133     const signed char MixN2            = 12; //
       
  6134     const signed char MixN3            = 13; //
       
  6135     const signed char MixN4            = 14; //
       
  6136     const signed char Cp               = 15; // parse cp
       
  6137     const signed char Cp2              = 16; //
       
  6138     const signed char WsD              = 17; // eat whitespace before Done
       
  6139     const signed char Done             = 18;
       
  6140 
       
  6141     const signed char InpWs            =  0;
       
  6142     const signed char InpGt            =  1; // >
       
  6143     const signed char InpPipe          =  2; // |
       
  6144     const signed char InpOp            =  3; // (
       
  6145     const signed char InpCp            =  4; //)
       
  6146     const signed char InpHash          =  5; // #
       
  6147     const signed char InpQm            =  6; // ?
       
  6148     const signed char InpAst           =  7; // *
       
  6149     const signed char InpPlus          =  8; // +
       
  6150     const signed char InpA             =  9; // A
       
  6151     const signed char InpE             = 10; // E
       
  6152     const signed char InpL             = 11; // L
       
  6153     const signed char InpUnknown       = 12;
       
  6154 
       
  6155     static const signed char table[18][13] = {
       
  6156      /*  InpWs   InpGt  InpPipe  InpOp  InpCp   InpHash  InpQm  InpAst  InpPlus  InpA    InpE    InpL    InpUnknown */
       
  6157         { -1,     -1,    -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     Elem,   -1     }, // Init
       
  6158         { Ws1,    -1,    -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Elem
       
  6159         { -1,     -1,    -1,      -1,    -1,     -1,      -1,    -1,     -1,      Nam,    Nam,    Nam,    Nam    }, // Ws1
       
  6160         { Ws2,    -1,    -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Nam
       
  6161         { -1,     -1,    -1,      Cont,  -1,     -1,      -1,    -1,     -1,      Any,    Empty,  -1,     -1     }, // Ws2
       
  6162         { WsD,    Done,  -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Empty
       
  6163         { WsD,    Done,  -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Any
       
  6164         { -1,     -1,    -1,      Cp,    Cp,     Mix,     -1,    -1,     -1,      Cp,     Cp,     Cp,     Cp     }, // Cont
       
  6165         { Mix2,   -1,    MixN1,   -1,    Mix3,   -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Mix
       
  6166         { -1,     -1,    MixN1,   -1,    Mix3,   -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Mix2
       
  6167         { WsD,    Done,  -1,      -1,    -1,     -1,      -1,    WsD,    -1,      -1,     -1,     -1,     -1     }, // Mix3
       
  6168         { -1,     -1,    -1,      -1,    -1,     -1,      -1,    -1,     -1,      MixN2,  MixN2,  MixN2,  MixN2  }, // MixN1
       
  6169         { MixN3,  -1,    MixN1,   -1,    MixN4,  -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // MixN2
       
  6170         { -1,     -1,    MixN1,   -1,    MixN4,  -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // MixN3
       
  6171         { -1,     -1,    -1,      -1,    -1,     -1,      -1,    WsD,    -1,      -1,     -1,     -1,     -1     }, // MixN4
       
  6172         { WsD,    Done,  -1,      -1,    -1,     -1,      Cp2,   Cp2,    Cp2,     -1,     -1,     -1,     -1     }, // Cp
       
  6173         { WsD,    Done,  -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }, // Cp2
       
  6174         { -1,     Done,  -1,      -1,    -1,     -1,      -1,    -1,     -1,      -1,     -1,     -1,     -1     }  // WsD
       
  6175     };
       
  6176     signed char state;
       
  6177     signed char input;
       
  6178 
       
  6179     if (parseStack==0 || parseStack->isEmpty()) {
       
  6180         state = Init;
       
  6181     } else {
       
  6182         state = parseStack->pop().state;
       
  6183 #if defined(QT_QXML_DEBUG)
       
  6184         qDebug("QXmlSimpleReader: parseElementDecl (cont) in state %d", state);
       
  6185 #endif
       
  6186         if (!parseStack->isEmpty()) {
       
  6187             ParseFunction function = parseStack->top().function;
       
  6188             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  6189                 parseStack->pop();
       
  6190 #if defined(QT_QXML_DEBUG)
       
  6191                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  6192 #endif
       
  6193             }
       
  6194             if (!(this->*function)()) {
       
  6195                 parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
       
  6196                 return false;
       
  6197             }
       
  6198         }
       
  6199     }
       
  6200 
       
  6201     for (;;) {
       
  6202         switch (state) {
       
  6203             case Done:
       
  6204                 return true;
       
  6205             case -1:
       
  6206                 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
       
  6207                 return false;
       
  6208         }
       
  6209 
       
  6210         if (atEnd()) {
       
  6211             unexpectedEof(&QXmlSimpleReaderPrivate::parseElementDecl, state);
       
  6212             return false;
       
  6213         }
       
  6214         if (is_S(c)) {
       
  6215             input = InpWs;
       
  6216         } else if (c == QLatin1Char('>')) {
       
  6217             input = InpGt;
       
  6218         } else if (c == QLatin1Char('|')) {
       
  6219             input = InpPipe;
       
  6220         } else if (c == QLatin1Char('(')) {
       
  6221             input = InpOp;
       
  6222         } else if (c == QLatin1Char(')')) {
       
  6223             input = InpCp;
       
  6224         } else if (c == QLatin1Char('#')) {
       
  6225             input = InpHash;
       
  6226         } else if (c == QLatin1Char('?')) {
       
  6227             input = InpQm;
       
  6228         } else if (c == QLatin1Char('*')) {
       
  6229             input = InpAst;
       
  6230         } else if (c == QLatin1Char('+')) {
       
  6231             input = InpPlus;
       
  6232         } else if (c == QLatin1Char('A')) {
       
  6233             input = InpA;
       
  6234         } else if (c == QLatin1Char('E')) {
       
  6235             input = InpE;
       
  6236         } else if (c == QLatin1Char('L')) {
       
  6237             input = InpL;
       
  6238         } else {
       
  6239             input = InpUnknown;
       
  6240         }
       
  6241         state = table[state][input];
       
  6242 
       
  6243         switch (state) {
       
  6244             case Elem:
       
  6245                 parseString_s = QLatin1String("LEMENT");
       
  6246                 if (!parseString()) {
       
  6247                     parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
       
  6248                     return false;
       
  6249                 }
       
  6250                 break;
       
  6251             case Ws1:
       
  6252                 if (!eat_ws()) {
       
  6253                     parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
       
  6254                     return false;
       
  6255                 }
       
  6256                 break;
       
  6257             case Nam:
       
  6258                 parseName_useRef = false;
       
  6259                 if (!parseName()) {
       
  6260                     parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
       
  6261                     return false;
       
  6262                 }
       
  6263                 break;
       
  6264             case Ws2:
       
  6265                 if (!eat_ws()) {
       
  6266                     parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
       
  6267                     return false;
       
  6268                 }
       
  6269                 break;
       
  6270             case Empty:
       
  6271                 parseString_s = QLatin1String("EMPTY");
       
  6272                 if (!parseString()) {
       
  6273                     parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
       
  6274                     return false;
       
  6275                 }
       
  6276                 break;
       
  6277             case Any:
       
  6278                 parseString_s = QLatin1String("ANY");
       
  6279                 if (!parseString()) {
       
  6280                     parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
       
  6281                     return false;
       
  6282                 }
       
  6283                 break;
       
  6284             case Cont:
       
  6285                 if (!next_eat_ws()) {
       
  6286                     parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
       
  6287                     return false;
       
  6288                 }
       
  6289                 break;
       
  6290             case Mix:
       
  6291                 parseString_s = QLatin1String("#PCDATA");
       
  6292                 if (!parseString()) {
       
  6293                     parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
       
  6294                     return false;
       
  6295                 }
       
  6296                 break;
       
  6297             case Mix2:
       
  6298                 if (!eat_ws()) {
       
  6299                     parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
       
  6300                     return false;
       
  6301                 }
       
  6302                 break;
       
  6303             case Mix3:
       
  6304                 next();
       
  6305                 break;
       
  6306             case MixN1:
       
  6307                 if (!next_eat_ws()) {
       
  6308                     parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
       
  6309                     return false;
       
  6310                 }
       
  6311                 break;
       
  6312             case MixN2:
       
  6313                 parseName_useRef = false;
       
  6314                 if (!parseName()) {
       
  6315                     parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
       
  6316                     return false;
       
  6317                 }
       
  6318                 break;
       
  6319             case MixN3:
       
  6320                 if (!eat_ws()) {
       
  6321                     parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
       
  6322                     return false;
       
  6323                 }
       
  6324                 break;
       
  6325             case MixN4:
       
  6326                 next();
       
  6327                 break;
       
  6328             case Cp:
       
  6329                 if (!parseChoiceSeq()) {
       
  6330                     parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
       
  6331                     return false;
       
  6332                 }
       
  6333                 break;
       
  6334             case Cp2:
       
  6335                 next();
       
  6336                 break;
       
  6337             case WsD:
       
  6338                 if (!next_eat_ws()) {
       
  6339                     parseFailed(&QXmlSimpleReaderPrivate::parseElementDecl, state);
       
  6340                     return false;
       
  6341                 }
       
  6342                 break;
       
  6343             case Done:
       
  6344                 next();
       
  6345                 break;
       
  6346         }
       
  6347     }
       
  6348     return false;
       
  6349 }
       
  6350 
       
  6351 /*
       
  6352   Parse a NotationDecl [82].
       
  6353 
       
  6354   Precondition: the beginning '<!' is already read and the head
       
  6355   stands on the 'N' of '<!NOTATION'
       
  6356 */
       
  6357 bool QXmlSimpleReaderPrivate::parseNotationDecl()
       
  6358 {
       
  6359     const signed char Init             = 0;
       
  6360     const signed char Not              = 1; // read NOTATION
       
  6361     const signed char Ws1              = 2; // eat whitespaces
       
  6362     const signed char Nam              = 3; // read Name
       
  6363     const signed char Ws2              = 4; // eat whitespaces
       
  6364     const signed char ExtID            = 5; // parse ExternalID
       
  6365     const signed char ExtIDR           = 6; // same as ExtID, but already reported
       
  6366     const signed char Ws3              = 7; // eat whitespaces
       
  6367     const signed char Done             = 8;
       
  6368 
       
  6369     const signed char InpWs            = 0;
       
  6370     const signed char InpGt            = 1; // >
       
  6371     const signed char InpN             = 2; // N
       
  6372     const signed char InpUnknown       = 3;
       
  6373 
       
  6374     static const signed char table[8][4] = {
       
  6375      /*  InpWs   InpGt  InpN    InpUnknown */
       
  6376         { -1,     -1,    Not,    -1     }, // Init
       
  6377         { Ws1,    -1,    -1,     -1     }, // Not
       
  6378         { -1,     -1,    Nam,    Nam    }, // Ws1
       
  6379         { Ws2,    Done,  -1,     -1     }, // Nam
       
  6380         { -1,     Done,  ExtID,  ExtID  }, // Ws2
       
  6381         { Ws3,    Done,  -1,     -1     }, // ExtID
       
  6382         { Ws3,    Done,  -1,     -1     }, // ExtIDR
       
  6383         { -1,     Done,  -1,     -1     }  // Ws3
       
  6384     };
       
  6385     signed char state;
       
  6386     signed char input;
       
  6387 
       
  6388     if (parseStack==0 || parseStack->isEmpty()) {
       
  6389         state = Init;
       
  6390     } else {
       
  6391         state = parseStack->pop().state;
       
  6392 #if defined(QT_QXML_DEBUG)
       
  6393         qDebug("QXmlSimpleReader: parseNotationDecl (cont) in state %d", state);
       
  6394 #endif
       
  6395         if (!parseStack->isEmpty()) {
       
  6396             ParseFunction function = parseStack->top().function;
       
  6397             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  6398                 parseStack->pop();
       
  6399 #if defined(QT_QXML_DEBUG)
       
  6400                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  6401 #endif
       
  6402             }
       
  6403             if (!(this->*function)()) {
       
  6404                 parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
       
  6405                 return false;
       
  6406             }
       
  6407         }
       
  6408     }
       
  6409 
       
  6410     for (;;) {
       
  6411         switch (state) {
       
  6412             case ExtID:
       
  6413                 // call the handler
       
  6414                 if (dtdHnd) {
       
  6415                     if (!dtdHnd->notationDecl(name(), publicId, systemId)) {
       
  6416                         reportParseError(dtdHnd->errorString());
       
  6417                         return false;
       
  6418                     }
       
  6419                 }
       
  6420                 state = ExtIDR;
       
  6421                 break;
       
  6422             case Done:
       
  6423                 return true;
       
  6424             case -1:
       
  6425                 // Error
       
  6426                 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
       
  6427                 return false;
       
  6428         }
       
  6429 
       
  6430         if (atEnd()) {
       
  6431             unexpectedEof(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
       
  6432             return false;
       
  6433         }
       
  6434         if (is_S(c)) {
       
  6435             input = InpWs;
       
  6436         } else if (c == QLatin1Char('>')) {
       
  6437             input = InpGt;
       
  6438         } else if (c == QLatin1Char('N')) {
       
  6439             input = InpN;
       
  6440         } else {
       
  6441             input = InpUnknown;
       
  6442         }
       
  6443         state = table[state][input];
       
  6444 
       
  6445         switch (state) {
       
  6446             case Not:
       
  6447                 parseString_s = QLatin1String("NOTATION");
       
  6448                 if (!parseString()) {
       
  6449                     parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
       
  6450                     return false;
       
  6451                 }
       
  6452                 break;
       
  6453             case Ws1:
       
  6454                 if (!eat_ws()) {
       
  6455                     parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
       
  6456                     return false;
       
  6457                 }
       
  6458                 break;
       
  6459             case Nam:
       
  6460                 parseName_useRef = false;
       
  6461                 if (!parseName()) {
       
  6462                     parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
       
  6463                     return false;
       
  6464                 }
       
  6465                 break;
       
  6466             case Ws2:
       
  6467                 if (!eat_ws()) {
       
  6468                     parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
       
  6469                     return false;
       
  6470                 }
       
  6471                 break;
       
  6472             case ExtID:
       
  6473             case ExtIDR:
       
  6474                 parseExternalID_allowPublicID = true;
       
  6475                 if (!parseExternalID()) {
       
  6476                     parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
       
  6477                     return false;
       
  6478                 }
       
  6479                 break;
       
  6480             case Ws3:
       
  6481                 if (!eat_ws()) {
       
  6482                     parseFailed(&QXmlSimpleReaderPrivate::parseNotationDecl, state);
       
  6483                     return false;
       
  6484                 }
       
  6485                 break;
       
  6486             case Done:
       
  6487                 next();
       
  6488                 break;
       
  6489         }
       
  6490     }
       
  6491     return false;
       
  6492 }
       
  6493 
       
  6494 /*
       
  6495   Parse choice [49] or seq [50].
       
  6496 
       
  6497   Precondition: the beginning '('S? is already read and the head
       
  6498   stands on the first non-whitespace character after it.
       
  6499 */
       
  6500 bool QXmlSimpleReaderPrivate::parseChoiceSeq()
       
  6501 {
       
  6502     const signed char Init             = 0;
       
  6503     const signed char Ws1              = 1; // eat whitespace
       
  6504     const signed char CoS              = 2; // choice or set
       
  6505     const signed char Ws2              = 3; // eat whitespace
       
  6506     const signed char More             = 4; // more cp to read
       
  6507     const signed char Name             = 5; // read name
       
  6508     const signed char Done             = 6; //
       
  6509 
       
  6510     const signed char InpWs            = 0; // S
       
  6511     const signed char InpOp            = 1; // (
       
  6512     const signed char InpCp            = 2; //)
       
  6513     const signed char InpQm            = 3; // ?
       
  6514     const signed char InpAst           = 4; // *
       
  6515     const signed char InpPlus          = 5; // +
       
  6516     const signed char InpPipe          = 6; // |
       
  6517     const signed char InpComm          = 7; // ,
       
  6518     const signed char InpUnknown       = 8;
       
  6519 
       
  6520     static const signed char table[6][9] = {
       
  6521      /*  InpWs   InpOp  InpCp  InpQm  InpAst  InpPlus  InpPipe  InpComm  InpUnknown */
       
  6522         { -1,     Ws1,   -1,    -1,    -1,     -1,      -1,      -1,      Name  }, // Init
       
  6523         { -1,     CoS,   -1,    -1,    -1,     -1,      -1,      -1,      CoS   }, // Ws1
       
  6524         { Ws2,    -1,    Done,  Ws2,   Ws2,    Ws2,     More,    More,    -1    }, // CS
       
  6525         { -1,     -1,    Done,  -1,    -1,     -1,      More,    More,    -1    }, // Ws2
       
  6526         { -1,     Ws1,   -1,    -1,    -1,     -1,      -1,      -1,      Name  }, // More (same as Init)
       
  6527         { Ws2,    -1,    Done,  Ws2,   Ws2,    Ws2,     More,    More,    -1    }  // Name (same as CS)
       
  6528     };
       
  6529     signed char state;
       
  6530     signed char input;
       
  6531 
       
  6532     if (parseStack==0 || parseStack->isEmpty()) {
       
  6533         state = Init;
       
  6534     } else {
       
  6535         state = parseStack->pop().state;
       
  6536 #if defined(QT_QXML_DEBUG)
       
  6537         qDebug("QXmlSimpleReader: parseChoiceSeq (cont) in state %d", state);
       
  6538 #endif
       
  6539         if (!parseStack->isEmpty()) {
       
  6540             ParseFunction function = parseStack->top().function;
       
  6541             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  6542                 parseStack->pop();
       
  6543 #if defined(QT_QXML_DEBUG)
       
  6544                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  6545 #endif
       
  6546             }
       
  6547             if (!(this->*function)()) {
       
  6548                 parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
       
  6549                 return false;
       
  6550             }
       
  6551         }
       
  6552     }
       
  6553 
       
  6554     for (;;) {
       
  6555         switch (state) {
       
  6556             case Done:
       
  6557                 return true;
       
  6558             case -1:
       
  6559                 // Error
       
  6560                 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
       
  6561                 return false;
       
  6562         }
       
  6563 
       
  6564         if (atEnd()) {
       
  6565             unexpectedEof(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
       
  6566             return false;
       
  6567         }
       
  6568         if (is_S(c)) {
       
  6569             input = InpWs;
       
  6570         } else if (c == QLatin1Char('(')) {
       
  6571             input = InpOp;
       
  6572         } else if (c == QLatin1Char(')')) {
       
  6573             input = InpCp;
       
  6574         } else if (c == QLatin1Char('?')) {
       
  6575             input = InpQm;
       
  6576         } else if (c == QLatin1Char('*')) {
       
  6577             input = InpAst;
       
  6578         } else if (c == QLatin1Char('+')) {
       
  6579             input = InpPlus;
       
  6580         } else if (c == QLatin1Char('|')) {
       
  6581             input = InpPipe;
       
  6582         } else if (c == QLatin1Char(',')) {
       
  6583             input = InpComm;
       
  6584         } else {
       
  6585             input = InpUnknown;
       
  6586         }
       
  6587         state = table[state][input];
       
  6588 
       
  6589         switch (state) {
       
  6590             case Ws1:
       
  6591                 if (!next_eat_ws()) {
       
  6592                     parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
       
  6593                     return false;
       
  6594                 }
       
  6595                 break;
       
  6596             case CoS:
       
  6597                 if (!parseChoiceSeq()) {
       
  6598                     parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
       
  6599                     return false;
       
  6600                 }
       
  6601                 break;
       
  6602             case Ws2:
       
  6603                 if (!next_eat_ws()) {
       
  6604                     parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
       
  6605                     return false;
       
  6606                 }
       
  6607                 break;
       
  6608             case More:
       
  6609                 if (!next_eat_ws()) {
       
  6610                     parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
       
  6611                     return false;
       
  6612                 }
       
  6613                 break;
       
  6614             case Name:
       
  6615                 parseName_useRef = false;
       
  6616                 if (!parseName()) {
       
  6617                     parseFailed(&QXmlSimpleReaderPrivate::parseChoiceSeq, state);
       
  6618                     return false;
       
  6619                 }
       
  6620                 break;
       
  6621             case Done:
       
  6622                 next();
       
  6623                 break;
       
  6624         }
       
  6625     }
       
  6626     return false;
       
  6627 }
       
  6628 
       
  6629 /*
       
  6630   Parse a EntityDecl [70].
       
  6631 
       
  6632   Precondition: the beginning '<!E' is already read and the head
       
  6633   stand on the 'N' of '<!ENTITY'
       
  6634 */
       
  6635 bool QXmlSimpleReaderPrivate::parseEntityDecl()
       
  6636 {
       
  6637     const signed char Init             =  0;
       
  6638     const signed char Ent              =  1; // parse "ENTITY"
       
  6639     const signed char Ws1              =  2; // white space read
       
  6640     const signed char Name             =  3; // parse name
       
  6641     const signed char Ws2              =  4; // white space read
       
  6642     const signed char EValue           =  5; // parse entity value
       
  6643     const signed char EValueR          =  6; // same as EValue, but already reported
       
  6644     const signed char ExtID            =  7; // parse ExternalID
       
  6645     const signed char Ws3              =  8; // white space read
       
  6646     const signed char Ndata            =  9; // parse "NDATA"
       
  6647     const signed char Ws4              = 10; // white space read
       
  6648     const signed char NNam             = 11; // parse name
       
  6649     const signed char NNamR            = 12; // same as NNam, but already reported
       
  6650     const signed char PEDec            = 13; // parse PEDecl
       
  6651     const signed char Ws6              = 14; // white space read
       
  6652     const signed char PENam            = 15; // parse name
       
  6653     const signed char Ws7              = 16; // white space read
       
  6654     const signed char PEVal            = 17; // parse entity value
       
  6655     const signed char PEValR           = 18; // same as PEVal, but already reported
       
  6656     const signed char PEEID            = 19; // parse ExternalID
       
  6657     const signed char PEEIDR           = 20; // same as PEEID, but already reported
       
  6658     const signed char WsE              = 21; // white space read
       
  6659     const signed char Done             = 22;
       
  6660     const signed char EDDone           = 23; // done, but also report an external, unparsed entity decl
       
  6661 
       
  6662     const signed char InpWs            = 0; // white space
       
  6663     const signed char InpPer           = 1; // %
       
  6664     const signed char InpQuot          = 2; // " or '
       
  6665     const signed char InpGt            = 3; // >
       
  6666     const signed char InpN             = 4; // N
       
  6667     const signed char InpUnknown       = 5;
       
  6668 
       
  6669     static const signed char table[22][6] = {
       
  6670      /*  InpWs  InpPer  InpQuot  InpGt  InpN    InpUnknown */
       
  6671         { -1,    -1,     -1,      -1,    Ent,    -1      }, // Init
       
  6672         { Ws1,   -1,     -1,      -1,    -1,     -1      }, // Ent
       
  6673         { -1,    PEDec,  -1,      -1,    Name,   Name    }, // Ws1
       
  6674         { Ws2,   -1,     -1,      -1,    -1,     -1      }, // Name
       
  6675         { -1,    -1,     EValue,  -1,    -1,     ExtID   }, // Ws2
       
  6676         { WsE,   -1,     -1,      Done,  -1,     -1      }, // EValue
       
  6677         { WsE,   -1,     -1,      Done,  -1,     -1      }, // EValueR
       
  6678         { Ws3,   -1,     -1,      EDDone,-1,     -1      }, // ExtID
       
  6679         { -1,    -1,     -1,      EDDone,Ndata,  -1      }, // Ws3
       
  6680         { Ws4,   -1,     -1,      -1,    -1,     -1      }, // Ndata
       
  6681         { -1,    -1,     -1,      -1,    NNam,   NNam    }, // Ws4
       
  6682         { WsE,   -1,     -1,      Done,  -1,     -1      }, // NNam
       
  6683         { WsE,   -1,     -1,      Done,  -1,     -1      }, // NNamR
       
  6684         { Ws6,   -1,     -1,      -1,    -1,     -1      }, // PEDec
       
  6685         { -1,    -1,     -1,      -1,    PENam,  PENam   }, // Ws6
       
  6686         { Ws7,   -1,     -1,      -1,    -1,     -1      }, // PENam
       
  6687         { -1,    -1,     PEVal,   -1,    -1,     PEEID   }, // Ws7
       
  6688         { WsE,   -1,     -1,      Done,  -1,     -1      }, // PEVal
       
  6689         { WsE,   -1,     -1,      Done,  -1,     -1      }, // PEValR
       
  6690         { WsE,   -1,     -1,      Done,  -1,     -1      }, // PEEID
       
  6691         { WsE,   -1,     -1,      Done,  -1,     -1      }, // PEEIDR
       
  6692         { -1,    -1,     -1,      Done,  -1,     -1      }  // WsE
       
  6693     };
       
  6694     signed char state;
       
  6695     signed char input;
       
  6696 
       
  6697     if (parseStack==0 || parseStack->isEmpty()) {
       
  6698         state = Init;
       
  6699     } else {
       
  6700         state = parseStack->pop().state;
       
  6701 #if defined(QT_QXML_DEBUG)
       
  6702         qDebug("QXmlSimpleReader: parseEntityDecl (cont) in state %d", state);
       
  6703 #endif
       
  6704         if (!parseStack->isEmpty()) {
       
  6705             ParseFunction function = parseStack->top().function;
       
  6706             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  6707                 parseStack->pop();
       
  6708 #if defined(QT_QXML_DEBUG)
       
  6709                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  6710 #endif
       
  6711             }
       
  6712             if (!(this->*function)()) {
       
  6713                 parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
       
  6714                 return false;
       
  6715             }
       
  6716         }
       
  6717     }
       
  6718 
       
  6719     for (;;) {
       
  6720         switch (state) {
       
  6721             case EValue:
       
  6722                 if ( !entityExist(name())) {
       
  6723                     entities.insert(name(), string());
       
  6724                     if (declHnd) {
       
  6725                         if (!declHnd->internalEntityDecl(name(), string())) {
       
  6726                             reportParseError(declHnd->errorString());
       
  6727                             return false;
       
  6728                         }
       
  6729                     }
       
  6730                 }
       
  6731                 state = EValueR;
       
  6732                 break;
       
  6733             case NNam:
       
  6734                 if ( !entityExist(name())) {
       
  6735                     externEntities.insert(name(), QXmlSimpleReaderPrivate::ExternEntity(publicId, systemId, ref()));
       
  6736                     if (dtdHnd) {
       
  6737                         if (!dtdHnd->unparsedEntityDecl(name(), publicId, systemId, ref())) {
       
  6738                             reportParseError(declHnd->errorString());
       
  6739                             return false;
       
  6740                         }
       
  6741                     }
       
  6742                 }
       
  6743                 state = NNamR;
       
  6744                 break;
       
  6745             case PEVal:
       
  6746                 if ( !entityExist(name())) {
       
  6747                     parameterEntities.insert(name(), string());
       
  6748                     if (declHnd) {
       
  6749                         if (!declHnd->internalEntityDecl(QLatin1Char('%') + name(), string())) {
       
  6750                             reportParseError(declHnd->errorString());
       
  6751                             return false;
       
  6752                         }
       
  6753                     }
       
  6754                 }
       
  6755                 state = PEValR;
       
  6756                 break;
       
  6757             case PEEID:
       
  6758                 if ( !entityExist(name())) {
       
  6759                     externParameterEntities.insert(name(), QXmlSimpleReaderPrivate::ExternParameterEntity(publicId, systemId));
       
  6760                     if (declHnd) {
       
  6761                         if (!declHnd->externalEntityDecl(QLatin1Char('%') + name(), publicId, systemId)) {
       
  6762                             reportParseError(declHnd->errorString());
       
  6763                             return false;
       
  6764                         }
       
  6765                     }
       
  6766                 }
       
  6767                 state = PEEIDR;
       
  6768                 break;
       
  6769             case EDDone:
       
  6770                 if ( !entityExist(name())) {
       
  6771                     externEntities.insert(name(), QXmlSimpleReaderPrivate::ExternEntity(publicId, systemId, QString()));
       
  6772                     if (declHnd) {
       
  6773                         if (!declHnd->externalEntityDecl(name(), publicId, systemId)) {
       
  6774                             reportParseError(declHnd->errorString());
       
  6775                             return false;
       
  6776                         }
       
  6777                     }
       
  6778                 }
       
  6779                 return true;
       
  6780             case Done:
       
  6781                 return true;
       
  6782             case -1:
       
  6783                 // Error
       
  6784                 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
       
  6785                 return false;
       
  6786         }
       
  6787 
       
  6788         if (atEnd()) {
       
  6789             unexpectedEof(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
       
  6790             return false;
       
  6791         }
       
  6792         if (is_S(c)) {
       
  6793             input = InpWs;
       
  6794         } else if (c == QLatin1Char('%')) {
       
  6795             input = InpPer;
       
  6796         } else if (c == QLatin1Char('"') || c == QLatin1Char('\'')) {
       
  6797             input = InpQuot;
       
  6798         } else if (c == QLatin1Char('>')) {
       
  6799             input = InpGt;
       
  6800         } else if (c == QLatin1Char('N')) {
       
  6801             input = InpN;
       
  6802         } else {
       
  6803             input = InpUnknown;
       
  6804         }
       
  6805         state = table[state][input];
       
  6806 
       
  6807         switch (state) {
       
  6808             case Ent:
       
  6809                 parseString_s = QLatin1String("NTITY");
       
  6810                 if (!parseString()) {
       
  6811                     parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
       
  6812                     return false;
       
  6813                 }
       
  6814                 break;
       
  6815             case Ws1:
       
  6816                 if (!eat_ws()) {
       
  6817                     parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
       
  6818                     return false;
       
  6819                 }
       
  6820                 break;
       
  6821             case Name:
       
  6822                 parseName_useRef = false;
       
  6823                 if (!parseName()) {
       
  6824                     parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
       
  6825                     return false;
       
  6826                 }
       
  6827                 break;
       
  6828             case Ws2:
       
  6829                 if (!eat_ws()) {
       
  6830                     parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
       
  6831                     return false;
       
  6832                 }
       
  6833                 break;
       
  6834             case EValue:
       
  6835             case EValueR:
       
  6836                 if (!parseEntityValue()) {
       
  6837                     parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
       
  6838                     return false;
       
  6839                 }
       
  6840                 break;
       
  6841             case ExtID:
       
  6842                 parseExternalID_allowPublicID = false;
       
  6843                 if (!parseExternalID()) {
       
  6844                     parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
       
  6845                     return false;
       
  6846                 }
       
  6847                 break;
       
  6848             case Ws3:
       
  6849                 if (!eat_ws()) {
       
  6850                     parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
       
  6851                     return false;
       
  6852                 }
       
  6853                 break;
       
  6854             case Ndata:
       
  6855                 parseString_s = QLatin1String("NDATA");
       
  6856                 if (!parseString()) {
       
  6857                     parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
       
  6858                     return false;
       
  6859                 }
       
  6860                 break;
       
  6861             case Ws4:
       
  6862                 if (!eat_ws()) {
       
  6863                     parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
       
  6864                     return false;
       
  6865                 }
       
  6866                 break;
       
  6867             case NNam:
       
  6868             case NNamR:
       
  6869                 parseName_useRef = true;
       
  6870                 if (!parseName()) {
       
  6871                     parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
       
  6872                     return false;
       
  6873                 }
       
  6874                 break;
       
  6875             case PEDec:
       
  6876                 next();
       
  6877                 break;
       
  6878             case Ws6:
       
  6879                 if (!eat_ws()) {
       
  6880                     parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
       
  6881                     return false;
       
  6882                 }
       
  6883                 break;
       
  6884             case PENam:
       
  6885                 parseName_useRef = false;
       
  6886                 if (!parseName()) {
       
  6887                     parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
       
  6888                     return false;
       
  6889                 }
       
  6890                 break;
       
  6891             case Ws7:
       
  6892                 if (!eat_ws()) {
       
  6893                     parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
       
  6894                     return false;
       
  6895                 }
       
  6896                 break;
       
  6897             case PEVal:
       
  6898             case PEValR:
       
  6899                 if (!parseEntityValue()) {
       
  6900                     parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
       
  6901                     return false;
       
  6902                 }
       
  6903                 break;
       
  6904             case PEEID:
       
  6905             case PEEIDR:
       
  6906                 parseExternalID_allowPublicID = false;
       
  6907                 if (!parseExternalID()) {
       
  6908                     parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
       
  6909                     return false;
       
  6910                 }
       
  6911                 break;
       
  6912             case WsE:
       
  6913                 if (!eat_ws()) {
       
  6914                     parseFailed(&QXmlSimpleReaderPrivate::parseEntityDecl, state);
       
  6915                     return false;
       
  6916                 }
       
  6917                 break;
       
  6918             case EDDone:
       
  6919                 next();
       
  6920                 break;
       
  6921             case Done:
       
  6922                 next();
       
  6923                 break;
       
  6924         }
       
  6925     }
       
  6926     return false;
       
  6927 }
       
  6928 
       
  6929 /*
       
  6930   Parse a EntityValue [9]
       
  6931 */
       
  6932 bool QXmlSimpleReaderPrivate::parseEntityValue()
       
  6933 {
       
  6934     const signed char Init             = 0;
       
  6935     const signed char Dq               = 1; // EntityValue is double quoted
       
  6936     const signed char DqC              = 2; // signed character
       
  6937     const signed char DqPER            = 3; // PERefence
       
  6938     const signed char DqRef            = 4; // Reference
       
  6939     const signed char Sq               = 5; // EntityValue is double quoted
       
  6940     const signed char SqC              = 6; // signed character
       
  6941     const signed char SqPER            = 7; // PERefence
       
  6942     const signed char SqRef            = 8; // Reference
       
  6943     const signed char Done             = 9;
       
  6944 
       
  6945     const signed char InpDq            = 0; // "
       
  6946     const signed char InpSq            = 1; // '
       
  6947     const signed char InpAmp           = 2; // &
       
  6948     const signed char InpPer           = 3; // %
       
  6949     const signed char InpUnknown       = 4;
       
  6950 
       
  6951     static const signed char table[9][5] = {
       
  6952      /*  InpDq  InpSq  InpAmp  InpPer  InpUnknown */
       
  6953         { Dq,    Sq,    -1,     -1,     -1    }, // Init
       
  6954         { Done,  DqC,   DqRef,  DqPER,  DqC   }, // Dq
       
  6955         { Done,  DqC,   DqRef,  DqPER,  DqC   }, // DqC
       
  6956         { Done,  DqC,   DqRef,  DqPER,  DqC   }, // DqPER
       
  6957         { Done,  DqC,   DqRef,  DqPER,  DqC   }, // DqRef
       
  6958         { SqC,   Done,  SqRef,  SqPER,  SqC   }, // Sq
       
  6959         { SqC,   Done,  SqRef,  SqPER,  SqC   }, // SqC
       
  6960         { SqC,   Done,  SqRef,  SqPER,  SqC   }, // SqPER
       
  6961         { SqC,   Done,  SqRef,  SqPER,  SqC   }  // SqRef
       
  6962     };
       
  6963     signed char state;
       
  6964     signed char input;
       
  6965 
       
  6966     if (parseStack==0 || parseStack->isEmpty()) {
       
  6967         state = Init;
       
  6968     } else {
       
  6969         state = parseStack->pop().state;
       
  6970 #if defined(QT_QXML_DEBUG)
       
  6971         qDebug("QXmlSimpleReader: parseEntityValue (cont) in state %d", state);
       
  6972 #endif
       
  6973         if (!parseStack->isEmpty()) {
       
  6974             ParseFunction function = parseStack->top().function;
       
  6975             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  6976                 parseStack->pop();
       
  6977 #if defined(QT_QXML_DEBUG)
       
  6978                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  6979 #endif
       
  6980             }
       
  6981             if (!(this->*function)()) {
       
  6982                 parseFailed(&QXmlSimpleReaderPrivate::parseEntityValue, state);
       
  6983                 return false;
       
  6984             }
       
  6985         }
       
  6986     }
       
  6987 
       
  6988     for (;;) {
       
  6989         switch (state) {
       
  6990             case Done:
       
  6991                 return true;
       
  6992             case -1:
       
  6993                 // Error
       
  6994                 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
       
  6995                 return false;
       
  6996         }
       
  6997 
       
  6998         if (atEnd()) {
       
  6999             unexpectedEof(&QXmlSimpleReaderPrivate::parseEntityValue, state);
       
  7000             return false;
       
  7001         }
       
  7002         if        (c == QLatin1Char('"')) {
       
  7003             input = InpDq;
       
  7004         } else if (c == QLatin1Char('\'')) {
       
  7005             input = InpSq;
       
  7006         } else if (c == QLatin1Char('&')) {
       
  7007             input = InpAmp;
       
  7008         } else if (c == QLatin1Char('%')) {
       
  7009             input = InpPer;
       
  7010         } else {
       
  7011             input = InpUnknown;
       
  7012         }
       
  7013         state = table[state][input];
       
  7014 
       
  7015         switch (state) {
       
  7016             case Dq:
       
  7017             case Sq:
       
  7018                 stringClear();
       
  7019                 next();
       
  7020                 break;
       
  7021             case DqC:
       
  7022             case SqC:
       
  7023                 stringAddC();
       
  7024                 next();
       
  7025                 break;
       
  7026             case DqPER:
       
  7027             case SqPER:
       
  7028                 parsePEReference_context = InEntityValue;
       
  7029                 if (!parsePEReference()) {
       
  7030                     parseFailed(&QXmlSimpleReaderPrivate::parseEntityValue, state);
       
  7031                     return false;
       
  7032                 }
       
  7033                 break;
       
  7034             case DqRef:
       
  7035             case SqRef:
       
  7036                 parseReference_context = InEntityValue;
       
  7037                 if (!parseReference()) {
       
  7038                     parseFailed(&QXmlSimpleReaderPrivate::parseEntityValue, state);
       
  7039                     return false;
       
  7040                 }
       
  7041                 break;
       
  7042             case Done:
       
  7043                 next();
       
  7044                 break;
       
  7045         }
       
  7046     }
       
  7047     return false;
       
  7048 }
       
  7049 
       
  7050 /*
       
  7051   Parse a comment [15].
       
  7052 
       
  7053   Precondition: the beginning '<!' of the comment is already read and the head
       
  7054   stands on the first '-' of '<!--'.
       
  7055 
       
  7056   If this funktion was successful, the head-position is on the first
       
  7057   character after the comment.
       
  7058 */
       
  7059 bool QXmlSimpleReaderPrivate::parseComment()
       
  7060 {
       
  7061     const signed char Init             = 0;
       
  7062     const signed char Dash1            = 1; // the first dash was read
       
  7063     const signed char Dash2            = 2; // the second dash was read
       
  7064     const signed char Com              = 3; // read comment
       
  7065     const signed char Com2             = 4; // read comment (help state)
       
  7066     const signed char ComE             = 5; // finished reading comment
       
  7067     const signed char Done             = 6;
       
  7068 
       
  7069     const signed char InpDash          = 0; // -
       
  7070     const signed char InpGt            = 1; // >
       
  7071     const signed char InpUnknown       = 2;
       
  7072 
       
  7073     static const signed char table[6][3] = {
       
  7074      /*  InpDash  InpGt  InpUnknown */
       
  7075         { Dash1,   -1,    -1  }, // Init
       
  7076         { Dash2,   -1,    -1  }, // Dash1
       
  7077         { Com2,    Com,   Com }, // Dash2
       
  7078         { Com2,    Com,   Com }, // Com
       
  7079         { ComE,    Com,   Com }, // Com2
       
  7080         { -1,      Done,  -1  }  // ComE
       
  7081     };
       
  7082     signed char state;
       
  7083     signed char input;
       
  7084 
       
  7085     if (parseStack==0 || parseStack->isEmpty()) {
       
  7086         state = Init;
       
  7087     } else {
       
  7088         state = parseStack->pop().state;
       
  7089 #if defined(QT_QXML_DEBUG)
       
  7090         qDebug("QXmlSimpleReader: parseComment (cont) in state %d", state);
       
  7091 #endif
       
  7092         if (!parseStack->isEmpty()) {
       
  7093             ParseFunction function = parseStack->top().function;
       
  7094             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  7095                 parseStack->pop();
       
  7096 #if defined(QT_QXML_DEBUG)
       
  7097                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  7098 #endif
       
  7099             }
       
  7100             if (!(this->*function)()) {
       
  7101                 parseFailed(&QXmlSimpleReaderPrivate::parseComment, state);
       
  7102                 return false;
       
  7103             }
       
  7104         }
       
  7105     }
       
  7106 
       
  7107     for (;;) {
       
  7108         switch (state) {
       
  7109             case Dash2:
       
  7110                 stringClear();
       
  7111                 break;
       
  7112             case Com2:
       
  7113                 // if next character is not a dash than don't skip it
       
  7114                 if (!atEnd() && c != QLatin1Char('-'))
       
  7115                     stringAddC(QLatin1Char('-'));
       
  7116                 break;
       
  7117             case Done:
       
  7118                 return true;
       
  7119             case -1:
       
  7120                 // Error
       
  7121                 reportParseError(QLatin1String(XMLERR_ERRORPARSINGCOMMENT));
       
  7122                 return false;
       
  7123         }
       
  7124 
       
  7125         if (atEnd()) {
       
  7126             unexpectedEof(&QXmlSimpleReaderPrivate::parseComment, state);
       
  7127             return false;
       
  7128         }
       
  7129         if (c == QLatin1Char('-')) {
       
  7130             input = InpDash;
       
  7131         } else if (c == QLatin1Char('>')) {
       
  7132             input = InpGt;
       
  7133         } else {
       
  7134             input = InpUnknown;
       
  7135         }
       
  7136         state = table[state][input];
       
  7137 
       
  7138         switch (state) {
       
  7139             case Dash1:
       
  7140                 next();
       
  7141                 break;
       
  7142             case Dash2:
       
  7143                 next();
       
  7144                 break;
       
  7145             case Com:
       
  7146                 stringAddC();
       
  7147                 next();
       
  7148                 break;
       
  7149             case Com2:
       
  7150                 next();
       
  7151                 break;
       
  7152             case ComE:
       
  7153                 next();
       
  7154                 break;
       
  7155             case Done:
       
  7156                 next();
       
  7157                 break;
       
  7158         }
       
  7159     }
       
  7160     return false;
       
  7161 }
       
  7162 
       
  7163 /*
       
  7164     Parse an Attribute [41].
       
  7165 
       
  7166     Precondition: the head stands on the first character of the name
       
  7167     of the attribute (i.e. all whitespaces are already parsed).
       
  7168 
       
  7169     The head stand on the next character after the end quotes. The
       
  7170     variable name contains the name of the attribute and the variable
       
  7171     string contains the value of the attribute.
       
  7172 */
       
  7173 bool QXmlSimpleReaderPrivate::parseAttribute()
       
  7174 {
       
  7175     const int Init             = 0;
       
  7176     const int PName            = 1; // parse name
       
  7177     const int Ws               = 2; // eat ws
       
  7178     const int Eq               = 3; // the '=' was read
       
  7179     const int Quotes           = 4; // " or ' were read
       
  7180 
       
  7181     const int InpNameBe        = 0;
       
  7182     const int InpEq            = 1; // =
       
  7183     const int InpDq            = 2; // "
       
  7184     const int InpSq            = 3; // '
       
  7185     const int InpUnknown       = 4;
       
  7186 
       
  7187     static const int table[4][5] = {
       
  7188      /*  InpNameBe  InpEq  InpDq    InpSq    InpUnknown */
       
  7189         { PName,     -1,    -1,      -1,      -1    }, // Init
       
  7190         { -1,        Eq,    -1,      -1,      Ws    }, // PName
       
  7191         { -1,        Eq,    -1,      -1,      -1    }, // Ws
       
  7192         { -1,        -1,    Quotes,  Quotes,  -1    }  // Eq
       
  7193     };
       
  7194     int state;
       
  7195     int input;
       
  7196 
       
  7197     if (parseStack==0 || parseStack->isEmpty()) {
       
  7198         state = Init;
       
  7199     } else {
       
  7200         state = parseStack->pop().state;
       
  7201 #if defined(QT_QXML_DEBUG)
       
  7202         qDebug("QXmlSimpleReader: parseAttribute (cont) in state %d", state);
       
  7203 #endif
       
  7204         if (!parseStack->isEmpty()) {
       
  7205             ParseFunction function = parseStack->top().function;
       
  7206             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  7207                 parseStack->pop();
       
  7208 #if defined(QT_QXML_DEBUG)
       
  7209                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  7210 #endif
       
  7211             }
       
  7212             if (!(this->*function)()) {
       
  7213                 parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state);
       
  7214                 return false;
       
  7215             }
       
  7216         }
       
  7217     }
       
  7218 
       
  7219     for (;;) {
       
  7220         switch (state) {
       
  7221             case Quotes:
       
  7222                 // Done
       
  7223                 return true;
       
  7224             case -1:
       
  7225                 // Error
       
  7226                 reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
       
  7227                 return false;
       
  7228         }
       
  7229 
       
  7230         if (atEnd()) {
       
  7231             unexpectedEof(&QXmlSimpleReaderPrivate::parseAttribute, state);
       
  7232             return false;
       
  7233         }
       
  7234         if (determineNameChar(c) == NameBeginning) {
       
  7235             input = InpNameBe;
       
  7236         } else if (c == QLatin1Char('=')) {
       
  7237             input = InpEq;
       
  7238         } else if (c == QLatin1Char('"')) {
       
  7239             input = InpDq;
       
  7240         } else if (c == QLatin1Char('\'')) {
       
  7241             input = InpSq;
       
  7242         } else {
       
  7243             input = InpUnknown;
       
  7244         }
       
  7245         state = table[state][input];
       
  7246 
       
  7247         switch (state) {
       
  7248             case PName:
       
  7249                 parseName_useRef = false;
       
  7250                 if (!parseName()) {
       
  7251                     parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state);
       
  7252                     return false;
       
  7253                 }
       
  7254                 break;
       
  7255             case Ws:
       
  7256                 if (!eat_ws()) {
       
  7257                     parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state);
       
  7258                     return false;
       
  7259                 }
       
  7260                 break;
       
  7261             case Eq:
       
  7262                 if (!next_eat_ws()) {
       
  7263                     parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state);
       
  7264                     return false;
       
  7265                 }
       
  7266                 break;
       
  7267             case Quotes:
       
  7268                 if (!parseAttValue()) {
       
  7269                     parseFailed(&QXmlSimpleReaderPrivate::parseAttribute, state);
       
  7270                     return false;
       
  7271                 }
       
  7272                 break;
       
  7273         }
       
  7274     }
       
  7275     return false;
       
  7276 }
       
  7277 
       
  7278 /*
       
  7279   Parse a Name [5] and store the name in name or ref (if useRef is true).
       
  7280 */
       
  7281 bool QXmlSimpleReaderPrivate::parseName()
       
  7282 {
       
  7283     const int Init             = 0;
       
  7284     const int Name1            = 1; // parse first character of the name
       
  7285     const int Name             = 2; // parse name
       
  7286     const int Done             = 3;
       
  7287 
       
  7288     static const int table[3][3] = {
       
  7289      /*  InpNameBe  InpNameCh  InpUnknown */
       
  7290         { Name1,     -1,        -1    }, // Init
       
  7291         { Name,      Name,      Done  }, // Name1
       
  7292         { Name,      Name,      Done  }  // Name
       
  7293     };
       
  7294     int state;
       
  7295 
       
  7296     if (parseStack==0 || parseStack->isEmpty()) {
       
  7297         state = Init;
       
  7298     } else {
       
  7299         state = parseStack->pop().state;
       
  7300 #if defined(QT_QXML_DEBUG)
       
  7301         qDebug("QXmlSimpleReader: parseName (cont) in state %d", state);
       
  7302 #endif
       
  7303         if (!parseStack->isEmpty()) {
       
  7304             ParseFunction function = parseStack->top().function;
       
  7305             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  7306                 parseStack->pop();
       
  7307 #if defined(QT_QXML_DEBUG)
       
  7308                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  7309 #endif
       
  7310             }
       
  7311             if (!(this->*function)()) {
       
  7312                 parseFailed(&QXmlSimpleReaderPrivate::parseName, state);
       
  7313                 return false;
       
  7314             }
       
  7315         }
       
  7316     }
       
  7317 
       
  7318     for (;;) {
       
  7319         switch (state) {
       
  7320             case Done:
       
  7321                 return true;
       
  7322             case -1:
       
  7323                 // Error
       
  7324                 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
       
  7325                 return false;
       
  7326         }
       
  7327 
       
  7328         if (atEnd()) {
       
  7329             unexpectedEof(&QXmlSimpleReaderPrivate::parseName, state);
       
  7330             return false;
       
  7331         }
       
  7332 
       
  7333         // we can safely do the (int) cast thanks to the Q_ASSERTs earlier in this function
       
  7334         state = table[state][(int)fastDetermineNameChar(c)];
       
  7335 
       
  7336         switch (state) {
       
  7337             case Name1:
       
  7338                 if (parseName_useRef) {
       
  7339                     refClear();
       
  7340                     refAddC();
       
  7341                 } else {
       
  7342                     nameClear();
       
  7343                     nameAddC();
       
  7344                 }
       
  7345                 next();
       
  7346                 break;
       
  7347             case Name:
       
  7348                 if (parseName_useRef) {
       
  7349                     refAddC();
       
  7350                 } else {
       
  7351                     nameAddC();
       
  7352                 }
       
  7353                 next();
       
  7354                 break;
       
  7355         }
       
  7356     }
       
  7357     return false;
       
  7358 }
       
  7359 
       
  7360 /*
       
  7361   Parse a Nmtoken [7] and store the name in name.
       
  7362 */
       
  7363 bool QXmlSimpleReaderPrivate::parseNmtoken()
       
  7364 {
       
  7365     const signed char Init             = 0;
       
  7366     const signed char NameF            = 1;
       
  7367     const signed char Name             = 2;
       
  7368     const signed char Done             = 3;
       
  7369 
       
  7370     const signed char InpNameCh        = 0; // NameChar without InpNameBe
       
  7371     const signed char InpUnknown       = 1;
       
  7372 
       
  7373     static const signed char table[3][2] = {
       
  7374      /*  InpNameCh  InpUnknown */
       
  7375         { NameF,     -1    }, // Init
       
  7376         { Name,      Done  }, // NameF
       
  7377         { Name,      Done  }  // Name
       
  7378     };
       
  7379     signed char state;
       
  7380     signed char input;
       
  7381 
       
  7382     if (parseStack==0 || parseStack->isEmpty()) {
       
  7383         state = Init;
       
  7384     } else {
       
  7385         state = parseStack->pop().state;
       
  7386 #if defined(QT_QXML_DEBUG)
       
  7387         qDebug("QXmlSimpleReader: parseNmtoken (cont) in state %d", state);
       
  7388 #endif
       
  7389         if (!parseStack->isEmpty()) {
       
  7390             ParseFunction function = parseStack->top().function;
       
  7391             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  7392                 parseStack->pop();
       
  7393 #if defined(QT_QXML_DEBUG)
       
  7394                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  7395 #endif
       
  7396             }
       
  7397             if (!(this->*function)()) {
       
  7398                 parseFailed(&QXmlSimpleReaderPrivate::parseNmtoken, state);
       
  7399                 return false;
       
  7400             }
       
  7401         }
       
  7402     }
       
  7403 
       
  7404     for (;;) {
       
  7405         switch (state) {
       
  7406             case Done:
       
  7407                 return true;
       
  7408             case -1:
       
  7409                 // Error
       
  7410                 reportParseError(QLatin1String(XMLERR_LETTEREXPECTED));
       
  7411                 return false;
       
  7412         }
       
  7413 
       
  7414         if (atEnd()) {
       
  7415             unexpectedEof(&QXmlSimpleReaderPrivate::parseNmtoken, state);
       
  7416             return false;
       
  7417         }
       
  7418         if (determineNameChar(c) == NotName) {
       
  7419             input = InpUnknown;
       
  7420         } else {
       
  7421             input = InpNameCh;
       
  7422         }
       
  7423         state = table[state][input];
       
  7424 
       
  7425         switch (state) {
       
  7426             case NameF:
       
  7427                 nameClear();
       
  7428                 nameAddC();
       
  7429                 next();
       
  7430                 break;
       
  7431             case Name:
       
  7432                 nameAddC();
       
  7433                 next();
       
  7434                 break;
       
  7435         }
       
  7436     }
       
  7437     return false;
       
  7438 }
       
  7439 
       
  7440 /*
       
  7441   Parse a Reference [67].
       
  7442 
       
  7443   parseReference_charDataRead is set to true if the reference must not be
       
  7444   parsed. The character(s) which the reference mapped to are appended to
       
  7445   string. The head stands on the first character after the reference.
       
  7446 
       
  7447   parseReference_charDataRead is set to false if the reference must be parsed.
       
  7448   The charachter(s) which the reference mapped to are inserted at the reference
       
  7449   position. The head stands on the first character of the replacement).
       
  7450 */
       
  7451 bool QXmlSimpleReaderPrivate::parseReference()
       
  7452 {
       
  7453     // temporary variables (only used in very local context, so they don't
       
  7454     // interfere with incremental parsing)
       
  7455     uint tmp;
       
  7456     bool ok;
       
  7457 
       
  7458     const signed char Init             =  0;
       
  7459     const signed char SRef             =  1; // start of a reference
       
  7460     const signed char ChRef            =  2; // parse CharRef
       
  7461     const signed char ChDec            =  3; // parse CharRef decimal
       
  7462     const signed char ChHexS           =  4; // start CharRef hexadecimal
       
  7463     const signed char ChHex            =  5; // parse CharRef hexadecimal
       
  7464     const signed char Name             =  6; // parse name
       
  7465     const signed char DoneD            =  7; // done CharRef decimal
       
  7466     const signed char DoneH            =  8; // done CharRef hexadecimal
       
  7467     const signed char DoneN            =  9; // done EntityRef
       
  7468 
       
  7469     const signed char InpAmp           = 0; // &
       
  7470     const signed char InpSemi          = 1; // ;
       
  7471     const signed char InpHash          = 2; // #
       
  7472     const signed char InpX             = 3; // x
       
  7473     const signed char InpNum           = 4; // 0-9
       
  7474     const signed char InpHex           = 5; // a-f A-F
       
  7475     const signed char InpUnknown       = 6;
       
  7476 
       
  7477     static const signed char table[8][7] = {
       
  7478      /*  InpAmp  InpSemi  InpHash  InpX     InpNum  InpHex  InpUnknown */
       
  7479         { SRef,   -1,      -1,      -1,      -1,     -1,     -1    }, // Init
       
  7480         { -1,     -1,      ChRef,   Name,    Name,   Name,   Name  }, // SRef
       
  7481         { -1,     -1,      -1,      ChHexS,  ChDec,  -1,     -1    }, // ChRef
       
  7482         { -1,     DoneD,   -1,      -1,      ChDec,  -1,     -1    }, // ChDec
       
  7483         { -1,     -1,      -1,      -1,      ChHex,  ChHex,  -1    }, // ChHexS
       
  7484         { -1,     DoneH,   -1,      -1,      ChHex,  ChHex,  -1    }, // ChHex
       
  7485         { -1,     DoneN,   -1,      -1,      -1,     -1,     -1    }  // Name
       
  7486     };
       
  7487     signed char state;
       
  7488     signed char input;
       
  7489 
       
  7490     if (parseStack==0 || parseStack->isEmpty()) {
       
  7491         parseReference_charDataRead = false;
       
  7492         state = Init;
       
  7493     } else {
       
  7494         state = parseStack->pop().state;
       
  7495 #if defined(QT_QXML_DEBUG)
       
  7496         qDebug("QXmlSimpleReader: parseReference (cont) in state %d", state);
       
  7497 #endif
       
  7498         if (!parseStack->isEmpty()) {
       
  7499             ParseFunction function = parseStack->top().function;
       
  7500             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  7501                 parseStack->pop();
       
  7502 #if defined(QT_QXML_DEBUG)
       
  7503                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  7504 #endif
       
  7505             }
       
  7506             if (!(this->*function)()) {
       
  7507                 parseFailed(&QXmlSimpleReaderPrivate::parseReference, state);
       
  7508                 return false;
       
  7509             }
       
  7510         }
       
  7511     }
       
  7512 
       
  7513     for (;;) {
       
  7514         switch (state) {
       
  7515             case DoneD:
       
  7516                 return true;
       
  7517             case DoneH:
       
  7518                 return true;
       
  7519             case DoneN:
       
  7520                 return true;
       
  7521             case -1:
       
  7522                 // Error
       
  7523                 reportParseError(QLatin1String(XMLERR_ERRORPARSINGREFERENCE));
       
  7524                 return false;
       
  7525         }
       
  7526 
       
  7527         if (atEnd()) {
       
  7528             unexpectedEof(&QXmlSimpleReaderPrivate::parseReference, state);
       
  7529             return false;
       
  7530         }
       
  7531         if        (c.row()) {
       
  7532             input = InpUnknown;
       
  7533         } else if (c.cell() == '&') {
       
  7534             input = InpAmp;
       
  7535         } else if (c.cell() == ';') {
       
  7536             input = InpSemi;
       
  7537         } else if (c.cell() == '#') {
       
  7538             input = InpHash;
       
  7539         } else if (c.cell() == 'x') {
       
  7540             input = InpX;
       
  7541         } else if ('0' <= c.cell() && c.cell() <= '9') {
       
  7542             input = InpNum;
       
  7543         } else if ('a' <= c.cell() && c.cell() <= 'f') {
       
  7544             input = InpHex;
       
  7545         } else if ('A' <= c.cell() && c.cell() <= 'F') {
       
  7546             input = InpHex;
       
  7547         } else {
       
  7548             input = InpUnknown;
       
  7549         }
       
  7550         state = table[state][input];
       
  7551 
       
  7552         switch (state) {
       
  7553             case SRef:
       
  7554                 refClear();
       
  7555                 next();
       
  7556                 break;
       
  7557             case ChRef:
       
  7558                 next();
       
  7559                 break;
       
  7560             case ChDec:
       
  7561                 refAddC();
       
  7562                 next();
       
  7563                 break;
       
  7564             case ChHexS:
       
  7565                 next();
       
  7566                 break;
       
  7567             case ChHex:
       
  7568                 refAddC();
       
  7569                 next();
       
  7570                 break;
       
  7571             case Name:
       
  7572                 // read the name into the ref
       
  7573                 parseName_useRef = true;
       
  7574                 if (!parseName()) {
       
  7575                     parseFailed(&QXmlSimpleReaderPrivate::parseReference, state);
       
  7576                     return false;
       
  7577                 }
       
  7578                 break;
       
  7579             case DoneD:
       
  7580                 tmp = ref().toUInt(&ok, 10);
       
  7581                 if (ok) {
       
  7582                     stringAddC(QChar(tmp));
       
  7583                 } else {
       
  7584                     reportParseError(QLatin1String(XMLERR_ERRORPARSINGREFERENCE));
       
  7585                     return false;
       
  7586                 }
       
  7587                 parseReference_charDataRead = true;
       
  7588                 next();
       
  7589                 break;
       
  7590             case DoneH:
       
  7591                 tmp = ref().toUInt(&ok, 16);
       
  7592                 if (ok) {
       
  7593                     stringAddC(QChar(tmp));
       
  7594                 } else {
       
  7595                     reportParseError(QLatin1String(XMLERR_ERRORPARSINGREFERENCE));
       
  7596                     return false;
       
  7597                 }
       
  7598                 parseReference_charDataRead = true;
       
  7599                 next();
       
  7600                 break;
       
  7601             case DoneN:
       
  7602                 if (!processReference())
       
  7603                     return false;
       
  7604                 next();
       
  7605                 break;
       
  7606         }
       
  7607     }
       
  7608     return false;
       
  7609 }
       
  7610 
       
  7611 /*
       
  7612   Helper function for parseReference()
       
  7613 */
       
  7614 bool QXmlSimpleReaderPrivate::processReference()
       
  7615 {
       
  7616     QString reference = ref();
       
  7617     if (reference == QLatin1String("amp")) {
       
  7618         if (parseReference_context == InEntityValue) {
       
  7619             // Bypassed
       
  7620             stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('a')); stringAddC(QLatin1Char('m')); stringAddC(QLatin1Char('p')); stringAddC(QLatin1Char(';'));
       
  7621         } else {
       
  7622             // Included or Included in literal
       
  7623             stringAddC(QLatin1Char('&'));
       
  7624         }
       
  7625         parseReference_charDataRead = true;
       
  7626     } else if (reference == QLatin1String("lt")) {
       
  7627         if (parseReference_context == InEntityValue) {
       
  7628             // Bypassed
       
  7629             stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('l')); stringAddC(QLatin1Char('t')); stringAddC(QLatin1Char(';'));
       
  7630         } else {
       
  7631             // Included or Included in literal
       
  7632             stringAddC(QLatin1Char('<'));
       
  7633         }
       
  7634         parseReference_charDataRead = true;
       
  7635     } else if (reference == QLatin1String("gt")) {
       
  7636         if (parseReference_context == InEntityValue) {
       
  7637             // Bypassed
       
  7638             stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('g')); stringAddC(QLatin1Char('t')); stringAddC(QLatin1Char(';'));
       
  7639         } else {
       
  7640             // Included or Included in literal
       
  7641             stringAddC(QLatin1Char('>'));
       
  7642         }
       
  7643         parseReference_charDataRead = true;
       
  7644     } else if (reference == QLatin1String("apos")) {
       
  7645         if (parseReference_context == InEntityValue) {
       
  7646             // Bypassed
       
  7647             stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('a')); stringAddC(QLatin1Char('p')); stringAddC(QLatin1Char('o')); stringAddC(QLatin1Char('s')); stringAddC(QLatin1Char(';'));
       
  7648         } else {
       
  7649             // Included or Included in literal
       
  7650             stringAddC(QLatin1Char('\''));
       
  7651         }
       
  7652         parseReference_charDataRead = true;
       
  7653     } else if (reference == QLatin1String("quot")) {
       
  7654         if (parseReference_context == InEntityValue) {
       
  7655             // Bypassed
       
  7656             stringAddC(QLatin1Char('&')); stringAddC(QLatin1Char('q')); stringAddC(QLatin1Char('u')); stringAddC(QLatin1Char('o')); stringAddC(QLatin1Char('t')); stringAddC(QLatin1Char(';'));
       
  7657         } else {
       
  7658             // Included or Included in literal
       
  7659             stringAddC(QLatin1Char('"'));
       
  7660         }
       
  7661         parseReference_charDataRead = true;
       
  7662     } else {
       
  7663         QMap<QString,QString>::Iterator it;
       
  7664         it = entities.find(reference);
       
  7665         if (it != entities.end()) {
       
  7666             // "Internal General"
       
  7667             switch (parseReference_context) {
       
  7668                 case InContent:
       
  7669                     // Included
       
  7670                     if (!insertXmlRef(*it, reference, false))
       
  7671                         return false;
       
  7672                     parseReference_charDataRead = false;
       
  7673                     break;
       
  7674                 case InAttributeValue:
       
  7675                     // Included in literal
       
  7676                     if (!insertXmlRef(*it, reference, true))
       
  7677                         return false;
       
  7678                     parseReference_charDataRead = false;
       
  7679                     break;
       
  7680                 case InEntityValue:
       
  7681                     {
       
  7682                         // Bypassed
       
  7683                         stringAddC(QLatin1Char('&'));
       
  7684                         for (int i=0; i<(int)reference.length(); i++) {
       
  7685                             stringAddC(reference[i]);
       
  7686                         }
       
  7687                         stringAddC(QLatin1Char(';'));
       
  7688                         parseReference_charDataRead = true;
       
  7689                     }
       
  7690                     break;
       
  7691                 case InDTD:
       
  7692                     // Forbidden
       
  7693                     parseReference_charDataRead = false;
       
  7694                     reportParseError(QLatin1String(XMLERR_INTERNALGENERALENTITYINDTD));
       
  7695                     return false;
       
  7696             }
       
  7697         } else {
       
  7698             QMap<QString,QXmlSimpleReaderPrivate::ExternEntity>::Iterator itExtern;
       
  7699             itExtern = externEntities.find(reference);
       
  7700             if (itExtern == externEntities.end()) {
       
  7701                 // entity not declared
       
  7702                 // ### check this case for conformance
       
  7703                 if (parseReference_context == InEntityValue) {
       
  7704                     // Bypassed
       
  7705                     stringAddC(QLatin1Char('&'));
       
  7706                     for (int i=0; i<(int)reference.length(); i++) {
       
  7707                         stringAddC(reference[i]);
       
  7708                     }
       
  7709                     stringAddC(QLatin1Char(';'));
       
  7710                     parseReference_charDataRead = true;
       
  7711                 } else {
       
  7712                     // if we have some char data read, report it now
       
  7713                     if (parseReference_context == InContent) {
       
  7714                         if (contentCharDataRead) {
       
  7715                             if (reportWhitespaceCharData || !string().simplified().isEmpty()) {
       
  7716                                 if (contentHnd != 0 && !contentHnd->characters(string())) {
       
  7717                                     reportParseError(contentHnd->errorString());
       
  7718                                     return false;
       
  7719                                 }
       
  7720                             }
       
  7721                             stringClear();
       
  7722                             contentCharDataRead = false;
       
  7723                         }
       
  7724                     }
       
  7725 
       
  7726                     if (contentHnd) {
       
  7727                         qt_xml_skipped_entity_in_content = parseReference_context == InContent;
       
  7728                         if (!contentHnd->skippedEntity(reference)) {
       
  7729                             qt_xml_skipped_entity_in_content = false;
       
  7730                             reportParseError(contentHnd->errorString());
       
  7731                             return false; // error
       
  7732                         }
       
  7733                         qt_xml_skipped_entity_in_content = false;
       
  7734                     }
       
  7735                 }
       
  7736             } else if ((*itExtern).notation.isNull()) {
       
  7737                 // "External Parsed General"
       
  7738                 switch (parseReference_context) {
       
  7739                     case InContent:
       
  7740                         {
       
  7741                             // Included if validating
       
  7742                             bool skipIt = true;
       
  7743                             if (entityRes) {
       
  7744                                 QXmlInputSource *ret = 0;
       
  7745                                 if (!entityRes->resolveEntity((*itExtern).publicId, (*itExtern).systemId, ret)) {
       
  7746                                     delete ret;
       
  7747                                     reportParseError(entityRes->errorString());
       
  7748                                     return false;
       
  7749                                 }
       
  7750                                 if (ret) {
       
  7751                                     QString xmlRefString = ret->data();
       
  7752                                     delete ret;
       
  7753                                     if (!stripTextDecl(xmlRefString)) {
       
  7754                                         reportParseError(QLatin1String(XMLERR_ERRORINTEXTDECL));
       
  7755                                         return false;
       
  7756                                     }
       
  7757                                     if (!insertXmlRef(xmlRefString, reference, false))
       
  7758                                         return false;
       
  7759                                     skipIt = false;
       
  7760                                 }
       
  7761                             }
       
  7762                             if (skipIt && contentHnd) {
       
  7763                                 qt_xml_skipped_entity_in_content = true;
       
  7764                                 if (!contentHnd->skippedEntity(reference)) {
       
  7765                                     qt_xml_skipped_entity_in_content = false;
       
  7766                                     reportParseError(contentHnd->errorString());
       
  7767                                     return false; // error
       
  7768                                 }
       
  7769                                 qt_xml_skipped_entity_in_content = false;
       
  7770                             }
       
  7771                             parseReference_charDataRead = false;
       
  7772                         } break;
       
  7773                     case InAttributeValue:
       
  7774                         // Forbidden
       
  7775                         parseReference_charDataRead = false;
       
  7776                         reportParseError(QLatin1String(XMLERR_EXTERNALGENERALENTITYINAV));
       
  7777                         return false;
       
  7778                     case InEntityValue:
       
  7779                         {
       
  7780                             // Bypassed
       
  7781                             stringAddC(QLatin1Char('&'));
       
  7782                             for (int i=0; i<(int)reference.length(); i++) {
       
  7783                                 stringAddC(reference[i]);
       
  7784                             }
       
  7785                             stringAddC(QLatin1Char(';'));
       
  7786                             parseReference_charDataRead = true;
       
  7787                         }
       
  7788                         break;
       
  7789                     case InDTD:
       
  7790                         // Forbidden
       
  7791                         parseReference_charDataRead = false;
       
  7792                         reportParseError(QLatin1String(XMLERR_EXTERNALGENERALENTITYINDTD));
       
  7793                         return false;
       
  7794                 }
       
  7795             } else {
       
  7796                 // "Unparsed"
       
  7797                 // ### notify for "Occurs as Attribute Value" missing (but this is no refence, anyway)
       
  7798                 // Forbidden
       
  7799                 parseReference_charDataRead = false;
       
  7800                 reportParseError(QLatin1String(XMLERR_UNPARSEDENTITYREFERENCE));
       
  7801                 return false; // error
       
  7802             }
       
  7803         }
       
  7804     }
       
  7805     return true; // no error
       
  7806 }
       
  7807 
       
  7808 
       
  7809 /*
       
  7810   Parses over a simple string.
       
  7811 
       
  7812   After the string was successfully parsed, the head is on the first
       
  7813   character after the string.
       
  7814 */
       
  7815 bool QXmlSimpleReaderPrivate::parseString()
       
  7816 {
       
  7817     const signed char InpCharExpected  = 0; // the character that was expected
       
  7818     const signed char InpUnknown       = 1;
       
  7819 
       
  7820     signed char state; // state in this function is the position in the string s
       
  7821     signed char input;
       
  7822 
       
  7823     if (parseStack==0 || parseStack->isEmpty()) {
       
  7824         Done = parseString_s.length();
       
  7825         state = 0;
       
  7826     } else {
       
  7827         state = parseStack->pop().state;
       
  7828 #if defined(QT_QXML_DEBUG)
       
  7829         qDebug("QXmlSimpleReader: parseString (cont) in state %d", state);
       
  7830 #endif
       
  7831         if (!parseStack->isEmpty()) {
       
  7832             ParseFunction function = parseStack->top().function;
       
  7833             if (function == &QXmlSimpleReaderPrivate::eat_ws) {
       
  7834                 parseStack->pop();
       
  7835 #if defined(QT_QXML_DEBUG)
       
  7836                 qDebug("QXmlSimpleReader: eat_ws (cont)");
       
  7837 #endif
       
  7838             }
       
  7839             if (!(this->*function)()) {
       
  7840                 parseFailed(&QXmlSimpleReaderPrivate::parseString, state);
       
  7841                 return false;
       
  7842             }
       
  7843         }
       
  7844     }
       
  7845 
       
  7846     for (;;) {
       
  7847         if (state == Done) {
       
  7848             return true;
       
  7849         }
       
  7850 
       
  7851         if (atEnd()) {
       
  7852             unexpectedEof(&QXmlSimpleReaderPrivate::parseString, state);
       
  7853             return false;
       
  7854         }
       
  7855         if (c == parseString_s[(int)state]) {
       
  7856             input = InpCharExpected;
       
  7857         } else {
       
  7858             input = InpUnknown;
       
  7859         }
       
  7860         if (input == InpCharExpected) {
       
  7861             state++;
       
  7862         } else {
       
  7863             // Error
       
  7864             reportParseError(QLatin1String(XMLERR_UNEXPECTEDCHARACTER));
       
  7865             return false;
       
  7866         }
       
  7867 
       
  7868         next();
       
  7869     }
       
  7870     return false;
       
  7871 }
       
  7872 
       
  7873 /*
       
  7874   This private function inserts and reports an entity substitution. The
       
  7875   substituted string is \a data and the name of the entity reference is \a
       
  7876   name. If \a inLiteral is true, the entity is IncludedInLiteral (i.e., " and '
       
  7877   must be quoted. Otherwise they are not quoted.
       
  7878 
       
  7879   This function returns false on error.
       
  7880 */
       
  7881 bool QXmlSimpleReaderPrivate::insertXmlRef(const QString &data, const QString &name, bool inLiteral)
       
  7882 {
       
  7883     if (inLiteral) {
       
  7884         QString tmp = data;
       
  7885         xmlRefStack.push(XmlRef(name, tmp.replace(QLatin1Char('\"'),
       
  7886                             QLatin1String("&quot;")).replace(QLatin1Char('\''), QLatin1String("&apos;"))));
       
  7887     } else {
       
  7888         xmlRefStack.push(XmlRef(name, data));
       
  7889     }
       
  7890     int n = qMax(parameterEntities.count(), entities.count());
       
  7891     if (xmlRefStack.count() > n+1) {
       
  7892         // recursive entities
       
  7893         reportParseError(QLatin1String(XMLERR_RECURSIVEENTITIES));
       
  7894         return false;
       
  7895     }
       
  7896     if (reportEntities && lexicalHnd) {
       
  7897         if (!lexicalHnd->startEntity(name)) {
       
  7898             reportParseError(lexicalHnd->errorString());
       
  7899             return false;
       
  7900         }
       
  7901     }
       
  7902     return true;
       
  7903 }
       
  7904 
       
  7905 /*
       
  7906   This private function moves the cursor to the next character.
       
  7907 */
       
  7908 void QXmlSimpleReaderPrivate::next()
       
  7909 {
       
  7910     int count = xmlRefStack.size();
       
  7911     while (count != 0) {
       
  7912         if (xmlRefStack.top().isEmpty()) {
       
  7913             xmlRefStack.pop_back();
       
  7914             count--;
       
  7915         } else {
       
  7916             c = xmlRefStack.top().next();
       
  7917             return;
       
  7918         }
       
  7919     }
       
  7920 
       
  7921     // the following could be written nicer, but since it is a time-critical
       
  7922     // function, rather optimize for speed
       
  7923     ushort uc = c.unicode();
       
  7924     c = inputSource->next();
       
  7925     // If we are not incremental parsing, we just skip over EndOfData chars to give the
       
  7926     // parser an uninterrupted stream of document chars.
       
  7927     if (c == QXmlInputSource::EndOfData && parseStack == 0)
       
  7928         c = inputSource->next();
       
  7929     if (uc == '\n') {
       
  7930         lineNr++;
       
  7931         columnNr = -1;
       
  7932     } else if (uc == '\r') {
       
  7933         if (c != QLatin1Char('\n')) {
       
  7934             lineNr++;
       
  7935             columnNr = -1;
       
  7936         }
       
  7937     }
       
  7938     ++columnNr;
       
  7939 }
       
  7940 
       
  7941 /*
       
  7942   This private function moves the cursor to the next non-whitespace character.
       
  7943   This function does not move the cursor if the actual cursor position is a
       
  7944   non-whitespace charcter.
       
  7945 
       
  7946   Returns false when you use incremental parsing and this function reaches EOF
       
  7947   with reading only whitespace characters. In this case it also poplulates the
       
  7948   parseStack with useful information. In all other cases, this function returns
       
  7949   true.
       
  7950 */
       
  7951 bool QXmlSimpleReaderPrivate::eat_ws()
       
  7952 {
       
  7953     while (!atEnd()) {
       
  7954         if (!is_S(c)) {
       
  7955             return true;
       
  7956         }
       
  7957         next();
       
  7958     }
       
  7959     if (parseStack != 0) {
       
  7960         unexpectedEof(&QXmlSimpleReaderPrivate::eat_ws, 0);
       
  7961         return false;
       
  7962     }
       
  7963     return true;
       
  7964 }
       
  7965 
       
  7966 bool QXmlSimpleReaderPrivate::next_eat_ws()
       
  7967 {
       
  7968     next();
       
  7969     return eat_ws();
       
  7970 }
       
  7971 
       
  7972 
       
  7973 /*
       
  7974   This private function initializes the reader. \a i is the input source to
       
  7975   read the data from.
       
  7976 */
       
  7977 void QXmlSimpleReaderPrivate::init(const QXmlInputSource *i)
       
  7978 {
       
  7979     lineNr = 0;
       
  7980     columnNr = -1;
       
  7981     inputSource = const_cast<QXmlInputSource *>(i);
       
  7982     initData();
       
  7983 
       
  7984     externParameterEntities.clear();
       
  7985     parameterEntities.clear();
       
  7986     externEntities.clear();
       
  7987     entities.clear();
       
  7988 
       
  7989     tags.clear();
       
  7990 
       
  7991     doctype.clear();
       
  7992     xmlVersion.clear();
       
  7993     encoding.clear();
       
  7994     standalone = QXmlSimpleReaderPrivate::Unknown;
       
  7995     error.clear();
       
  7996 }
       
  7997 
       
  7998 /*
       
  7999   This private function initializes the XML data related variables. Especially,
       
  8000   it reads the data from the input source.
       
  8001 */
       
  8002 void QXmlSimpleReaderPrivate::initData()
       
  8003 {
       
  8004     c = QXmlInputSource::EndOfData;
       
  8005     xmlRefStack.clear();
       
  8006     next();
       
  8007 }
       
  8008 
       
  8009 /*
       
  8010   Returns true if a entity with the name \a e exists,
       
  8011   otherwise returns false.
       
  8012 */
       
  8013 bool QXmlSimpleReaderPrivate::entityExist(const QString& e) const
       
  8014 {
       
  8015     if ( parameterEntities.find(e) == parameterEntities.end() &&
       
  8016           externParameterEntities.find(e) == externParameterEntities.end() &&
       
  8017           externEntities.find(e) == externEntities.end() &&
       
  8018           entities.find(e) == entities.end()) {
       
  8019         return false;
       
  8020     } else {
       
  8021         return true;
       
  8022     }
       
  8023 }
       
  8024 
       
  8025 void QXmlSimpleReaderPrivate::reportParseError(const QString& error)
       
  8026 {
       
  8027     this->error = error;
       
  8028     if (errorHnd) {
       
  8029         if (this->error.isNull()) {
       
  8030             const QXmlParseException ex(QLatin1String(XMLERR_OK), columnNr+1, lineNr+1,
       
  8031                                         thisPublicId, thisSystemId);
       
  8032             errorHnd->fatalError(ex);
       
  8033         } else {
       
  8034             const QXmlParseException ex(this->error, columnNr+1, lineNr+1,
       
  8035                                         thisPublicId, thisSystemId);
       
  8036             errorHnd->fatalError(ex);
       
  8037         }
       
  8038     }
       
  8039 }
       
  8040 
       
  8041 /*
       
  8042   This private function is called when a parsing function encounters an
       
  8043   unexpected EOF. It decides what to do (depending on incremental parsing or
       
  8044   not). \a where is a pointer to the function where the error occurred and \a
       
  8045   state is the parsing state in this function.
       
  8046 */
       
  8047 void QXmlSimpleReaderPrivate::unexpectedEof(ParseFunction where, int state)
       
  8048 {
       
  8049     if (parseStack == 0) {
       
  8050         reportParseError(QLatin1String(XMLERR_UNEXPECTEDEOF));
       
  8051     } else {
       
  8052         if (c == QXmlInputSource::EndOfDocument) {
       
  8053             reportParseError(QLatin1String(XMLERR_UNEXPECTEDEOF));
       
  8054         } else {
       
  8055             pushParseState(where, state);
       
  8056         }
       
  8057     }
       
  8058 }
       
  8059 
       
  8060 /*
       
  8061   This private function is called when a parse...() function returned false. It
       
  8062   determines if there was an error or if incremental parsing simply went out of
       
  8063   data and does the right thing for the case. \a where is a pointer to the
       
  8064   function where the error occurred and \a state is the parsing state in this
       
  8065   function.
       
  8066 */
       
  8067 void QXmlSimpleReaderPrivate::parseFailed(ParseFunction where, int state)
       
  8068 {
       
  8069     if (parseStack!=0 && error.isNull()) {
       
  8070         pushParseState(where, state);
       
  8071     }
       
  8072 }
       
  8073 
       
  8074 /*
       
  8075   This private function pushes the function pointer \a function and state \a
       
  8076   state to the parse stack. This is used when you are doing an incremental
       
  8077   parsing and reach the end of file too early.
       
  8078 
       
  8079   Only call this function when d->parseStack!=0.
       
  8080 */
       
  8081 void QXmlSimpleReaderPrivate::pushParseState(ParseFunction function, int state)
       
  8082 {
       
  8083     QXmlSimpleReaderPrivate::ParseState ps;
       
  8084     ps.function = function;
       
  8085     ps.state = state;
       
  8086     parseStack->push(ps);
       
  8087 }
       
  8088 
       
  8089 inline static void updateValue(QString &value, const QChar *array, int &arrayPos, int &valueLen)
       
  8090 {
       
  8091     value.resize(valueLen + arrayPos);
       
  8092     memcpy(value.data() + valueLen, array, arrayPos * sizeof(QChar));
       
  8093     valueLen += arrayPos;
       
  8094     arrayPos = 0;
       
  8095 }
       
  8096 
       
  8097 // use buffers instead of QString::operator+= when single characters are read
       
  8098 const QString& QXmlSimpleReaderPrivate::string()
       
  8099 {
       
  8100     updateValue(stringValue, stringArray, stringArrayPos, stringValueLen);
       
  8101     return stringValue;
       
  8102 }
       
  8103 const QString& QXmlSimpleReaderPrivate::name()
       
  8104 {
       
  8105     updateValue(nameValue, nameArray, nameArrayPos, nameValueLen);
       
  8106     return nameValue;
       
  8107 }
       
  8108 const QString& QXmlSimpleReaderPrivate::ref()
       
  8109 {
       
  8110     updateValue(refValue, refArray, refArrayPos, refValueLen);
       
  8111     return refValue;
       
  8112 }
       
  8113 
       
  8114 void QXmlSimpleReaderPrivate::stringAddC(QChar ch)
       
  8115 {
       
  8116     if (stringArrayPos == 256)
       
  8117         updateValue(stringValue, stringArray, stringArrayPos, stringValueLen);
       
  8118     stringArray[stringArrayPos++] = ch;
       
  8119 }
       
  8120 void QXmlSimpleReaderPrivate::nameAddC(QChar ch)
       
  8121 {
       
  8122     if (nameArrayPos == 256)
       
  8123         updateValue(nameValue, nameArray, nameArrayPos, nameValueLen);
       
  8124     nameArray[nameArrayPos++] = ch;
       
  8125 }
       
  8126 void QXmlSimpleReaderPrivate::refAddC(QChar ch)
       
  8127 {
       
  8128     if (refArrayPos == 256)
       
  8129         updateValue(refValue, refArray, refArrayPos, refValueLen);
       
  8130     refArray[refArrayPos++] = ch;
       
  8131 }
       
  8132 QT_END_NAMESPACE