2f5384b9022678457f7d84327827d311eaddd4b5
[profile/ivi/qtbase.git] / src / xml / sax / qxml.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2011 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 ** GNU Lesser General Public License Usage
11 ** This file may be used under the terms of the GNU Lesser General Public
12 ** License version 2.1 as published by the Free Software Foundation and
13 ** appearing in the file LICENSE.LGPL included in the packaging of this
14 ** file. Please review the following information to ensure the GNU Lesser
15 ** General Public License version 2.1 requirements will be met:
16 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 **
18 ** In addition, as a special exception, Nokia gives you certain additional
19 ** rights. These rights are described in the Nokia Qt LGPL Exception
20 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 **
22 ** GNU General Public License Usage
23 ** Alternatively, this file may be used under the terms of the GNU General
24 ** Public License version 3.0 as published by the Free Software Foundation
25 ** and appearing in the file LICENSE.GPL included in the packaging of this
26 ** file. Please review the following information to ensure the GNU General
27 ** Public License version 3.0 requirements will be met:
28 ** http://www.gnu.org/copyleft/gpl.html.
29 **
30 ** Other Usage
31 ** Alternatively, this file may be used in accordance with the terms and
32 ** conditions contained in a signed written agreement between you and Nokia.
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     \snippet doc/src/snippets/code/src_xml_sax_qxml.cpp 0
3067
3068     QXmlSimpleReader is not reentrant. If you want to use the class
3069     in threaded code, lock the code using QXmlSimpleReader with a
3070     locking mechanism, such as a QMutex.
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