Chameleon

Chameleon Svn Source Tree

Root/branches/xZenu/src/util/doxygen/qtools/qxml.cpp

Source at commit 1322 created 9 years 5 months ago.
By meklort, Add doxygen to utils folder
1/****************************************************************************
2**
3**
4** Implementation of QXmlSimpleReader and related classes.
5**
6** Created : 000518
7**
8** Copyright (C) 1992-2000 Trolltech AS. All rights reserved.
9**
10** This file is part of the XML module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition licenses may use this
22** file in accordance with the Qt Commercial License Agreement provided
23** with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#define QT_XML_CPP
39#include "qxml.h"
40#include "qtextcodec.h"
41#include "qbuffer.h"
42
43#ifndef QT_NO_XML
44// NOT REVISED
45
46// Error strings for the XML reader
47#define XMLERR_OK "no error occured"
48#define XMLERR_TAGMISMATCH "tag mismatch"
49#define XMLERR_UNEXPECTEDEOF "unexpected end of file"
50#define XMLERR_FINISHEDPARSINGWHILENOTEOF "parsing is finished but end of file is not reached"
51#define XMLERR_LETTEREXPECTED "letter is expected"
52#define XMLERR_ERRORPARSINGELEMENT "error while parsing element"
53#define XMLERR_ERRORPARSINGPROLOG "error while parsing prolog"
54#define XMLERR_ERRORPARSINGMAINELEMENT "error while parsing main element"
55#define XMLERR_ERRORPARSINGCONTENT "error while parsing content"
56#define XMLERR_ERRORPARSINGNAME "error while parsing name"
57#define XMLERR_ERRORPARSINGNMTOKEN "error while parsing Nmtoken"
58#define XMLERR_ERRORPARSINGATTRIBUTE "error while parsing attribute"
59#define XMLERR_ERRORPARSINGMISC "error while parsing misc"
60#define XMLERR_ERRORPARSINGCHOICE "error while parsing choice or seq"
61#define XMLERR_ERRORBYCONSUMER "error triggered by consumer"
62#define XMLERR_UNEXPECTEDCHARACTER "unexpected character"
63#define XMLERR_EQUALSIGNEXPECTED "expected '=' but not found"
64#define XMLERR_QUOTATIONEXPECTED "expected \" or ' but not found"
65#define XMLERR_ERRORPARSINGREFERENCE "error while parsing reference"
66#define XMLERR_ERRORPARSINGPI "error while parsing processing instruction"
67#define XMLERR_ERRORPARSINGATTLISTDECL "error while parsing attribute list declaration"
68#define XMLERR_ERRORPARSINGATTTYPE "error while parsing attribute type declaration"
69#define XMLERR_ERRORPARSINGATTVALUE "error while parsing attribute value declaration"
70#define XMLERR_ERRORPARSINGELEMENTDECL "error while parsing element declaration"
71#define XMLERR_ERRORPARSINGENTITYDECL "error while parsing entity declaration"
72#define XMLERR_ERRORPARSINGNOTATIONDECL "error while parsing notation declaration"
73#define XMLERR_ERRORPARSINGEXTERNALID "error while parsing external id"
74#define XMLERR_ERRORPARSINGCOMMENT "error while parsing comment"
75#define XMLERR_ERRORPARSINGENTITYVALUE "error while parsing entity value declaration"
76#define XMLERR_CDSECTHEADEREXPECTED "expected the header for a cdata section"
77#define XMLERR_MORETHANONEDOCTYPE "more than one document type definition"
78#define XMLERR_ERRORPARSINGDOCTYPE "error while parsing document type definition"
79#define XMLERR_INVALIDNAMEFORPI "invalid name for processing instruction"
80#define XMLERR_VERSIONEXPECTED "version expected while reading the XML declaration"
81#define XMLERR_EDECLORSDDECLEXPECTED "EDecl or SDDecl expected while reading the XML declaration"
82#define XMLERR_SDDECLEXPECTED "SDDecl expected while reading the XML declaration"
83#define XMLERR_WRONGVALUEFORSDECL "wrong value for standalone declaration"
84#define XMLERR_UNPARSEDENTITYREFERENCE "unparsed entity reference in wrong context"
85#define XMLERR_INTERNALGENERALENTITYINDTD "internal general entity reference not allowed in DTD"
86#define XMLERR_EXTERNALGENERALENTITYINDTD "external parsed general entity reference not allowed in DTD"
87#define XMLERR_EXTERNALGENERALENTITYINAV "external parsed general entity reference not allowed in attribute value"
88
89
90// the constants for the lookup table
91static const signed char cltWS = 0; // white space
92static const signed char cltPer = 1; // %
93static const signed char cltAmp = 2; // &
94static const signed char cltGt = 3; // >
95static const signed char cltLt = 4; // <
96static const signed char cltSlash = 5; // /
97static const signed char cltQm = 6; // ?
98static const signed char cltEm = 7; // !
99static const signed char cltDash = 8; // -
100static const signed char cltCB = 9; // ]
101static const signed char cltOB = 10; // [
102static const signed char cltEq = 11; // =
103static const signed char cltDq = 12; // "
104static const signed char cltSq = 13; // '
105static const signed char cltUnknown = 14;
106
107// character lookup table
108static const signed char charLookupTable[256]={
109 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x00 - 0x07
110 cltUnknown, // 0x08
111 cltWS, // 0x09 \t
112 cltWS, // 0x0A \n
113 cltUnknown, // 0x0B
114 cltUnknown, // 0x0C
115 cltWS, // 0x0D \r
116 cltUnknown, // 0x0E
117 cltUnknown, // 0x0F
118 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x17 - 0x16
119 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x18 - 0x1F
120 cltWS, // 0x20 Space
121 cltEm, // 0x21 !
122 cltDq, // 0x22 "
123 cltUnknown, // 0x23
124 cltUnknown, // 0x24
125 cltPer, // 0x25 %
126 cltAmp, // 0x26 &
127 cltSq, // 0x27 '
128 cltUnknown, // 0x28
129 cltUnknown, // 0x29
130 cltUnknown, // 0x2A
131 cltUnknown, // 0x2B
132 cltUnknown, // 0x2C
133 cltDash, // 0x2D -
134 cltUnknown, // 0x2E
135 cltSlash, // 0x2F /
136 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x30 - 0x37
137 cltUnknown, // 0x38
138 cltUnknown, // 0x39
139 cltUnknown, // 0x3A
140 cltUnknown, // 0x3B
141 cltLt, // 0x3C <
142 cltEq, // 0x3D =
143 cltGt, // 0x3E >
144 cltQm, // 0x3F ?
145 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x40 - 0x47
146 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x48 - 0x4F
147 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x50 - 0x57
148 cltUnknown, // 0x58
149 cltUnknown, // 0x59
150 cltUnknown, // 0x5A
151 cltOB, // 0x5B [
152 cltUnknown, // 0x5C
153 cltCB, // 0x5D ]
154 cltUnknown, // 0x5E
155 cltUnknown, // 0x5F
156 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x60 - 0x67
157 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x68 - 0x6F
158 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x70 - 0x77
159 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x78 - 0x7F
160 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x80 - 0x87
161 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x88 - 0x8F
162 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x90 - 0x97
163 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0x98 - 0x9F
164 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xA0 - 0xA7
165 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xA8 - 0xAF
166 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xB0 - 0xB7
167 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xB8 - 0xBF
168 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xC0 - 0xC7
169 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xC8 - 0xCF
170 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xD0 - 0xD7
171 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xD8 - 0xDF
172 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xE0 - 0xE7
173 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xE8 - 0xEF
174 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, // 0xF0 - 0xF7
175 cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown, cltUnknown // 0xF8 - 0xFF
176};
177
178
179class QXmlNamespaceSupportPrivate
180{
181};
182class QXmlAttributesPrivate
183{
184};
185class QXmlInputSourcePrivate
186{
187};
188class QXmlParseExceptionPrivate
189{
190};
191class QXmlLocatorPrivate
192{
193};
194class QXmlDefaultHandlerPrivate
195{
196};
197
198#if defined(Q_FULL_TEMPLATE_INSTANTIATION)
199bool operator==( const QMap<QString, QString>, const QMap<QString, QString> )
200{
201 return FALSE;
202}
203#endif
204
205/*!
206 \class QXmlParseException qxml.h
207 \brief The QXmlParseException class is used to report errors with the
208 QXmlErrorHandler interface.
209
210 \module XML
211
212 \sa QXmlErrorHandler
213*/
214/*!
215 \fn QXmlParseException::QXmlParseException( const QString& name, int c, int l, const QString& p, const QString& s )
216
217 Constructs a parse exception with the error string \a name in the column
218 \a c and line \a l for the public identifier \a p and the system identifier
219 \a s.
220*/
221/*!
222 Returns the error message.
223*/
224QString QXmlParseException::message() const
225{
226 return msg;
227}
228/*!
229 Returns the column number the error occured.
230*/
231int QXmlParseException::columnNumber() const
232{
233 return column;
234}
235/*!
236 Returns the line number the error occured.
237*/
238int QXmlParseException::lineNumber() const
239{
240 return line;
241}
242/*!
243 Returns the public identifier the error occured.
244*/
245QString QXmlParseException::publicId() const
246{
247 return pub;
248}
249/*!
250 Returns the system identifier the error occured.
251*/
252QString QXmlParseException::systemId() const
253{
254 return sys;
255}
256
257
258/*!
259 \class QXmlLocator qxml.h
260 \brief The QXmlLocator class provides the XML handler classes with
261 information about the actual parsing position.
262
263 \module XML
264
265 The reader reports a QXmlLocator to the content handler before he starts to
266 parse the document. This is done with the
267 QXmlContentHandler::setDocumentLocator() function. The handler classes can
268 now use this locator to get the actual position the reader is at.
269*/
270/*!
271 \fn QXmlLocator::QXmlLocator( QXmlSimpleReader* parent )
272
273 Constructor.
274*/
275/*!
276 \fn QXmlLocator::~QXmlLocator()
277
278 Destructor.
279*/
280/*!
281 Gets the column number (starting with 1) or -1 if there is no column number
282 available.
283*/
284int QXmlLocator::columnNumber()
285{
286 return ( reader->columnNr == -1 ? -1 : reader->columnNr + 1 );
287}
288/*!
289 Gets the line number (starting with 1) or -1 if there is no line number
290 available.
291*/
292int QXmlLocator::lineNumber()
293{
294 return ( reader->lineNr == -1 ? -1 : reader->lineNr + 1 );
295}
296
297
298/*********************************************
299 *
300 * QXmlNamespaceSupport
301 *
302 *********************************************/
303
304/*!
305 \class QXmlNamespaceSupport qxml.h
306 \brief The QXmlNamespaceSupport class is a helper class for XML readers which
307 want to include namespace support.
308
309 \module XML
310
311 It provides some functions that makes it easy to handle namespaces. Its main
312 use is for subclasses of QXmlReader which want to provide namespace
313 support.
314
315 See also the <a href="xml-sax.html#namespaces">namespace description</a>.
316*/
317
318/*!
319 Constructs a QXmlNamespaceSupport.
320*/
321QXmlNamespaceSupport::QXmlNamespaceSupport()
322{
323 reset();
324}
325
326/*!
327 Destructs a QXmlNamespaceSupport.
328*/
329QXmlNamespaceSupport::~QXmlNamespaceSupport()
330{
331}
332
333/*!
334 This function declares a prefix in the current namespace context; the prefix
335 will remain in force until this context is popped, unless it is shadowed in a
336 descendant context.
337
338 Note that there is an asymmetry in this library: while prefix() will not
339 return the default "" prefix, even if you have declared one; to check for a
340 default prefix, you have to look it up explicitly using uri(). This
341 asymmetry exists to make it easier to look up prefixes for attribute names,
342 where the default prefix is not allowed.
343*/
344void QXmlNamespaceSupport::setPrefix( const QString& pre, const QString& uri )
345{
346 if( pre.isNull() ) {
347ns.insert( "", uri );
348 } else {
349ns.insert( pre, uri );
350 }
351}
352
353/*!
354 Returns one of the prefixes mapped to a namespace URI.
355
356 If more than one prefix is currently mapped to the same URI, this function
357 will make an arbitrary selection; if you want all of the prefixes, use the
358 prefixes() function instead.
359
360 Note: this will never return the empty (default) prefix; to check for a
361 default prefix, use the uri() function with an argument of "".
362*/
363QString QXmlNamespaceSupport::prefix( const QString& uri ) const
364{
365 QMap<QString, QString>::ConstIterator itc, it = ns.begin();
366 while ( (itc=it) != ns.end() ) {
367++it;
368if ( itc.data() == uri && !itc.key().isEmpty() )
369 return itc.key();
370 }
371 return "";
372}
373
374/*!
375 Looks up a prefix in the current context and returns the currently-mapped
376 namespace URI. Use the empty string ("") for the default namespace.
377*/
378QString QXmlNamespaceSupport::uri( const QString& prefix ) const
379{
380 const QString& returi = ns[ prefix ];
381 return returi;
382}
383
384/*!
385 Splits the name at the ':' and returns the prefix and the local name.
386*/
387void QXmlNamespaceSupport::splitName( const QString& qname,
388QString& prefix, QString& localname ) const
389{
390 uint pos;
391 // search the ':'
392 for( pos=0; pos<qname.length(); pos++ ) {
393if ( qname.at(pos) == ':' )
394 break;
395 }
396 // and split
397 prefix = qname.left( pos );
398 localname = qname.mid( pos+1 );
399}
400
401/*!
402 Processes a raw XML 1.0 name in the current context by removing the prefix
403 and looking it up among the prefixes currently declared.
404
405 First parameter is the raw XML 1.0 name to be processed. The second parameter
406 is a flag wheter the name is the name of an attribute (TRUE) or not (FALSE).
407
408 The return values will be stored in the last two parameters as follows:
409 <ul>
410 <li> The namespace URI, or an empty string if none is in use.
411 <li> The local name (without prefix).
412 </ul>
413
414 If the raw name has a prefix that has not been declared, then the return
415 value will be empty.
416
417 Note that attribute names are processed differently than element names: an
418 unprefixed element name will received the default namespace (if any), while
419 an unprefixed element name will not
420*/
421void QXmlNamespaceSupport::processName( const QString& qname,
422bool isAttribute,
423QString& nsuri, QString& localname ) const
424{
425 uint pos;
426 // search the ':'
427 for( pos=0; pos<qname.length(); pos++ ) {
428if ( qname.at(pos) == ':' )
429 break;
430 }
431 if ( pos < qname.length() ) {
432// there was a ':'
433nsuri = uri( qname.left( pos ) );
434localname = qname.mid( pos+1 );
435 } else {
436// there was no ':'
437if ( isAttribute ) {
438 nsuri = ""; // attributes don't take default namespace
439} else {
440 nsuri = uri( "" ); // get default namespace
441}
442localname = qname;
443 }
444}
445
446/*!
447 Returns an enumeration of all prefixes currently declared.
448
449 Note: if there is a default prefix, it will not be returned in this
450 enumeration; check for the default prefix using uri() with an argument
451 of "".
452*/
453QStringList QXmlNamespaceSupport::prefixes() const
454{
455 QStringList list;
456
457 QMap<QString, QString>::ConstIterator itc, it = ns.begin();
458 while ( (itc=it) != ns.end() ) {
459++it;
460if ( !itc.key().isEmpty() )
461 list.append( itc.key() );
462 }
463 return list;
464}
465
466/*!
467 Returns a list of all prefixes currently declared for a URI.
468
469 The xml: prefix will be included. If you want only one prefix that's
470 mapped to the namespace URI, and you don't care which one you get, use the
471 prefix() function instead.
472
473 Note: the empty (default) prefix is never included in this enumeration; to
474 check for the presence of a default namespace, use uri() with an
475 argument of "".
476*/
477QStringList QXmlNamespaceSupport::prefixes( const QString& uri ) const
478{
479 QStringList list;
480
481 QMap<QString, QString>::ConstIterator itc, it = ns.begin();
482 while ( (itc=it) != ns.end() ) {
483++it;
484if ( itc.data() == uri && !itc.key().isEmpty() )
485 list.append( itc.key() );
486 }
487 return list;
488}
489
490/*!
491 Starts a new namespace context.
492
493 Normally, you should push a new context at the beginning of each XML element:
494 the new context will automatically inherit the declarations of its parent
495 context, but it will also keep track of which declarations were made within
496 this context.
497*/
498void QXmlNamespaceSupport::pushContext()
499{
500 nsStack.push( ns );
501}
502
503/*!
504 Reverts to the previous namespace context.
505
506 Normally, you should pop the context at the end of each XML element. After
507 popping the context, all namespace prefix mappings that were previously in
508 force are restored.
509*/
510void QXmlNamespaceSupport::popContext()
511{
512 if( !nsStack.isEmpty() )
513ns = nsStack.pop();
514}
515
516/*!
517 Resets this namespace support object for reuse.
518*/
519void QXmlNamespaceSupport::reset()
520{
521 nsStack.clear();
522 ns.clear();
523 ns.insert( "xml", "http://www.w3.org/XML/1998/namespace" ); // the XML namespace
524}
525
526
527
528/*********************************************
529 *
530 * QXmlAttributes
531 *
532 *********************************************/
533
534/*!
535 \class QXmlAttributes qxml.h
536 \brief The QXmlAttributes class provides XML attributes.
537
538 \module XML
539
540 If attributes are reported by QXmlContentHandler::startElement() this
541 class is used to pass the attribute values. It provides you with different
542 functions to access the attribute names and values.
543*/
544/*!
545 \fn QXmlAttributes::QXmlAttributes()
546
547 Constructs an empty attribute list.
548*/
549/*!
550 \fn QXmlAttributes::~QXmlAttributes()
551
552 Destructs attributes.
553*/
554
555/*!
556 Look up the index of an attribute by an XML 1.0 qualified name.
557
558 Returns the index of the attribute (starting with 0) or -1 if it wasn't
559 found.
560
561 See also the <a href="xml-sax.html#namespaces">namespace description</a>.
562*/
563int QXmlAttributes::index( const QString& qName ) const
564{
565 return qnameList.findIndex( qName );
566}
567
568/*!
569 Looks up the index of an attribute by a namespace name.
570
571 \a uri specifies the namespace URI, or the empty string if the name has no
572 namespace URI. \a localPart specifies the attribute's local name.
573
574 Returns the index of the attribute (starting with 0) or -1 if it wasn't
575 found.
576
577 See also the <a href="xml-sax.html#namespaces">namespace description</a>.
578*/
579int QXmlAttributes::index( const QString& uri, const QString& localPart ) const
580{
581 uint count = uriList.count();
582 for ( uint i=0; i<count; i++ ) {
583if ( uriList[i] == uri && localnameList[i] == localPart )
584 return i;
585 }
586 return -1;
587}
588
589/*!
590 Returns the number of attributes in the list.
591*/
592int QXmlAttributes::length() const
593{
594 return valueList.count();
595}
596
597/*!
598 Looks up an attribute's local name by index (starting with 0).
599
600 See also the <a href="xml-sax.html#namespaces">namespace description</a>.
601*/
602QString QXmlAttributes::localName( int index ) const
603{
604 return localnameList[index];
605}
606
607/*!
608 Looks up an attribute's XML 1.0 qualified name by index (starting with 0).
609
610 See also the <a href="xml-sax.html#namespaces">namespace description</a>.
611*/
612QString QXmlAttributes::qName( int index ) const
613{
614 return qnameList[index];
615}
616
617/*!
618 Looks up an attribute's namespace URI by index (starting with 0).
619
620 See also the <a href="xml-sax.html#namespaces">namespace description</a>.
621*/
622QString QXmlAttributes::uri( int index ) const
623{
624 return uriList[index];
625}
626
627/*!
628 Looks up an attribute's type by index (starting with 0).
629
630 At the moment only 'CDATA' is returned.
631*/
632QString QXmlAttributes::type( int ) const
633{
634 return "CDATA";
635}
636
637/*!
638 Looks up an attribute's type by XML 1.0 qualified name.
639
640 At the moment only 'CDATA' is returned.
641*/
642QString QXmlAttributes::type( const QString& ) const
643{
644 return "CDATA";
645}
646
647/*!
648 Looks up an attribute's type by namespace name.
649
650 The first parameter specifies the namespace URI, or the empty string if
651 the name has no namespace URI. The second parameter specifies the
652 attribute's local name.
653
654 At the moment only 'CDATA' is returned.
655*/
656QString QXmlAttributes::type( const QString&, const QString& ) const
657{
658 return "CDATA";
659}
660
661/*!
662 Looks up an attribute's value by index (starting with 0).
663*/
664QString QXmlAttributes::value( int index ) const
665{
666 return valueList[index];
667}
668
669/*!
670 Looks up an attribute's value by XML 1.0 qualified name.
671
672 See also the <a href="xml-sax.html#namespaces">namespace description</a>.
673*/
674QString QXmlAttributes::value( const QString& qName ) const
675{
676 int i = index( qName );
677 if ( i == -1 )
678return QString::null;
679 return valueList[ i ];
680}
681
682/*!
683 Looks up an attribute's value by namespace name.
684
685 \a uri specifies the namespace URI, or the empty string if the name has no
686 namespace URI. \a localName specifies the attribute's local name.
687
688 See also the <a href="xml-sax.html#namespaces">namespace description</a>.
689*/
690QString QXmlAttributes::value( const QString& uri, const QString& localName ) const
691{
692 int i = index( uri, localName );
693 if ( i == -1 )
694return QString::null;
695 return valueList[ i ];
696}
697
698
699/*********************************************
700 *
701 * QXmlInputSource
702 *
703 *********************************************/
704
705/*!
706 \class QXmlInputSource qxml.h
707 \brief The QXmlInputSource class is the source where XML data is read from.
708
709 \module XML
710
711 All subclasses of QXmlReader read the input from this class.
712*/
713
714/*!
715 Returns all the data this input source contains.
716*/
717const QString& QXmlInputSource::data() const
718{
719 return input;
720}
721
722/*!
723 Constructs a input source which contains no data.
724*/
725QXmlInputSource::QXmlInputSource( )
726{
727 input = "";
728}
729
730/*!
731 Constructs a input source and get the data from the text stream.
732*/
733QXmlInputSource::QXmlInputSource( QTextStream& stream )
734{
735 QByteArray rawData;
736 if ( stream.device()->isDirectAccess() ) {
737rawData = stream.device()->readAll();
738 } else {
739int nread = 0;
740const int bufsize = 512;
741while ( !stream.device()->atEnd() ) {
742 rawData.resize( nread + bufsize );
743 nread += stream.device()->readBlock( rawData.data()+nread, bufsize );
744}
745rawData.resize( nread );
746 }
747 readInput( rawData );
748}
749
750/*!
751 Constructs a input source and get the data from a file. If the file cannot be
752 read the input source is empty.
753*/
754QXmlInputSource::QXmlInputSource( QFile& file )
755{
756 if ( !file.open(IO_ReadOnly) ) {
757input = "";
758return;
759 }
760 QByteArray rawData = file.readAll();
761 readInput( rawData );
762 file.close();
763}
764
765/*!
766 Destructor.
767*/
768QXmlInputSource::~QXmlInputSource()
769{
770}
771
772/*!
773 Sets the data of the input source to \a dat.
774*/
775void QXmlInputSource::setData( const QString& dat )
776{
777 input = dat;
778}
779
780/*!
781 Read the XML file from the byte array; try to recoginize the encoding.
782*/
783// ### The input source should not do the encoding detection!
784void QXmlInputSource::readInput( QByteArray& rawData )
785{
786 QBuffer buf( rawData );
787 buf.open( IO_ReadOnly );
788 QTextStream *stream = new QTextStream( &buf );
789 QChar tmp;
790 // assume UTF8 or UTF16 at first
791 stream->setEncoding( QTextStream::UnicodeUTF8 );
792 input = "";
793 // read the first 5 characters
794 for ( int i=0; i<5; i++ ) {
795*stream >> tmp;
796input += tmp;
797 }
798 // starts the document with an XML declaration?
799 if ( input == "<?xml" ) {
800// read the whole XML declaration
801do {
802 *stream >> tmp;
803 input += tmp;
804} while( tmp != '>' );
805// and try to find out if there is an encoding
806int pos = input.find( "encoding" );
807if ( pos != -1 ) {
808 QString encoding;
809 do {
810pos++;
811if ( pos > (int)input.length() )
812 goto finished;
813 } while( input[pos] != '"' && input[pos] != '\'' );
814 pos++;
815 while( input[pos] != '"' && input[pos] != '\'' ) {
816encoding += input[pos];
817pos++;
818if ( pos > (int)input.length() )
819 goto finished;
820 }
821 delete stream;
822 stream = new QTextStream( &buf );
823 stream->setCodec( QTextCodec::codecForName( encoding ) );
824 buf.reset();
825 input = "";
826}
827 }
828finished:
829 input += stream->read();
830 delete stream;
831 buf.close();
832}
833
834
835/*********************************************
836 *
837 * QXmlDefaultHandler
838 *
839 *********************************************/
840
841/*!
842 \class QXmlContentHandler qxml.h
843 \brief The QXmlContentHandler class provides an interface to report logical
844 content of XML data.
845
846 \module XML
847
848 If the application needs to be informed of basic parsing events, it
849 implements this interface and sets it with QXmlReader::setContentHandler().
850 The reader reports basic document-related events like the start and end of
851 elements and character data through this interface.
852
853 The order of events in this interface is very important, and mirrors the
854 order of information in the document itself. For example, all of an element's
855 content (character data, processing instructions, and/or subelements) will
856 appear, in order, between the startElement() event and the corresponding
857 endElement() event.
858
859 The class QXmlDefaultHandler gives a default implementation for this
860 interface; subclassing from this class is very convenient if you want only be
861 informed of some parsing events.
862
863 See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>.
864
865 \sa QXmlDTDHandler QXmlDeclHandler QXmlEntityResolver QXmlErrorHandler
866 QXmlLexicalHandler
867*/
868/*!
869 \fn void QXmlContentHandler::setDocumentLocator( QXmlLocator* locator )
870
871 The reader calls this function before he starts parsing the document. The
872 argument \a locator is a pointer to a QXmlLocator which allows the
873 application to get the actual position of the parsing in the document.
874
875 Do not destroy the \a locator; it is destroyed when the reader is destroyed
876 (do not use the \a locator after the reader got destroyed).
877*/
878/*!
879 \fn bool QXmlContentHandler::startDocument()
880
881 The reader calls this function when he starts parsing the document.
882 The reader will call this function only once before any other functions in
883 this class or in the QXmlDTDHandler class are called (except
884 QXmlContentHandler::setDocumentLocator()).
885
886 If this function returns FALSE the reader will stop parsing and will report
887 an error. The reader will use the function errorString() to get the error
888 message that will be used for reporting the error.
889
890 \sa endDocument()
891*/
892/*!
893 \fn bool QXmlContentHandler::endDocument()
894
895 The reader calls this function after he has finished the parsing. It
896 is only called once. It is the last function of all handler functions that is
897 called. It is called after the reader has read all input or has abandoned
898 parsing because of a fatal error.
899
900 If this function returns FALSE the reader will stop parsing and will report
901 an error. The reader will use the function errorString() to get the error
902 message that will be used for reporting the error.
903
904 \sa startDocument()
905*/
906/*!
907 \fn bool QXmlContentHandler::startPrefixMapping( const QString& prefix, const QString& uri )
908
909 The reader calls this function to signal the begin of a prefix-URI
910 namespace mapping scope. This information is not necessary for normal
911 namespace processing since the reader automatically replaces prefixes for
912 element and attribute names.
913
914 Note that startPrefixMapping and endPrefixMapping calls are not guaranteed to
915 be properly nested relative to each-other: all startPrefixMapping events will
916 occur before the corresponding startElement event, and all endPrefixMapping
917 events will occur after the corresponding endElement event, but their order
918 is not otherwise guaranteed.
919
920 The argument \a prefix is the namespace prefix being declared and the
921 argument \a uri is the namespace URI the prefix is mapped to.
922
923 If this function returns FALSE the reader will stop parsing and will report
924 an error. The reader will use the function errorString() to get the error
925 message that will be used for reporting the error.
926
927 See also the <a href="xml-sax.html#namespaces">namespace description</a>.
928
929 \sa endPrefixMapping()
930*/
931/*!
932 \fn bool QXmlContentHandler::endPrefixMapping( const QString& prefix )
933
934 The reader calls this function to signal the end of a prefix mapping.
935
936 If this function returns FALSE the reader will stop parsing and will report
937 an error. The reader will use the function errorString() to get the error
938 message that will be used for reporting the error.
939
940 See also the <a href="xml-sax.html#namespaces">namespace description</a>.
941
942 \sa startPrefixMapping()
943*/
944/*!
945 \fn bool QXmlContentHandler::startElement( const QString& namespaceURI, const QString& localName, const QString& qName, const QXmlAttributes& atts )
946
947 The reader calls this function when he has parsed a start element tag.
948
949 There will be a corresponding endElement() call when the corresponding end
950 element tag was read. The startElement() and endElement() calls are always
951 nested correctly. Empty element tags (e.g. &lt;a/&gt;) are reported by
952 startElement() directly followed by a call to endElement().
953
954 The attribute list provided will contain only attributes with explicit
955 values. The attribute list will contain attributes used for namespace
956 declaration (i.e. attributes starting with xmlns) only if the
957 namespace-prefix property of the reader is TRUE.
958
959 The argument \a uri is the namespace URI, or the empty string if the element
960 has no namespace URI or if namespace processing is not being performed, \a
961 localName is the local name (without prefix), or the empty string if
962 namespace processing is not being performed, \a qName is the qualified name
963 (with prefix), or the empty string if qualified names are not available and
964 \a atts are the attributes attached to the element. If there are no
965 attributes, \a atts is an empty attributes object
966
967 If this function returns FALSE the reader will stop parsing and will report
968 an error. The reader will use the function errorString() to get the error
969 message that will be used for reporting the error.
970
971 See also the <a href="xml-sax.html#namespaces">namespace description</a>.
972
973 \sa endElement()
974*/
975/*!
976 \fn bool QXmlContentHandler::endElement( const QString& namespaceURI, const QString& localName, const QString& qName )
977
978 The reader calls this function when he has parsed an end element tag.
979
980 If this function returns FALSE the reader will stop parsing and will report
981 an error. The reader will use the function errorString() to get the error
982 message that will be used for reporting the error.
983
984 See also the <a href="xml-sax.html#namespaces">namespace description</a>.
985
986 \sa startElement()
987*/
988/*!
989 \fn bool QXmlContentHandler::characters( const QString& ch )
990
991 The reader calls this function when he has parsed a chunk of character
992 data (either normal character data or character data inside a CDATA section;
993 if you have to distinguish between those two types you have to use
994 QXmlLexicalHandler::startCDATA() and QXmlLexicalHandler::endCDATA() in
995 addition).
996
997 Some readers will report whitespace in element content using the
998 ignorableWhitespace() function rather than this one (QXmlSimpleReader will
999 do it not though).
1000
1001 A reader is allowed to report the character data of an element in more than
1002 one chunk; e.g. a reader might want to report "a &amp;lt; b" in three
1003 characters() events ("a ", "<" and " b").
1004
1005 If this function returns FALSE the reader will stop parsing and will report
1006 an error. The reader will use the function errorString() to get the error
1007 message that will be used for reporting the error.
1008*/
1009/*!
1010 \fn bool QXmlContentHandler::ignorableWhitespace( const QString& ch )
1011
1012 Some readers may use this function to report each chunk of whitespace in
1013 element content (QXmlSimpleReader does not though).
1014
1015 If this function returns FALSE the reader will stop parsing and will report
1016 an error. The reader will use the function errorString() to get the error
1017 message that will be used for reporting the error.
1018*/
1019/*!
1020 \fn bool QXmlContentHandler::processingInstruction( const QString& target, const QString& data )
1021
1022 The reader calls this function when he has parsed a processing
1023 instruction.
1024
1025 \a target is the target name of the processing instruction and \a data is the
1026 data of the processing instruction.
1027
1028 If this function returns FALSE the reader will stop parsing and will report
1029 an error. The reader will use the function errorString() to get the error
1030 message that will be used for reporting the error.
1031*/
1032/*!
1033 \fn bool QXmlContentHandler::skippedEntity( const QString& name )
1034
1035 Some readers may skip entities if they have not seen the declarations (e.g.
1036 because they are in an external DTD). If they do so they will report it by
1037 calling this function.
1038
1039 If this function returns FALSE the reader will stop parsing and will report
1040 an error. The reader will use the function errorString() to get the error
1041 message that will be used for reporting the error.
1042*/
1043/*!
1044 \fn QString QXmlContentHandler::errorString()
1045
1046 The reader calls this function to get an error string if any of the handler
1047 functions returns FALSE to him.
1048*/
1049
1050
1051/*!
1052 \class QXmlErrorHandler qxml.h
1053 \brief The QXmlErrorHandler class provides an interface to report errors in
1054 XML data.
1055
1056 \module XML
1057
1058 If the application is interested in reporting errors to the user or any other
1059 customized error handling, you should subclass this class.
1060
1061 You can set the error handler with QXmlReader::setErrorHandler().
1062
1063 See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>.
1064
1065 \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlEntityResolver
1066 QXmlLexicalHandler
1067*/
1068/*!
1069 \fn bool QXmlErrorHandler::warning( const QXmlParseException& exception )
1070
1071 A reader might use this function to report a warning. Warnings are conditions
1072 that are not errors or fatal errors as defined by the XML 1.0 specification.
1073
1074 If this function returns FALSE the reader will stop parsing and will report
1075 an error. The reader will use the function errorString() to get the error
1076 message that will be used for reporting the error.
1077*/
1078/*!
1079 \fn bool QXmlErrorHandler::error( const QXmlParseException& exception )
1080
1081 A reader might use this function to report a recoverable error. A recoverable
1082 error corresponds to the definiton of "error" in section 1.2 of the XML 1.0
1083 specification.
1084
1085 The reader must continue to provide normal parsing events after invoking this
1086 function.
1087
1088 If this function returns FALSE the reader will stop parsing and will report
1089 an error. The reader will use the function errorString() to get the error
1090 message that will be used for reporting the error.
1091*/
1092/*!
1093 \fn bool QXmlErrorHandler::fatalError( const QXmlParseException& exception )
1094
1095 A reader must use this function to report a non-recoverable error.
1096
1097 If this function returns TRUE the reader might try to go on parsing and
1098 reporting further errors; but no regular parsing events are reported.
1099*/
1100/*!
1101 \fn QString QXmlErrorHandler::errorString()
1102
1103 The reader calls this function to get an error string if any of the handler
1104 functions returns FALSE to him.
1105*/
1106
1107
1108/*!
1109 \class QXmlDTDHandler qxml.h
1110 \brief The QXmlDTDHandler class provides an interface to report DTD content
1111 of XML data.
1112
1113 \module XML
1114
1115 If an application needs information about notations and unparsed entities,
1116 then the application implements this interface and registers an instance with
1117 QXmlReader::setDTDHandler().
1118
1119 Note that this interface includes only those DTD events that the XML
1120 recommendation requires processors to report: notation and unparsed entity
1121 declarations.
1122
1123 See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>.
1124
1125 \sa QXmlDeclHandler QXmlContentHandler QXmlEntityResolver QXmlErrorHandler
1126 QXmlLexicalHandler
1127*/
1128/*!
1129 \fn bool QXmlDTDHandler::notationDecl( const QString& name, const QString& publicId, const QString& systemId )
1130
1131 The reader calls this function when he has parsed a notation
1132 declaration.
1133
1134 The argument \a name is the notation name, \a publicId is the notations's
1135 public identifier and \a systemId is the notations's system identifier.
1136
1137 If this function returns FALSE the reader will stop parsing and will report
1138 an error. The reader will use the function errorString() to get the error
1139 message that will be used for reporting the error.
1140*/
1141/*!
1142 \fn bool QXmlDTDHandler::unparsedEntityDecl( const QString& name, const QString& publicId, const QString& systemId, const QString& notationName )
1143
1144 The reader calls this function when he finds an unparsed entity declaration.
1145
1146 The argument \a name is the unparsed entity's name, \a publicId is the
1147 entity's public identifier, \a systemId is the entity's system identifier and
1148 \a notation is the name of the associated notation.
1149
1150 If this function returns FALSE the reader will stop parsing and will report
1151 an error. The reader will use the function errorString() to get the error
1152 message that will be used for reporting the error.
1153*/
1154/*!
1155 \fn QString QXmlDTDHandler::errorString()
1156
1157 The reader calls this function to get an error string if any of the handler
1158 functions returns FALSE to him.
1159*/
1160
1161
1162/*!
1163 \class QXmlEntityResolver qxml.h
1164 \brief The QXmlEntityResolver class provides an interface to resolve extern
1165 entities contained in XML data.
1166
1167 \module XML
1168
1169 If an application needs to implement customized handling for external
1170 entities, it must implement this interface and register it with
1171 QXmlReader::setEntityResolver().
1172
1173 See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>.
1174
1175 \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlErrorHandler
1176 QXmlLexicalHandler
1177*/
1178/*!
1179 \fn bool QXmlEntityResolver::resolveEntity( const QString& publicId, const QString& systemId, QXmlInputSource* ret )
1180
1181 The reader will call this function before he opens any external entity,
1182 except the top-level document entity. The application may request the reader
1183 to resolve the entity itself (\a ret is 0) or to use an entirely different
1184 input source (\a ret points to the input source).
1185
1186 The reader will delete the input source \a ret when he no longer needs it. So
1187 you should allocate it on the heap with \c new.
1188
1189 The argument \a publicId is the public identifier of the external entity, \a
1190 systemId is the system identifier of the external entity and \a ret is the
1191 return value of this function: if it is 0 the reader should resolve the
1192 entity itself, if it is non-zero it must point to an input source which the
1193 reader will use instead.
1194
1195 If this function returns FALSE the reader will stop parsing and will report
1196 an error. The reader will use the function errorString() to get the error
1197 message that will be used for reporting the error.
1198*/
1199/*!
1200 \fn QString QXmlEntityResolver::errorString()
1201
1202 The reader calls this function to get an error string if any of the handler
1203 functions returns FALSE to him.
1204*/
1205
1206
1207/*!
1208 \class QXmlLexicalHandler qxml.h
1209 \brief The QXmlLexicalHandler class provides an interface to report lexical
1210 content of XML data.
1211
1212 \module XML
1213
1214 The events in the lexical handler apply to the entire document, not just to
1215 the document element, and all lexical handler events appear between the
1216 content handler's startDocument and endDocument events.
1217
1218 You can set the lexical handler with QXmlReader::setLexicalHandler().
1219
1220 This interface is designed after the SAX2 extension LexicalHandler. The
1221 functions startEntity() and endEntity() are not included though.
1222
1223 See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>.
1224
1225 \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlEntityResolver
1226 QXmlErrorHandler
1227*/
1228/*!
1229 \fn bool QXmlLexicalHandler::startDTD( const QString& name, const QString& publicId, const QString& systemId )
1230
1231 The reader calls this function to report the start of a DTD declaration, if
1232 any.
1233
1234 All declarations reported through QXmlDTDHandler or QXmlDeclHandler appear
1235 between the startDTD() and endDTD() calls.
1236
1237 If this function returns FALSE the reader will stop parsing and will report
1238 an error. The reader will use the function errorString() to get the error
1239 message that will be used for reporting the error.
1240
1241 \sa endDTD()
1242*/
1243/*!
1244 \fn bool QXmlLexicalHandler::endDTD()
1245
1246 The reader calls this function to report the end of a DTD declaration, if
1247 any.
1248
1249 If this function returns FALSE the reader will stop parsing and will report
1250 an error. The reader will use the function errorString() to get the error
1251 message that will be used for reporting the error.
1252
1253 \sa startDTD()
1254*/
1255/*!
1256 \fn bool QXmlLexicalHandler::startCDATA()
1257
1258 The reader calls this function to report the start of a CDATA section. The
1259 content of the CDATA section will be reported through the regular
1260 QXmlContentHandler::characters(). This function is intended only to report
1261 the boundary.
1262
1263 If this function returns FALSE the reader will stop parsing and will report
1264 an error. The reader will use the function errorString() to get the error
1265 message that will be used for reporting the error.
1266
1267 \sa endCDATA()
1268*/
1269/*!
1270 \fn bool QXmlLexicalHandler::endCDATA()
1271
1272 The reader calls this function to report the end of a CDATA section.
1273
1274 If this function returns FALSE the reader will stop parsing and will report
1275 an error. The reader will use the function errorString() to get the error
1276 message that will be used for reporting the error.
1277
1278 \sa startCDATA()
1279*/
1280/*!
1281 \fn bool QXmlLexicalHandler::comment( const QString& ch )
1282
1283 The reader calls this function to report an XML comment anywhere in the
1284 document.
1285
1286 If this function returns FALSE the reader will stop parsing and will report
1287 an error. The reader will use the function errorString() to get the error
1288 message that will be used for reporting the error.
1289*/
1290/*!
1291 \fn QString QXmlLexicalHandler::errorString()
1292
1293 The reader calls this function to get an error string if any of the handler
1294 functions returns FALSE to him.
1295*/
1296
1297
1298/*!
1299 \class QXmlDeclHandler qxml.h
1300 \brief The QXmlDeclHandler class provides an interface to report declaration
1301 content of XML data.
1302
1303 \module XML
1304
1305 You can set the declaration handler with QXmlReader::setDeclHandler().
1306
1307 This interface is designed after the SAX2 extension DeclHandler.
1308
1309 See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>.
1310
1311 \sa QXmlDTDHandler QXmlContentHandler QXmlEntityResolver QXmlErrorHandler
1312 QXmlLexicalHandler
1313*/
1314/*!
1315 \fn bool QXmlDeclHandler::attributeDecl( const QString& eName, const QString& aName, const QString& type, const QString& valueDefault, const QString& value )
1316
1317 The reader calls this function to report an attribute type declaration. Only
1318 the effective (first) declaration for an attribute will be reported.
1319
1320 If this function returns FALSE the reader will stop parsing and will report
1321 an error. The reader will use the function errorString() to get the error
1322 message that will be used for reporting the error.
1323*/
1324/*!
1325 \fn bool QXmlDeclHandler::internalEntityDecl( const QString& name, const QString& value )
1326
1327 The reader calls this function to report an internal entity declaration. Only
1328 the effective (first) declaration will be reported.
1329
1330 If this function returns FALSE the reader will stop parsing and will report
1331 an error. The reader will use the function errorString() to get the error
1332 message that will be used for reporting the error.
1333*/
1334/*!
1335 \fn bool QXmlDeclHandler::externalEntityDecl( const QString& name, const QString& publicId, const QString& systemId )
1336
1337 The reader calls this function to report a parsed external entity
1338 declaration. Only the effective (first) declaration for each entity will be
1339 reported.
1340
1341 If this function returns FALSE the reader will stop parsing and will report
1342 an error. The reader will use the function errorString() to get the error
1343 message that will be used for reporting the error.
1344*/
1345/*!
1346 \fn QString QXmlDeclHandler::errorString()
1347
1348 The reader calls this function to get an error string if any of the handler
1349 functions returns FALSE to him.
1350*/
1351
1352
1353/*!
1354 \class QXmlDefaultHandler qxml.h
1355 \brief The QXmlDefaultHandler class provides a default implementation of all
1356 XML handler classes.
1357
1358 \module XML
1359
1360 Very often you are only interested in parts of the things that that the
1361 reader reports to you. This class simply implements a default behaviour of
1362 the handler classes (most of the time: do nothing). Normally this is the
1363 class you subclass for implementing your customized handler.
1364
1365 See also the <a href="xml.html#introSAX2">Introduction to SAX2</a>.
1366
1367 \sa QXmlDTDHandler QXmlDeclHandler QXmlContentHandler QXmlEntityResolver
1368 QXmlErrorHandler QXmlLexicalHandler
1369*/
1370/*!
1371 \fn QXmlDefaultHandler::QXmlDefaultHandler()
1372
1373 Constructor.
1374*/
1375/*!
1376 \fn QXmlDefaultHandler::~QXmlDefaultHandler()
1377
1378 Destructor.
1379*/
1380
1381/*!
1382 Does nothing.
1383*/
1384void QXmlDefaultHandler::setDocumentLocator( QXmlLocator* )
1385{
1386}
1387
1388/*!
1389 Does nothing.
1390*/
1391bool QXmlDefaultHandler::startDocument()
1392{
1393 return TRUE;
1394}
1395
1396/*!
1397 Does nothing.
1398*/
1399bool QXmlDefaultHandler::endDocument()
1400{
1401 return TRUE;
1402}
1403
1404/*!
1405 Does nothing.
1406*/
1407bool QXmlDefaultHandler::startPrefixMapping( const QString&, const QString& )
1408{
1409 return TRUE;
1410}
1411
1412/*!
1413 Does nothing.
1414*/
1415bool QXmlDefaultHandler::endPrefixMapping( const QString& )
1416{
1417 return TRUE;
1418}
1419
1420/*!
1421 Does nothing.
1422*/
1423bool QXmlDefaultHandler::startElement( const QString&, const QString&,
1424const QString&, const QXmlAttributes& )
1425{
1426 return TRUE;
1427}
1428
1429/*!
1430 Does nothing.
1431*/
1432bool QXmlDefaultHandler::endElement( const QString&, const QString&,
1433const QString& )
1434{
1435 return TRUE;
1436}
1437
1438/*!
1439 Does nothing.
1440*/
1441bool QXmlDefaultHandler::characters( const QString& )
1442{
1443 return TRUE;
1444}
1445
1446/*!
1447 Does nothing.
1448*/
1449bool QXmlDefaultHandler::ignorableWhitespace( const QString& )
1450{
1451 return TRUE;
1452}
1453
1454/*!
1455 Does nothing.
1456*/
1457bool QXmlDefaultHandler::processingInstruction( const QString&,
1458const QString& )
1459{
1460 return TRUE;
1461}
1462
1463/*!
1464 Does nothing.
1465*/
1466bool QXmlDefaultHandler::skippedEntity( const QString& )
1467{
1468 return TRUE;
1469}
1470
1471/*!
1472 Does nothing.
1473*/
1474bool QXmlDefaultHandler::warning( const QXmlParseException& )
1475{
1476 return TRUE;
1477}
1478
1479/*!
1480 Does nothing.
1481*/
1482bool QXmlDefaultHandler::error( const QXmlParseException& )
1483{
1484 return TRUE;
1485}
1486
1487/*!
1488 Does nothing.
1489*/
1490bool QXmlDefaultHandler::fatalError( const QXmlParseException& )
1491{
1492 return TRUE;
1493}
1494
1495/*!
1496 Does nothing.
1497*/
1498bool QXmlDefaultHandler::notationDecl( const QString&, const QString&,
1499const QString& )
1500{
1501 return TRUE;
1502}
1503
1504/*!
1505 Does nothing.
1506*/
1507bool QXmlDefaultHandler::unparsedEntityDecl( const QString&, const QString&,
1508const QString&, const QString& )
1509{
1510 return TRUE;
1511}
1512
1513/*!
1514 Always sets \a ret to 0, so that the reader will use the system identifier
1515 provided in the XML document.
1516*/
1517bool QXmlDefaultHandler::resolveEntity( const QString&, const QString&,
1518QXmlInputSource* ret )
1519{
1520 ret = 0;
1521 return TRUE;
1522}
1523
1524/*!
1525 Returns the default error string.
1526*/
1527QString QXmlDefaultHandler::errorString()
1528{
1529 return QString( XMLERR_ERRORBYCONSUMER );
1530}
1531
1532/*!
1533 Does nothing.
1534*/
1535bool QXmlDefaultHandler::startDTD( const QString&, const QString&, const QString& )
1536{
1537 return TRUE;
1538}
1539
1540/*!
1541 Does nothing.
1542*/
1543bool QXmlDefaultHandler::endDTD()
1544{
1545 return TRUE;
1546}
1547
1548#if 0
1549/*!
1550 Does nothing.
1551*/
1552bool QXmlDefaultHandler::startEntity( const QString& )
1553{
1554 return TRUE;
1555}
1556
1557/*!
1558 Does nothing.
1559*/
1560bool QXmlDefaultHandler::endEntity( const QString& )
1561{
1562 return TRUE;
1563}
1564#endif
1565
1566/*!
1567 Does nothing.
1568*/
1569bool QXmlDefaultHandler::startCDATA()
1570{
1571 return TRUE;
1572}
1573
1574/*!
1575 Does nothing.
1576*/
1577bool QXmlDefaultHandler::endCDATA()
1578{
1579 return TRUE;
1580}
1581
1582/*!
1583 Does nothing.
1584*/
1585bool QXmlDefaultHandler::comment( const QString& )
1586{
1587 return TRUE;
1588}
1589
1590/*!
1591 Does nothing.
1592*/
1593bool QXmlDefaultHandler::attributeDecl( const QString&, const QString&, const QString&, const QString&, const QString& )
1594{
1595 return TRUE;
1596}
1597
1598/*!
1599 Does nothing.
1600*/
1601bool QXmlDefaultHandler::internalEntityDecl( const QString&, const QString& )
1602{
1603 return TRUE;
1604}
1605
1606/*!
1607 Does nothing.
1608*/
1609bool QXmlDefaultHandler::externalEntityDecl( const QString&, const QString&, const QString& )
1610{
1611 return TRUE;
1612}
1613
1614
1615/*********************************************
1616 *
1617 * QXmlSimpleReaderPrivate
1618 *
1619 *********************************************/
1620
1621class QXmlSimpleReaderPrivate
1622{
1623private:
1624 // constructor
1625 QXmlSimpleReaderPrivate()
1626 { }
1627
1628
1629 // used for entity declarations
1630 struct ExternParameterEntity
1631 {
1632ExternParameterEntity( ) {}
1633ExternParameterEntity( const QString &p, const QString &s )
1634 : publicId(p), systemId(s) {}
1635QString publicId;
1636QString systemId;
1637 };
1638 struct ExternEntity
1639 {
1640ExternEntity( ) {}
1641ExternEntity( const QString &p, const QString &s, const QString &n )
1642 : publicId(p), systemId(s), notation(n) {}
1643QString publicId;
1644QString systemId;
1645QString notation;
1646 };
1647 QMap<QString,ExternParameterEntity> externParameterEntities;
1648 QMap<QString,QString> parameterEntities;
1649 QMap<QString,ExternEntity> externEntities;
1650 QMap<QString,QString> entities;
1651
1652 // used for standalone declaration
1653 enum Standalone { Yes, No, Unknown };
1654
1655 QString doctype; // only used for the doctype
1656 QString xmlVersion; // only used to store the version information
1657 QString encoding; // only used to store the encoding
1658 Standalone standalone; // used to store the value of the standalone declaration
1659
1660 QString publicId; // used by parseExternalID() to store the public ID
1661 QString systemId; // used by parseExternalID() to store the system ID
1662 QString attDeclEName; // use by parseAttlistDecl()
1663 QString attDeclAName; // use by parseAttlistDecl()
1664
1665 // flags for some features support
1666 bool useNamespaces;
1667 bool useNamespacePrefixes;
1668 bool reportWhitespaceCharData;
1669
1670 // used to build the attribute list
1671 QXmlAttributes attList;
1672
1673 // helper classes
1674 QXmlLocator *locator;
1675 QXmlNamespaceSupport namespaceSupport;
1676
1677 // error string
1678 QString error;
1679
1680 // friend declarations
1681 friend class QXmlSimpleReader;
1682};
1683
1684
1685/*********************************************
1686 *
1687 * QXmlSimpleReader
1688 *
1689 *********************************************/
1690
1691/*!
1692 \class QXmlReader qxml.h
1693 \brief The QXmlReader class provides an interface for XML readers (i.e.
1694 parsers).
1695
1696 \module XML
1697
1698 This abstract class describes an interface for all XML readers in Qt. At the
1699 moment there is only one implementation of a reader included in the XML
1700 module of Qt (QXmlSimpleReader). In future releases there might be more
1701 readers with different properties available (e.g. a validating parser).
1702
1703 The design of the XML classes follow the
1704 <a href="http://www.megginson.com/SAX/">SAX2 java interface</a>.
1705 It was adopted to fit into the Qt naming conventions; so it should be very
1706 easy for anybody who has worked with SAX2 to get started with the Qt XML
1707 classes.
1708
1709 All readers use the class QXmlInputSource to read the input document from.
1710 Since you are normally interested in certain contents of the XML document,
1711 the reader reports those contents through special handler classes
1712 (QXmlDTDHandler, QXmlDeclHandler, QXmlContentHandler, QXmlEntityResolver,
1713 QXmlErrorHandler and QXmlLexicalHandler).
1714
1715 You have to subclass these classes. Since the handler classes describe only
1716 interfaces you must implement all functions; there is a class
1717 (QXmlDefaultHandler) to make this easier; it implements a default behaviour
1718 (do nothing) for all functions.
1719
1720 For getting started see also the
1721 <a href="xml-sax.html#quickStart">Quick start</a>.
1722
1723 \sa QXmlSimpleReader
1724*/
1725/*!
1726 \fn bool QXmlReader::feature( const QString& name, bool *ok ) const
1727
1728 If the reader has the feature \a name, this function returns the value of the
1729 feature.
1730
1731 If the reader has not the feature \a name, the return value may be anything.
1732
1733 If \a ok is not 0, then \a ok is set to TRUE if the reader has the feature
1734 \a name, otherwise \a ok is set to FALSE.
1735
1736 \sa setFeature() hasFeature()
1737*/
1738/*!
1739 \fn void QXmlReader::setFeature( const QString& name, bool value )
1740
1741 Sets the feature \a name to \a value. If the reader has not the feature \a
1742 name, this value is ignored.
1743
1744 \sa feature() hasFeature()
1745*/
1746/*!
1747 \fn bool QXmlReader::hasFeature( const QString& name ) const
1748
1749 Returns \c TRUE if the reader has the feature \a name, otherwise FALSE.
1750
1751 \sa feature() setFeature()
1752*/
1753/*!
1754 \fn void* QXmlReader::property( const QString& name, bool *ok ) const
1755
1756 If the reader has the property \a name, this function returns the value of
1757 the property.
1758
1759 If the reader has not the property \a name, the return value is 0.
1760
1761 If \a ok is not 0, then \a ok is set to TRUE if the reader has the property
1762 \a name, otherwise \a ok is set to FALSE.
1763
1764 \sa setProperty() hasProperty()
1765*/
1766/*!
1767 \fn void QXmlReader::setProperty( const QString& name, void* value )
1768
1769 Sets the property \a name to \a value. If the reader has not the property \a
1770 name, this value is ignored.
1771
1772 \sa property() hasProperty()
1773*/
1774/*!
1775 \fn bool QXmlReader::hasProperty( const QString& name ) const
1776
1777 Returns TRUE if the reader has the property \a name, otherwise FALSE.
1778
1779 \sa property() setProperty()
1780*/
1781/*!
1782 \fn void QXmlReader::setEntityResolver( QXmlEntityResolver* handler )
1783
1784 Sets the entity resolver to \a handler.
1785
1786 \sa entityResolver()
1787*/
1788/*!
1789 \fn QXmlEntityResolver* QXmlReader::entityResolver() const
1790
1791 Returns the entity resolver or 0 if none was set.
1792
1793 \sa setEntityResolver()
1794*/
1795/*!
1796 \fn void QXmlReader::setDTDHandler( QXmlDTDHandler* handler )
1797
1798 Sets the DTD handler to \a handler.
1799
1800 \sa DTDHandler()
1801*/
1802/*!
1803 \fn QXmlDTDHandler* QXmlReader::DTDHandler() const
1804
1805 Returns the DTD handler or 0 if none was set.
1806
1807 \sa setDTDHandler()
1808*/
1809/*!
1810 \fn void QXmlReader::setContentHandler( QXmlContentHandler* handler )
1811
1812 Sets the content handler to \a handler.
1813
1814 \sa contentHandler()
1815*/
1816/*!
1817 \fn QXmlContentHandler* QXmlReader::contentHandler() const
1818
1819 Returns the content handler or 0 if none was set.
1820
1821 \sa setContentHandler()
1822*/
1823/*!
1824 \fn void QXmlReader::setErrorHandler( QXmlErrorHandler* handler )
1825
1826 Sets the error handler to \a handler.
1827
1828 \sa errorHandler()
1829*/
1830/*!
1831 \fn QXmlErrorHandler* QXmlReader::errorHandler() const
1832
1833 Returns the error handler or 0 if none was set
1834
1835 \sa setErrorHandler()
1836*/
1837/*!
1838 \fn void QXmlReader::setLexicalHandler( QXmlLexicalHandler* handler )
1839
1840 Sets the lexical handler to \a handler.
1841
1842 \sa lexicalHandler()
1843*/
1844/*!
1845 \fn QXmlLexicalHandler* QXmlReader::lexicalHandler() const
1846
1847 Returns the lexical handler or 0 if none was set.
1848
1849 \sa setLexicalHandler()
1850*/
1851/*!
1852 \fn void QXmlReader::setDeclHandler( QXmlDeclHandler* handler )
1853
1854 Sets the declaration handler to \a handler.
1855
1856 \sa declHandler()
1857*/
1858/*!
1859 \fn QXmlDeclHandler* QXmlReader::declHandler() const
1860
1861 Returns the declaration handler or 0 if none was set.
1862
1863 \sa setDeclHandler()
1864*/
1865/*!
1866 \fn bool QXmlReader::parse( const QXmlInputSource& input )
1867
1868 Parses the XML document \a input. Returns TRUE if the parsing was successful,
1869 otherwise FALSE.
1870*/
1871/*!
1872 \fn bool QXmlReader::parse( const QString& systemId )
1873
1874 Parses the XML document at the location \a systemId. Returns TRUE if the
1875 parsing was successful, otherwise FALSE.
1876*/
1877
1878
1879/*!
1880 \class QXmlSimpleReader qxml.h
1881 \brief The QXmlSimpleReader class provides an implementation of a simple XML
1882 reader (i.e. parser).
1883
1884 \module XML
1885
1886 This XML reader is sufficient for simple parsing tasks. Here is a short list
1887 of the properties of this reader:
1888 <ul>
1889 <li> well-formed parser
1890 <li> does not parse any external entities
1891 <li> can do namespace processing
1892 </ul>
1893
1894 For getting started see also the
1895 <a href="xml-sax.html#quickStart">Quick start</a>.
1896*/
1897
1898//guaranteed not to be a characater
1899const QChar QXmlSimpleReader::QEOF = QChar((ushort)0xffff);
1900
1901/*!
1902 Constructs a simple XML reader.
1903*/
1904QXmlSimpleReader::QXmlSimpleReader()
1905{
1906 d = new QXmlSimpleReaderPrivate();
1907 d->locator = new QXmlLocator( this );
1908
1909 entityRes = 0;
1910 dtdHnd = 0;
1911 contentHnd = 0;
1912 errorHnd = 0;
1913 lexicalHnd = 0;
1914 declHnd = 0;
1915
1916 // default feature settings
1917 d->useNamespaces = TRUE;
1918 d->useNamespacePrefixes = FALSE;
1919 d->reportWhitespaceCharData = TRUE;
1920}
1921
1922/*!
1923 Destroys a simple XML reader.
1924*/
1925QXmlSimpleReader::~QXmlSimpleReader()
1926{
1927 delete d->locator;
1928 delete d;
1929}
1930
1931/*!
1932 Gets the state of a feature.
1933
1934 \sa setFeature() hasFeature()
1935*/
1936bool QXmlSimpleReader::feature( const QString& name, bool *ok ) const
1937{
1938 if ( ok != 0 )
1939*ok = TRUE;
1940 if ( name == "http://xml.org/sax/features/namespaces" ) {
1941return d->useNamespaces;
1942 } else if ( name == "http://xml.org/sax/features/namespace-prefixes" ) {
1943return d->useNamespacePrefixes;
1944 } else if ( name == "http://trolltech.com/xml/features/report-whitespace-only-CharData" ) {
1945return d->reportWhitespaceCharData;
1946 } else {
1947qWarning( "Unknown feature %s", name.ascii() );
1948if ( ok != 0 )
1949 *ok = FALSE;
1950 }
1951 return FALSE;
1952}
1953
1954/*!
1955 Sets the state of a feature.
1956
1957 Supported features are:
1958 <ul>
1959 <li> http://xml.org/sax/features/namespaces:
1960 if this feature is TRUE, namespace processing is performed
1961 <li> http://xml.org/sax/features/namespace-prefixes:
1962 if this feature is TRUE, the the original prefixed names and attributes
1963 used for namespace declarations are reported
1964 <li> http://trolltech.com/xml/features/report-whitespace-only-CharData:
1965 if this feature is TRUE, CharData that consists only of whitespace (and
1966 no other characters) is not reported via
1967 QXmlContentHandler::characters()
1968 </ul>
1969
1970 \sa feature() hasFeature()
1971*/
1972void QXmlSimpleReader::setFeature( const QString& name, bool value )
1973{
1974 if ( name == "http://xml.org/sax/features/namespaces" ) {
1975d->useNamespaces = value;
1976 } else if ( name == "http://xml.org/sax/features/namespace-prefixes" ) {
1977d->useNamespacePrefixes = value;
1978 } else if ( name == "http://trolltech.com/xml/features/report-whitespace-only-CharData" ) {
1979d->reportWhitespaceCharData = value;
1980 } else {
1981qWarning( "Unknown feature %s", name.ascii() );
1982 }
1983}
1984
1985/*!
1986 Returns TRUE if the class has a feature named \a feature, otherwise FALSE.
1987
1988 \sa setFeature() feature()
1989*/
1990bool QXmlSimpleReader::hasFeature( const QString& name ) const
1991{
1992 if ( name == "http://xml.org/sax/features/namespaces" ||
1993 name == "http://xml.org/sax/features/namespace-prefixes" ||
1994 name == "http://trolltech.com/xml/features/report-whitespace-only-CharData" ) {
1995return TRUE;
1996 } else {
1997return FALSE;
1998 }
1999}
2000
2001/*!
2002 Returns 0 since this class does not support any properties.
2003*/
2004void* QXmlSimpleReader::property( const QString&, bool *ok ) const
2005{
2006 if ( ok != 0 )
2007*ok = FALSE;
2008 return 0;
2009}
2010
2011/*!
2012 Does nothing since this class does not support any properties.
2013*/
2014void QXmlSimpleReader::setProperty( const QString&, void* )
2015{
2016}
2017
2018/*!
2019 Returns FALSE since this class does not support any properties.
2020*/
2021bool QXmlSimpleReader::hasProperty( const QString& ) const
2022{
2023 return FALSE;
2024}
2025
2026/*! \reimp */
2027void QXmlSimpleReader::setEntityResolver( QXmlEntityResolver* handler )
2028{ entityRes = handler; }
2029
2030/*! \reimp */
2031QXmlEntityResolver* QXmlSimpleReader::entityResolver() const
2032{ return entityRes; }
2033
2034/*! \reimp */
2035void QXmlSimpleReader::setDTDHandler( QXmlDTDHandler* handler )
2036{ dtdHnd = handler; }
2037
2038/*! \reimp */
2039QXmlDTDHandler* QXmlSimpleReader::DTDHandler() const
2040{ return dtdHnd; }
2041
2042/*! \reimp */
2043void QXmlSimpleReader::setContentHandler( QXmlContentHandler* handler )
2044{ contentHnd = handler; }
2045
2046/*! \reimp */
2047QXmlContentHandler* QXmlSimpleReader::contentHandler() const
2048{ return contentHnd; }
2049
2050/*! \reimp */
2051void QXmlSimpleReader::setErrorHandler( QXmlErrorHandler* handler )
2052{ errorHnd = handler; }
2053
2054/*! \reimp */
2055QXmlErrorHandler* QXmlSimpleReader::errorHandler() const
2056{ return errorHnd; }
2057
2058/*! \reimp */
2059void QXmlSimpleReader::setLexicalHandler( QXmlLexicalHandler* handler )
2060{ lexicalHnd = handler; }
2061
2062/*! \reimp */
2063QXmlLexicalHandler* QXmlSimpleReader::lexicalHandler() const
2064{ return lexicalHnd; }
2065
2066/*! \reimp */
2067void QXmlSimpleReader::setDeclHandler( QXmlDeclHandler* handler )
2068{ declHnd = handler; }
2069
2070/*! \reimp */
2071QXmlDeclHandler* QXmlSimpleReader::declHandler() const
2072{ return declHnd; }
2073
2074
2075
2076/*! \reimp */
2077bool QXmlSimpleReader::parse( const QXmlInputSource& input )
2078{
2079 init( input );
2080 // call the handler
2081 if ( contentHnd ) {
2082contentHnd->setDocumentLocator( d->locator );
2083if ( !contentHnd->startDocument() ) {
2084 d->error = contentHnd->errorString();
2085 goto parseError;
2086}
2087 }
2088 // parse prolog
2089 if ( !parseProlog() ) {
2090d->error = XMLERR_ERRORPARSINGPROLOG;
2091goto parseError;
2092 }
2093 // parse element
2094 if ( !parseElement() ) {
2095d->error = XMLERR_ERRORPARSINGMAINELEMENT;
2096goto parseError;
2097 }
2098 // parse Misc*
2099 while ( !atEnd() ) {
2100if ( !parseMisc() ) {
2101 d->error = XMLERR_ERRORPARSINGMISC;
2102 goto parseError;
2103}
2104 }
2105 // is stack empty?
2106 if ( !tags.isEmpty() ) {
2107d->error = XMLERR_UNEXPECTEDEOF;
2108goto parseError;
2109 }
2110 // call the handler
2111 if ( contentHnd ) {
2112if ( !contentHnd->endDocument() ) {
2113 d->error = contentHnd->errorString();
2114 goto parseError;
2115}
2116 }
2117
2118 return TRUE;
2119
2120 // error handling
2121
2122parseError:
2123 reportParseError();
2124 tags.clear();
2125 return FALSE;
2126}
2127
2128/*!
2129 Parses the prolog [22].
2130*/
2131bool QXmlSimpleReader::parseProlog()
2132{
2133 bool xmldecl_possible = TRUE;
2134 bool doctype_read = FALSE;
2135
2136 const signed char Init = 0;
2137 const signed char EatWS = 1; // eat white spaces
2138 const signed char Lt = 2; // '<' read
2139 const signed char Em = 3; // '!' read
2140 const signed char DocType = 4; // read doctype
2141 const signed char Comment = 5; // read comment
2142 const signed char PI = 6; // read PI
2143 const signed char Done = 7;
2144
2145 const signed char InpWs = 0;
2146 const signed char InpLt = 1; // <
2147 const signed char InpQm = 2; // ?
2148 const signed char InpEm = 3; // !
2149 const signed char InpD = 4; // D
2150 const signed char InpDash = 5; // -
2151 const signed char InpUnknown = 6;
2152
2153 // use some kind of state machine for parsing
2154 static signed char table[7][7] = {
2155 /* InpWs InpLt InpQm InpEm InpD InpDash InpUnknown */
2156{ EatWS, Lt, -1, -1, -1, -1, -1 }, // Init
2157{ -1, Lt, -1, -1, -1, -1, -1 }, // EatWS
2158{ -1, -1, PI, Em, Done, -1, Done }, // Lt
2159{ -1, -1, -1, -1, DocType, Comment, -1 }, // Em
2160{ EatWS, Lt, -1, -1, -1, -1, -1 }, // DocType
2161{ EatWS, Lt, -1, -1, -1, -1, -1 }, // Comment
2162{ EatWS, Lt, -1, -1, -1, -1, -1 } // PI
2163 };
2164 signed char state = Init;
2165 signed char input;
2166 bool parseOk = TRUE;
2167
2168 while ( TRUE ) {
2169
2170// read input
2171if ( atEnd() ) {
2172 d->error = XMLERR_UNEXPECTEDEOF;
2173 goto parseError;
2174}
2175if ( is_S(c) ) {
2176 input = InpWs;
2177} else if ( c == '<' ) {
2178 input = InpLt;
2179} else if ( c == '?' ) {
2180 input = InpQm;
2181} else if ( c == '!' ) {
2182 input = InpEm;
2183} else if ( c == 'D' ) {
2184 input = InpD;
2185} else if ( c == '-' ) {
2186 input = InpDash;
2187} else {
2188 input = InpUnknown;
2189}
2190// get new state
2191state = table[state][input];
2192
2193// in some cases do special actions depending on state
2194switch ( state ) {
2195 case EatWS:
2196// XML declaration only on first position possible
2197xmldecl_possible = FALSE;
2198// eat white spaces
2199eat_ws();
2200break;
2201 case Lt:
2202// next character
2203next();
2204break;
2205 case Em:
2206// XML declaration only on first position possible
2207xmldecl_possible = FALSE;
2208// next character
2209next();
2210break;
2211 case DocType:
2212parseOk = parseDoctype();
2213break;
2214 case Comment:
2215parseOk = parseComment();
2216break;
2217 case PI:
2218parseOk = parsePI( xmldecl_possible );
2219break;
2220}
2221// no input is read after this
2222switch ( state ) {
2223 case DocType:
2224if ( !parseOk ) {
2225 d->error = XMLERR_ERRORPARSINGPROLOG;
2226 goto parseError;
2227}
2228if ( doctype_read ) {
2229 d->error = XMLERR_MORETHANONEDOCTYPE;
2230 goto parseError;
2231} else {
2232 doctype_read = FALSE;
2233}
2234break;
2235 case Comment:
2236if ( !parseOk ) {
2237 d->error = XMLERR_ERRORPARSINGPROLOG;
2238 goto parseError;
2239}
2240if ( lexicalHnd ) {
2241 if ( !lexicalHnd->comment( string() ) ) {
2242d->error = lexicalHnd->errorString();
2243goto parseError;
2244 }
2245}
2246break;
2247 case PI:
2248if ( !parseOk ) {
2249 d->error = XMLERR_ERRORPARSINGPROLOG;
2250 goto parseError;
2251}
2252// call the handler
2253if ( contentHnd ) {
2254 if ( xmldecl_possible && !d->xmlVersion.isEmpty() ) {
2255QString value( "version = '" );
2256value += d->xmlVersion;
2257value += "'";
2258if ( !d->encoding.isEmpty() ) {
2259 value += " encoding = '";
2260 value += d->encoding;
2261 value += "'";
2262}
2263if ( d->standalone == QXmlSimpleReaderPrivate::Yes ) {
2264 value += " standalone = 'yes'";
2265} else if ( d->standalone == QXmlSimpleReaderPrivate::No ) {
2266 value += " standalone = 'no'";
2267}
2268if ( !contentHnd->processingInstruction( "xml", value ) ) {
2269 d->error = contentHnd->errorString();
2270 goto parseError;
2271}
2272 } else {
2273if ( !contentHnd->processingInstruction( name(), string() ) ) {
2274 d->error = contentHnd->errorString();
2275 goto parseError;
2276}
2277 }
2278}
2279// XML declaration only on first position possible
2280xmldecl_possible = FALSE;
2281break;
2282 case Done:
2283return TRUE;
2284 case -1:
2285d->error = XMLERR_ERRORPARSINGELEMENT;
2286goto parseError;
2287}
2288
2289 }
2290
2291 return TRUE;
2292
2293parseError:
2294 reportParseError();
2295 return FALSE;
2296}
2297
2298/*!
2299 Parse an element [39].
2300
2301 Precondition: the opening '<' is already read.
2302*/
2303bool QXmlSimpleReader::parseElement()
2304{
2305 static QString uri, lname, prefix;
2306 static bool t;
2307
2308 const signed char Init = 0;
2309 const signed char ReadName = 1;
2310 const signed char Ws1 = 2;
2311 const signed char STagEnd = 3;
2312 const signed char STagEnd2 = 4;
2313 const signed char ETagBegin = 5;
2314 const signed char ETagBegin2 = 6;
2315 const signed char Ws2 = 7;
2316 const signed char EmptyTag = 8;
2317 const signed char Attribute = 9;
2318 const signed char Ws3 = 10;
2319 const signed char Done = 11;
2320
2321 const signed char InpWs = 0; // whitespace
2322 const signed char InpNameBe = 1; // is_NameBeginning()
2323 const signed char InpGt = 2; // >
2324 const signed char InpSlash = 3; // /
2325 const signed char InpUnknown = 4;
2326
2327 // use some kind of state machine for parsing
2328 static signed char table[11][5] = {
2329 /* InpWs InpNameBe InpGt InpSlash InpUnknown */
2330{ -1, ReadName, -1, -1, -1 }, // Init
2331{ Ws1, Attribute, STagEnd, EmptyTag, -1 }, // ReadName
2332{ -1, Attribute, STagEnd, EmptyTag, -1 }, // Ws1
2333{ STagEnd2, STagEnd2, STagEnd2, STagEnd2, STagEnd2 }, // STagEnd
2334{ -1, -1, -1, ETagBegin, -1 }, // STagEnd2
2335{ -1, ETagBegin2, -1, -1, -1 }, // ETagBegin
2336{ Ws2, -1, Done, -1, -1 }, // ETagBegin2
2337{ -1, -1, Done, -1, -1 }, // Ws2
2338{ -1, -1, Done, -1, -1 }, // EmptyTag
2339{ Ws3, Attribute, STagEnd, EmptyTag, -1 }, // Attribute
2340{ -1, Attribute, STagEnd, EmptyTag, -1 } // Ws3
2341 };
2342 signed char state = Init;
2343 signed char input;
2344 bool parseOk = TRUE;
2345
2346 while ( TRUE ) {
2347
2348// read input
2349if ( atEnd() ) {
2350 d->error = XMLERR_UNEXPECTEDEOF;
2351 goto parseError;
2352}
2353if ( is_S(c) ) {
2354 input = InpWs;
2355} else if ( is_NameBeginning(c) ) {
2356 input = InpNameBe;
2357} else if ( c == '>' ) {
2358 input = InpGt;
2359} else if ( c == '/' ) {
2360 input = InpSlash;
2361} else {
2362 input = InpUnknown;
2363}
2364// get new state
2365//qDebug( "%d -%d(%c)-> %d", state, input, c.latin1(), table[state][input] );
2366state = table[state][input];
2367
2368// in some cases do special actions depending on state
2369switch ( state ) {
2370 case ReadName:
2371parseOk = parseName();
2372break;
2373 case Ws1:
2374 case Ws2:
2375 case Ws3:
2376eat_ws();
2377break;
2378 case STagEnd:
2379// call the handler
2380if ( contentHnd ) {
2381 if ( d->useNamespaces ) {
2382d->namespaceSupport.processName( tags.top(), FALSE, uri, lname );
2383t = contentHnd->startElement( uri, lname, tags.top(), d->attList );
2384 } else {
2385t = contentHnd->startElement( "", "", tags.top(), d->attList );
2386 }
2387 if ( !t ) {
2388d->error = contentHnd->errorString();
2389goto parseError;
2390 }
2391}
2392next();
2393break;
2394 case STagEnd2:
2395parseOk = parseContent();
2396break;
2397 case ETagBegin:
2398next();
2399break;
2400 case ETagBegin2:
2401// get the name of the tag
2402parseOk = parseName();
2403break;
2404 case EmptyTag:
2405if ( tags.isEmpty() ) {
2406 d->error = XMLERR_TAGMISMATCH;
2407 goto parseError;
2408}
2409if ( !parseElementEmptyTag( t, uri, lname ) )
2410 goto parseError;
2411// next character
2412next();
2413break;
2414 case Attribute:
2415// get name and value of attribute
2416parseOk = parseAttribute();
2417break;
2418 case Done:
2419next();
2420break;
2421}
2422// no input is read after this
2423switch ( state ) {
2424 case ReadName:
2425if ( !parseOk ) {
2426 d->error = XMLERR_ERRORPARSINGNAME;
2427 goto parseError;
2428}
2429// store it on the stack
2430tags.push( name() );
2431// empty the attributes
2432d->attList.qnameList.clear();
2433d->attList.uriList.clear();
2434d->attList.localnameList.clear();
2435d->attList.valueList.clear();
2436// namespace support?
2437if ( d->useNamespaces ) {
2438 d->namespaceSupport.pushContext();
2439}
2440break;
2441 case STagEnd2:
2442if ( !parseOk ) {
2443 d->error = XMLERR_ERRORPARSINGCONTENT;
2444 goto parseError;
2445}
2446break;
2447 case ETagBegin2:
2448if ( !parseOk ) {
2449 d->error = XMLERR_ERRORPARSINGNAME;
2450 goto parseError;
2451}
2452if ( !parseElementETagBegin2() )
2453 goto parseError;
2454break;
2455 case Attribute:
2456if ( !parseOk ) {
2457 d->error = XMLERR_ERRORPARSINGATTRIBUTE;
2458 goto parseError;
2459}
2460if ( !parseElementAttribute( prefix, uri, lname ) )
2461 goto parseError;
2462break;
2463 case Done:
2464return TRUE;
2465 case -1:
2466d->error = XMLERR_ERRORPARSINGELEMENT;
2467goto parseError;
2468}
2469
2470 }
2471
2472 return TRUE;
2473
2474parseError:
2475 reportParseError();
2476 return FALSE;
2477}
2478/*!
2479 Helper to break down the size of the code in the case statement.
2480 Return FALSE on error, otherwise TRUE.
2481*/
2482bool QXmlSimpleReader::parseElementEmptyTag( bool &t, QString &uri, QString &lname )
2483{
2484 // pop the stack and call the handler
2485 if ( contentHnd ) {
2486// report startElement first...
2487if ( d->useNamespaces ) {
2488 d->namespaceSupport.processName( tags.top(), FALSE, uri, lname );
2489 t = contentHnd->startElement( uri, lname, tags.top(), d->attList );
2490} else {
2491 t = contentHnd->startElement( "", "", tags.top(), d->attList );
2492}
2493if ( !t ) {
2494 d->error = contentHnd->errorString();
2495 return FALSE;
2496}
2497// ... followed by endElement
2498// ### missing namespace support!
2499if ( !contentHnd->endElement( "","",tags.pop() ) ) {
2500 d->error = contentHnd->errorString();
2501 return FALSE;
2502}
2503// namespace support?
2504if ( d->useNamespaces ) {
2505 QStringList prefixesBefore, prefixesAfter;
2506 if ( contentHnd ) {
2507prefixesBefore = d->namespaceSupport.prefixes();
2508 }
2509 d->namespaceSupport.popContext();
2510 // call the handler for prefix mapping
2511 if ( contentHnd ) {
2512prefixesAfter = d->namespaceSupport.prefixes();
2513for ( QStringList::Iterator it = prefixesBefore.begin(); it != prefixesBefore.end(); ++it ) {
2514 if ( prefixesAfter.contains(*it) == 0 ) {
2515if ( !contentHnd->endPrefixMapping( *it ) ) {
2516 d->error = contentHnd->errorString();
2517 return FALSE;
2518}
2519 }
2520}
2521 }
2522}
2523 } else {
2524tags.pop();
2525 }
2526 return TRUE;
2527}
2528/*!
2529 Helper to break down the size of the code in the case statement.
2530 Return FALSE on error, otherwise TRUE.
2531*/
2532bool QXmlSimpleReader::parseElementETagBegin2()
2533{
2534
2535 // pop the stack and compare it with the name
2536 if ( tags.pop() != name() ) {
2537d->error = XMLERR_TAGMISMATCH;
2538return FALSE;
2539 }
2540 // call the handler
2541 // ### missing namespace support!
2542 if ( contentHnd ) {
2543if ( !contentHnd->endElement("","",name()) ) {
2544 d->error = contentHnd->errorString();
2545 return FALSE;
2546}
2547 }
2548 // namespace support?
2549 if ( d->useNamespaces ) {
2550QStringList prefixesBefore, prefixesAfter;
2551if ( contentHnd ) {
2552 prefixesBefore = d->namespaceSupport.prefixes();
2553}
2554d->namespaceSupport.popContext();
2555// call the handler for prefix mapping
2556if ( contentHnd ) {
2557 prefixesAfter = d->namespaceSupport.prefixes();
2558 for ( QStringList::Iterator it = prefixesBefore.begin(); it != prefixesBefore.end(); ++it ) {
2559if ( prefixesAfter.contains(*it) == 0 ) {
2560 if ( !contentHnd->endPrefixMapping( *it ) ) {
2561d->error = contentHnd->errorString();
2562return FALSE;
2563 }
2564}
2565 }
2566}
2567 }
2568 return TRUE;
2569}
2570/*!
2571 Helper to break down the size of the code in the case statement.
2572 Return FALSE on error, otherwise TRUE.
2573*/
2574bool QXmlSimpleReader::parseElementAttribute( QString &prefix, QString &uri, QString &lname )
2575{
2576 // add the attribute to the list
2577 if ( d->useNamespaces ) {
2578// is it a namespace declaration?
2579d->namespaceSupport.splitName( name(), prefix, lname );
2580if ( prefix == "xmlns" ) {
2581 // namespace declaration
2582 d->namespaceSupport.setPrefix( lname, string() );
2583 if ( d->useNamespacePrefixes ) {
2584d->attList.qnameList.append( name() );
2585d->attList.uriList.append( "" );
2586d->attList.localnameList.append( "" );
2587d->attList.valueList.append( string() );
2588 }
2589 // call the handler for prefix mapping
2590 if ( contentHnd ) {
2591if ( !contentHnd->startPrefixMapping( lname, string() ) ) {
2592 d->error = contentHnd->errorString();
2593 return FALSE;
2594}
2595 }
2596} else {
2597 // no namespace delcaration
2598 d->namespaceSupport.processName( name(), TRUE, uri, lname );
2599 d->attList.qnameList.append( name() );
2600 d->attList.uriList.append( uri );
2601 d->attList.localnameList.append( lname );
2602 d->attList.valueList.append( string() );
2603}
2604 } else {
2605// no namespace support
2606d->attList.qnameList.append( name() );
2607d->attList.uriList.append( "" );
2608d->attList.localnameList.append( "" );
2609d->attList.valueList.append( string() );
2610 }
2611 return TRUE;
2612}
2613
2614/*!
2615 Parse a content [43].
2616
2617 A content is only used between tags. If a end tag is found the < is already
2618 read and the head stand on the '/' of the end tag '</name>'.
2619*/
2620bool QXmlSimpleReader::parseContent()
2621{
2622 bool charDataRead = FALSE;
2623
2624 const signed char Init = 0;
2625 const signed char ChD = 1; // CharData
2626 const signed char ChD1 = 2; // CharData help state
2627 const signed char ChD2 = 3; // CharData help state
2628 const signed char Ref = 4; // Reference
2629 const signed char Lt = 5; // '<' read
2630 const signed char PI = 6; // PI
2631 const signed char Elem = 7; // Element
2632 const signed char Em = 8; // '!' read
2633 const signed char Com = 9; // Comment
2634 const signed char CDS = 10; // CDSect
2635 const signed char CDS1 = 11; // read a CDSect
2636 const signed char CDS2 = 12; // read a CDSect (help state)
2637 const signed char CDS3 = 13; // read a CDSect (help state)
2638 const signed char Done = 14; // finished reading content
2639
2640 const signed char InpLt = 0; // <
2641 const signed char InpGt = 1; // >
2642 const signed char InpSlash = 2; // /
2643 const signed char InpQMark = 3; // ?
2644 const signed char InpEMark = 4; // !
2645 const signed char InpAmp = 5; // &
2646 const signed char InpDash = 6; // -
2647 const signed char InpOpenB = 7; // [
2648 const signed char InpCloseB = 8; // ]
2649 const signed char InpUnknown = 9;
2650
2651 static signed char mapCLT2FSMChar[] = {
2652InpUnknown, // white space
2653InpUnknown, // %
2654InpAmp, // &
2655InpGt, // >
2656InpLt, // <
2657InpSlash, // /
2658InpQMark, // ?
2659InpEMark, // !
2660InpDash, // -
2661InpCloseB, // ]
2662InpOpenB, // [
2663InpUnknown, // =
2664InpUnknown, // "
2665InpUnknown, // '
2666InpUnknown // unknown
2667 };
2668
2669 // use some kind of state machine for parsing
2670 static signed char const table[14][10] = {
2671 /* InpLt InpGt InpSlash InpQMark InpEMark InpAmp InpDash InpOpenB InpCloseB InpUnknown */
2672{ Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD1, ChD }, // Init
2673{ Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD1, ChD }, // ChD
2674{ Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD2, ChD }, // ChD1
2675{ Lt, -1, ChD, ChD, ChD, Ref, ChD, ChD, ChD2, ChD }, // ChD2
2676{ Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // Ref (same as Init)
2677{ -1, -1, Done, PI, Em, -1, -1, -1, -1, Elem }, // Lt
2678{ Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // PI (same as Init)
2679{ Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // Elem (same as Init)
2680{ -1, -1, -1, -1, -1, -1, Com, CDS, -1, -1 }, // Em
2681{ Lt, ChD, ChD, ChD, ChD, Ref, ChD, ChD, ChD, ChD }, // Com (same as Init)
2682{ CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS2, CDS1 }, // CDS
2683{ CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS2, CDS1 }, // CDS1
2684{ CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS3, CDS1 }, // CDS2
2685{ CDS1, Init, CDS1, CDS1, CDS1, CDS1, CDS1, CDS1, CDS3, CDS1 } // CDS3
2686 };
2687 signed char state = Init;
2688 signed char input;
2689 bool parseOk = TRUE;
2690
2691 while ( TRUE ) {
2692
2693// get input (use lookup-table instead of nested ifs for performance
2694// reasons)
2695if ( atEnd() ) {
2696 d->error = XMLERR_UNEXPECTEDEOF;
2697 goto parseError;
2698}
2699if ( c.row() ) {
2700 input = InpUnknown;
2701} else {
2702 input = mapCLT2FSMChar[ charLookupTable[ c.cell() ] ];
2703}
2704
2705// set state according to input
2706state = table[state][input];
2707
2708// do some actions according to state
2709switch ( state ) {
2710 case Init:
2711// next character
2712next();
2713break;
2714 case ChD:
2715// on first call: clear string
2716if ( !charDataRead ) {
2717 charDataRead = TRUE;
2718 stringClear();
2719}
2720stringAddC();
2721next();
2722break;
2723 case ChD1:
2724// on first call: clear string
2725if ( !charDataRead ) {
2726 charDataRead = TRUE;
2727 stringClear();
2728}
2729stringAddC();
2730next();
2731break;
2732 case ChD2:
2733stringAddC();
2734next();
2735break;
2736 case Ref:
2737if ( !charDataRead) {
2738 // reference may be CharData; so clear string to be safe
2739 stringClear();
2740 parseOk = parseReference( charDataRead, InContent );
2741} else {
2742 bool tmp;
2743 parseOk = parseReference( tmp, InContent );
2744}
2745break;
2746 case Lt:
2747// call the handler for CharData
2748if ( contentHnd ) {
2749 if ( charDataRead ) {
2750if ( d->reportWhitespaceCharData || !string().simplifyWhiteSpace().isEmpty() ) {
2751 if ( !contentHnd->characters( string() ) ) {
2752d->error = contentHnd->errorString();
2753goto parseError;
2754 }
2755}
2756 }
2757}
2758charDataRead = FALSE;
2759// next character
2760next();
2761break;
2762 case PI:
2763parseOk = parsePI();
2764break;
2765 case Elem:
2766parseOk = parseElement();
2767break;
2768 case Em:
2769// next character
2770next();
2771break;
2772 case Com:
2773parseOk = parseComment();
2774break;
2775 case CDS:
2776parseOk = parseString( "[CDATA[" );
2777break;
2778 case CDS1:
2779// read one character and add it
2780stringAddC();
2781next();
2782break;
2783 case CDS2:
2784// skip ']'
2785next();
2786break;
2787 case CDS3:
2788// skip ']'...
2789next();
2790break;
2791}
2792// no input is read after this
2793switch ( state ) {
2794 case Ref:
2795if ( !parseOk ) {
2796 d->error = XMLERR_ERRORPARSINGREFERENCE;
2797 goto parseError;
2798}
2799break;
2800 case PI:
2801if ( !parseOk ) {
2802 d->error = XMLERR_ERRORPARSINGPI;
2803 goto parseError;
2804}
2805// call the handler
2806if ( contentHnd ) {
2807 if ( !contentHnd->processingInstruction(name(),string()) ) {
2808d->error = contentHnd->errorString();
2809goto parseError;
2810 }
2811}
2812break;
2813 case Elem:
2814if ( !parseOk ) {
2815 d->error = XMLERR_ERRORPARSINGELEMENT;
2816 goto parseError;
2817}
2818break;
2819 case Com:
2820if ( !parseOk ) {
2821 d->error = XMLERR_ERRORPARSINGCOMMENT;
2822 goto parseError;
2823}
2824if ( lexicalHnd ) {
2825 if ( !lexicalHnd->comment( string() ) ) {
2826d->error = lexicalHnd->errorString();
2827goto parseError;
2828 }
2829}
2830break;
2831 case CDS:
2832if( !parseOk ) {
2833 d->error = XMLERR_CDSECTHEADEREXPECTED;
2834 goto parseError;
2835}
2836// empty string
2837stringClear();
2838break;
2839 case CDS2:
2840if (c != ']') {
2841 stringAddC( ']' );
2842}
2843break;
2844 case CDS3:
2845// test if this skipping was legal
2846if ( c == '>' ) {
2847 // the end of the CDSect
2848 if ( lexicalHnd ) {
2849if ( !lexicalHnd->startCDATA() ) {
2850 d->error = lexicalHnd->errorString();
2851 goto parseError;
2852}
2853 }
2854 if ( contentHnd ) {
2855if ( !contentHnd->characters( string() ) ) {
2856 d->error = contentHnd->errorString();
2857 goto parseError;
2858}
2859 }
2860 if ( lexicalHnd ) {
2861if ( !lexicalHnd->endCDATA() ) {
2862 d->error = lexicalHnd->errorString();
2863 goto parseError;
2864}
2865 }
2866} else if (c == ']') {
2867 // three or more ']'
2868 stringAddC( ']' );
2869} else {
2870 // after ']]' comes another character
2871 stringAddC( ']' );
2872 stringAddC( ']' );
2873}
2874break;
2875 case Done:
2876// call the handler for CharData
2877if ( contentHnd ) {
2878 if ( charDataRead ) {
2879if ( d->reportWhitespaceCharData || !string().simplifyWhiteSpace().isEmpty() ) {
2880 if ( !contentHnd->characters( string() ) ) {
2881d->error = contentHnd->errorString();
2882goto parseError;
2883 }
2884}
2885 }
2886}
2887// Done
2888return TRUE;
2889 case -1:
2890// Error
2891d->error = XMLERR_ERRORPARSINGCONTENT;
2892goto parseError;
2893}
2894
2895 }
2896
2897 return TRUE;
2898
2899parseError:
2900 reportParseError();
2901 return FALSE;
2902}
2903
2904/*!
2905 Parse Misc [27].
2906*/
2907bool QXmlSimpleReader::parseMisc()
2908{
2909 const signed char Init = 0;
2910 const signed char Lt = 1; // '<' was read
2911 const signed char Comment = 2; // read comment
2912 const signed char eatWS = 3; // eat whitespaces
2913 const signed char PI = 4; // read PI
2914 const signed char Comment2 = 5; // read comment
2915
2916 const signed char InpWs = 0; // S
2917 const signed char InpLt = 1; // <
2918 const signed char InpQm = 2; // ?
2919 const signed char InpEm = 3; // !
2920 const signed char InpUnknown = 4;
2921
2922 // use some kind of state machine for parsing
2923 static signed char table[3][5] = {
2924 /* InpWs InpLt InpQm InpEm InpUnknown */
2925{ eatWS, Lt, -1, -1, -1 }, // Init
2926{ -1, -1, PI, Comment, -1 }, // Lt
2927{ -1, -1, -1, -1, Comment2 } // Comment
2928 };
2929 signed char state = Init;
2930 signed char input;
2931 bool parseOk = TRUE;
2932
2933 while ( TRUE ) {
2934
2935// get input
2936if ( atEnd() ) {
2937 d->error = XMLERR_UNEXPECTEDEOF;
2938 goto parseError;
2939}
2940if ( is_S(c) ) {
2941 input = InpWs;
2942} else if ( c == '<' ) {
2943 input = InpLt;
2944} else if ( c == '?' ) {
2945 input = InpQm;
2946} else if ( c == '!' ) {
2947 input = InpEm;
2948} else {
2949 input = InpUnknown;
2950}
2951
2952// set state according to input
2953state = table[state][input];
2954
2955// do some actions according to state
2956switch ( state ) {
2957 case eatWS:
2958eat_ws();
2959break;
2960 case Lt:
2961next();
2962break;
2963 case PI:
2964parseOk = parsePI();
2965break;
2966 case Comment:
2967next();
2968break;
2969 case Comment2:
2970parseOk = parseComment();
2971break;
2972}
2973// no input is read after this
2974switch ( state ) {
2975 case eatWS:
2976return TRUE;
2977 case PI:
2978if ( !parseOk ) {
2979 d->error = XMLERR_ERRORPARSINGPI;
2980 goto parseError;
2981}
2982if ( contentHnd ) {
2983 if ( !contentHnd->processingInstruction(name(),string()) ) {
2984d->error = contentHnd->errorString();
2985goto parseError;
2986 }
2987}
2988return TRUE;
2989 case Comment2:
2990if ( !parseOk ) {
2991 d->error = XMLERR_ERRORPARSINGCOMMENT;
2992 goto parseError;
2993}
2994if ( lexicalHnd ) {
2995 if ( !lexicalHnd->comment( string() ) ) {
2996d->error = lexicalHnd->errorString();
2997goto parseError;
2998 }
2999}
3000return TRUE;
3001 case -1:
3002// Error
3003d->error = XMLERR_UNEXPECTEDCHARACTER;
3004goto parseError;
3005}
3006
3007 }
3008
3009 return TRUE;
3010
3011parseError:
3012 reportParseError();
3013 return FALSE;
3014}
3015
3016/*!
3017 Parse a processing instruction [16].
3018
3019 If xmldec is TRUE, it tries to parse a PI or a XML declaration [23].
3020
3021 Precondition: the beginning '<' of the PI is already read and the head stand
3022 on the '?' of '<?'.
3023
3024 If this funktion was successful, the head-position is on the first
3025 character after the PI.
3026*/
3027bool QXmlSimpleReader::parsePI( bool xmldecl )
3028{
3029 const signed char Init = 0;
3030 const signed char QmI = 1; // ? was read
3031 const signed char Name = 2; // read Name
3032 const signed char XMLDecl = 3; // read XMLDecl
3033 const signed char Ws1 = 4; // eat ws after "xml" of XMLDecl
3034 const signed char PI = 5; // read PI
3035 const signed char Ws2 = 6; // eat ws after Name of PI
3036 const signed char Version = 7; // read versionInfo
3037 const signed char Ws3 = 8; // eat ws after versionInfo
3038 const signed char EorSD = 9; // read EDecl or SDDecl
3039 const signed char Ws4 = 10; // eat ws after EDecl or SDDecl
3040 const signed char SD = 11; // read SDDecl
3041 const signed char Ws5 = 12; // eat ws after SDDecl
3042 const signed char ADone = 13; // almost done
3043 const signed char Char = 14; // Char was read
3044 const signed char Qm = 15; // Qm was read
3045 const signed char Done = 16; // finished reading content
3046
3047 const signed char InpWs = 0; // whitespace
3048 const signed char InpNameBe = 1; // is_nameBeginning()
3049 const signed char InpGt = 2; // >
3050 const signed char InpQm = 3; // ?
3051 const signed char InpUnknown = 4;
3052
3053 // use some kind of state machine for parsing
3054 static signed char table[16][5] = {
3055 /* InpWs, InpNameBe InpGt InpQm InpUnknown */
3056{ -1, -1, -1, QmI, -1 }, // Init
3057{ -1, Name, -1, -1, -1 }, // QmI
3058{ -1, -1, -1, -1, -1 }, // Name (this state is left not through input)
3059{ Ws1, -1, -1, -1, -1 }, // XMLDecl
3060{ -1, Version, -1, -1, -1 }, // Ws1
3061{ Ws2, -1, -1, Qm, -1 }, // PI
3062{ Char, Char, Char, Qm, Char }, // Ws2
3063{ Ws3, -1, -1, ADone, -1 }, // Version
3064{ -1, EorSD, -1, ADone, -1 }, // Ws3
3065{ Ws4, -1, -1, ADone, -1 }, // EorSD
3066{ -1, SD, -1, ADone, -1 }, // Ws4
3067{ Ws5, -1, -1, ADone, -1 }, // SD
3068{ -1, -1, -1, ADone, -1 }, // Ws5
3069{ -1, -1, Done, -1, -1 }, // ADone
3070{ Char, Char, Char, Qm, Char }, // Char
3071{ Char, Char, Done, Qm, Char }, // Qm
3072 };
3073 signed char state = Init;
3074 signed char input;
3075 bool parseOk = TRUE;
3076
3077 while ( TRUE ) {
3078
3079// get input
3080if ( atEnd() ) {
3081 d->error = XMLERR_UNEXPECTEDEOF;
3082 goto parseError;
3083}
3084if ( is_S(c) ) {
3085 input = InpWs;
3086} else if ( is_NameBeginning(c) ) {
3087 input = InpNameBe;
3088} else if ( c == '>' ) {
3089 input = InpGt;
3090} else if ( c == '?' ) {
3091 input = InpQm;
3092} else {
3093 input = InpUnknown;
3094}
3095
3096// set state according to input
3097state = table[state][input];
3098
3099// do some actions according to state
3100switch ( state ) {
3101 case QmI:
3102next();
3103break;
3104 case Name:
3105parseOk = parseName();
3106break;
3107 case Ws1:
3108 case Ws2:
3109 case Ws3:
3110 case Ws4:
3111 case Ws5:
3112eat_ws();
3113break;
3114 case Version:
3115parseOk = parseAttribute();
3116break;
3117 case EorSD:
3118parseOk = parseAttribute();
3119break;
3120 case SD:
3121// get the SDDecl (syntax like an attribute)
3122if ( d->standalone != QXmlSimpleReaderPrivate::Unknown ) {
3123 // already parsed the standalone declaration
3124 d->error = XMLERR_UNEXPECTEDCHARACTER;
3125 goto parseError;
3126}
3127parseOk = parseAttribute();
3128break;
3129 case ADone:
3130next();
3131break;
3132 case Char:
3133stringAddC();
3134next();
3135break;
3136 case Qm:
3137// skip the '?'
3138next();
3139break;
3140 case Done:
3141next();
3142break;
3143}
3144// no input is read after this
3145switch ( state ) {
3146 case Name:
3147if ( !parseOk ) {
3148 d->error = XMLERR_ERRORPARSINGNAME;
3149 goto parseError;
3150}
3151// test what name was read and determine the next state
3152// (not very beautiful, I admit)
3153if ( name().lower() == "xml" ) {
3154 if ( xmldecl && name()=="xml" ) {
3155state = XMLDecl;
3156 } else {
3157d->error = XMLERR_INVALIDNAMEFORPI;
3158goto parseError;
3159 }
3160} else {
3161 state = PI;
3162 stringClear();
3163}
3164break;
3165 case Version:
3166// get version (syntax like an attribute)
3167if ( !parseOk ) {
3168 d->error = XMLERR_VERSIONEXPECTED;
3169 goto parseError;
3170}
3171if ( name() != "version" ) {
3172 d->error = XMLERR_VERSIONEXPECTED;
3173 goto parseError;
3174}
3175d->xmlVersion = string();
3176break;
3177 case EorSD:
3178// get the EDecl or SDDecl (syntax like an attribute)
3179if ( !parseOk ) {
3180 d->error = XMLERR_EDECLORSDDECLEXPECTED;
3181 goto parseError;
3182}
3183if ( name() == "standalone" ) {
3184 if ( string()=="yes" ) {
3185d->standalone = QXmlSimpleReaderPrivate::Yes;
3186 } else if ( string()=="no" ) {
3187d->standalone = QXmlSimpleReaderPrivate::No;
3188 } else {
3189d->error = XMLERR_WRONGVALUEFORSDECL;
3190goto parseError;
3191 }
3192} else if ( name() == "encoding" ) {
3193 d->encoding = string();
3194} else {
3195 d->error = XMLERR_EDECLORSDDECLEXPECTED;
3196 goto parseError;
3197}
3198break;
3199 case SD:
3200if ( !parseOk ) {
3201 d->error = XMLERR_SDDECLEXPECTED;
3202 goto parseError;
3203}
3204if ( name() != "standalone" ) {
3205 d->error = XMLERR_SDDECLEXPECTED;
3206 goto parseError;
3207}
3208if ( string()=="yes" ) {
3209 d->standalone = QXmlSimpleReaderPrivate::Yes;
3210} else if ( string()=="no" ) {
3211 d->standalone = QXmlSimpleReaderPrivate::No;
3212} else {
3213 d->error = XMLERR_WRONGVALUEFORSDECL;
3214 goto parseError;
3215}
3216break;
3217 case Qm:
3218// test if the skipping was legal
3219if ( c != '>' ) {
3220 stringAddC( '?' );
3221}
3222break;
3223 case Done:
3224return TRUE;
3225 case -1:
3226// Error
3227d->error = XMLERR_UNEXPECTEDCHARACTER;
3228goto parseError;
3229}
3230
3231 }
3232
3233 return TRUE;
3234
3235parseError:
3236 reportParseError();
3237 return FALSE;
3238}
3239
3240/*!
3241 Parse a document type definition (doctypedecl [28]).
3242
3243 Precondition: the beginning '<!' of the doctype is already read the head
3244 stands on the 'D' of '<!DOCTYPE'.
3245
3246 If this funktion was successful, the head-position is on the first
3247 character after the document type definition.
3248*/
3249bool QXmlSimpleReader::parseDoctype()
3250{
3251 // some init-stuff
3252 d->systemId = QString::null;
3253 d->publicId = QString::null;
3254
3255 const signed char Init = 0;
3256 const signed char Doctype = 1; // read the doctype
3257 const signed char Ws1 = 2; // eat_ws
3258 const signed char Doctype2 = 3; // read the doctype, part 2
3259 const signed char Ws2 = 4; // eat_ws
3260 const signed char Sys = 5; // read SYSTEM
3261 const signed char Ws3 = 6; // eat_ws
3262 const signed char MP = 7; // markupdecl or PEReference
3263 const signed char PER = 8; // PERReference
3264 const signed char Mup = 9; // markupdecl
3265 const signed char Ws4 = 10; // eat_ws
3266 const signed char MPE = 11; // end of markupdecl or PEReference
3267 const signed char Done = 12;
3268
3269 const signed char InpWs = 0;
3270 const signed char InpD = 1; // 'D'
3271 const signed char InpS = 2; // 'S' or 'P'
3272 const signed char InpOB = 3; // [
3273 const signed char InpCB = 4; // ]
3274 const signed char InpPer = 5; // %
3275 const signed char InpGt = 6; // >
3276 const signed char InpUnknown = 7;
3277
3278 // use some kind of state machine for parsing
3279 static signed char table[12][8] = {
3280 /* InpWs, InpD InpS InpOB InpCB InpPer InpGt InpUnknown */
3281{ -1, Doctype, -1, -1, -1, -1, -1, -1 }, // Init
3282{ Ws1, Doctype2, Doctype2, -1, -1, -1, -1, Doctype2 }, // Doctype
3283{ -1, Doctype2, Doctype2, -1, -1, -1, -1, Doctype2 }, // Ws1
3284{ Ws2, -1, Sys, MP, -1, -1, Done, -1 }, // Doctype2
3285{ -1, -1, Sys, MP, -1, -1, Done, -1 }, // Ws2
3286{ Ws3, -1, -1, MP, -1, -1, Done, -1 }, // Sys
3287{ -1, -1, -1, MP, -1, -1, Done, -1 }, // Ws3
3288{ -1, -1, -1, -1, MPE, PER, -1, Mup }, // MP
3289{ Ws4, -1, -1, -1, MPE, PER, -1, Mup }, // PER
3290{ Ws4, -1, -1, -1, MPE, PER, -1, Mup }, // Mup
3291{ -1, -1, -1, -1, MPE, PER, -1, Mup }, // Ws4
3292{ -1, -1, -1, -1, -1, -1, Done, -1 } // MPE
3293 };
3294 signed char state = Init;
3295 signed char input;
3296 bool parseOk = TRUE;
3297
3298 while ( TRUE ) {
3299
3300// get input
3301if ( atEnd() ) {
3302 d->error = XMLERR_UNEXPECTEDEOF;
3303 goto parseError;
3304}
3305if ( is_S(c) ) {
3306 input = InpWs;
3307} else if ( c == 'D' ) {
3308 input = InpD;
3309} else if ( c == 'S' ) {
3310 input = InpS;
3311} else if ( c == 'P' ) {
3312 input = InpS;
3313} else if ( c == '[' ) {
3314 input = InpOB;
3315} else if ( c == ']' ) {
3316 input = InpCB;
3317} else if ( c == '%' ) {
3318 input = InpPer;
3319} else if ( c == '>' ) {
3320 input = InpGt;
3321} else {
3322 input = InpUnknown;
3323}
3324
3325// set state according to input
3326state = table[state][input];
3327
3328// do some actions according to state
3329switch ( state ) {
3330 case Doctype:
3331parseOk = parseString( "DOCTYPE" );
3332break;
3333 case Ws1:
3334 case Ws2:
3335 case Ws3:
3336 case Ws4:
3337eat_ws();
3338break;
3339 case Doctype2:
3340parseName();
3341break;
3342 case Sys:
3343parseOk = parseExternalID();
3344break;
3345 case MP:
3346next_eat_ws();
3347break;
3348 case PER:
3349parseOk = parsePEReference( InDTD );
3350break;
3351 case Mup:
3352parseOk = parseMarkupdecl();
3353break;
3354 case MPE:
3355next_eat_ws();
3356break;
3357 case Done:
3358if ( lexicalHnd ) {
3359 if ( !lexicalHnd->endDTD() ) {
3360d->error = lexicalHnd->errorString();
3361goto parseError;
3362 }
3363}
3364next();
3365break;
3366}
3367// no input is read after this
3368switch ( state ) {
3369 case Doctype:
3370if ( !parseOk ) {
3371 d->error = XMLERR_ERRORPARSINGDOCTYPE;
3372 goto parseError;
3373}
3374if ( !is_S(c) ) {
3375 d->error = XMLERR_ERRORPARSINGDOCTYPE;
3376 goto parseError;
3377}
3378break;
3379 case Doctype2:
3380d->doctype = name();
3381if ( lexicalHnd ) {
3382 if ( !lexicalHnd->startDTD( d->doctype, d->publicId, d->systemId ) ) {
3383d->error = lexicalHnd->errorString();
3384goto parseError;
3385 }
3386}
3387break;
3388 case Sys:
3389if ( !parseOk ) {
3390 d->error = XMLERR_ERRORPARSINGDOCTYPE;
3391 goto parseError;
3392}
3393break;
3394 case PER:
3395if ( !parseOk ) {
3396 d->error = XMLERR_ERRORPARSINGDOCTYPE;
3397 goto parseError;
3398}
3399break;
3400 case Mup:
3401if ( !parseOk ) {
3402 d->error = XMLERR_ERRORPARSINGDOCTYPE;
3403 goto parseError;
3404}
3405break;
3406 case Done:
3407return TRUE;
3408 case -1:
3409// Error
3410d->error = XMLERR_ERRORPARSINGDOCTYPE;
3411goto parseError;
3412}
3413
3414 }
3415
3416 return TRUE;
3417
3418parseError:
3419 reportParseError();
3420 return FALSE;
3421}
3422
3423/*!
3424 Parse a ExternalID [75].
3425
3426 If allowPublicID is TRUE parse ExternalID [75] or PublicID [83].
3427*/
3428bool QXmlSimpleReader::parseExternalID( bool allowPublicID )
3429{
3430 // some init-stuff
3431 d->systemId = QString::null;
3432 d->publicId = QString::null;
3433
3434 const signed char Init = 0;
3435 const signed char Sys = 1; // parse 'SYSTEM'
3436 const signed char SysWS = 2; // parse the whitespace after 'SYSTEM'
3437 const signed char SysSQ = 3; // parse SystemLiteral with '
3438 const signed char SysSQ2 = 4; // parse SystemLiteral with '
3439 const signed char SysDQ = 5; // parse SystemLiteral with "
3440 const signed char SysDQ2 = 6; // parse SystemLiteral with "
3441 const signed char Pub = 7; // parse 'PUBLIC'
3442 const signed char PubWS = 8; // parse the whitespace after 'PUBLIC'
3443 const signed char PubSQ = 9; // parse PubidLiteral with '
3444 const signed char PubSQ2 = 10; // parse PubidLiteral with '
3445 const signed char PubDQ = 11; // parse PubidLiteral with "
3446 const signed char PubDQ2 = 12; // parse PubidLiteral with "
3447 const signed char PubE = 13; // finished parsing the PubidLiteral
3448 const signed char PubWS2 = 14; // parse the whitespace after the PubidLiteral
3449 const signed char PDone = 15; // done if allowPublicID is TRUE
3450 const signed char Done = 16;
3451
3452 const signed char InpSQ = 0; // '
3453 const signed char InpDQ = 1; // "
3454 const signed char InpS = 2; // S
3455 const signed char InpP = 3; // P
3456 const signed char InpWs = 4; // white space
3457 const signed char InpUnknown = 5;
3458
3459 // use some kind of state machine for parsing
3460 static signed char table[15][6] = {
3461 /* InpSQ InpDQ InpS InpP InpWs InpUnknown */
3462{ -1, -1, Sys, Pub, -1, -1 }, // Init
3463{ -1, -1, -1, -1, SysWS, -1 }, // Sys
3464{ SysSQ, SysDQ, -1, -1, -1, -1 }, // SysWS
3465{ Done, SysSQ2, SysSQ2, SysSQ2, SysSQ2, SysSQ2 }, // SysSQ
3466{ Done, SysSQ2, SysSQ2, SysSQ2, SysSQ2, SysSQ2 }, // SysSQ2
3467{ SysDQ2, Done, SysDQ2, SysDQ2, SysDQ2, SysDQ2 }, // SysDQ
3468{ SysDQ2, Done, SysDQ2, SysDQ2, SysDQ2, SysDQ2 }, // SysDQ2
3469{ -1, -1, -1, -1, PubWS, -1 }, // Pub
3470{ PubSQ, PubDQ, -1, -1, -1, -1 }, // PubWS
3471{ PubE, -1, PubSQ2, PubSQ2, PubSQ2, PubSQ2 }, // PubSQ
3472{ PubE, -1, PubSQ2, PubSQ2, PubSQ2, PubSQ2 }, // PubSQ2
3473{ -1, PubE, PubDQ2, PubDQ2, PubDQ2, PubDQ2 }, // PubDQ
3474{ -1, PubE, PubDQ2, PubDQ2, PubDQ2, PubDQ2 }, // PubDQ2
3475{ PDone, PDone, PDone, PDone, PubWS2, PDone }, // PubE
3476{ SysSQ, SysDQ, PDone, PDone, PDone, PDone } // PubWS2
3477 };
3478 signed char state = Init;
3479 signed char input;
3480 bool parseOk = TRUE;
3481
3482 while ( TRUE ) {
3483
3484// get input
3485if ( atEnd() ) {
3486 d->error = XMLERR_UNEXPECTEDEOF;
3487 goto parseError;
3488}
3489if ( is_S(c) ) {
3490 input = InpWs;
3491} else if ( c == '\'' ) {
3492 input = InpSQ;
3493} else if ( c == '"' ) {
3494 input = InpDQ;
3495} else if ( c == 'S' ) {
3496 input = InpS;
3497} else if ( c == 'P' ) {
3498 input = InpP;
3499} else {
3500 input = InpUnknown;
3501}
3502
3503// set state according to input
3504state = table[state][input];
3505
3506// do some actions according to state
3507switch ( state ) {
3508 case Sys:
3509parseOk = parseString( "SYSTEM" );
3510break;
3511 case SysWS:
3512eat_ws();
3513break;
3514 case SysSQ:
3515 case SysDQ:
3516stringClear();
3517next();
3518break;
3519 case SysSQ2:
3520 case SysDQ2:
3521stringAddC();
3522next();
3523break;
3524 case Pub:
3525parseOk = parseString( "PUBLIC" );
3526break;
3527 case PubWS:
3528eat_ws();
3529break;
3530 case PubSQ:
3531 case PubDQ:
3532stringClear();
3533next();
3534break;
3535 case PubSQ2:
3536 case PubDQ2:
3537stringAddC();
3538next();
3539break;
3540 case PubE:
3541next();
3542break;
3543 case PubWS2:
3544d->publicId = string();
3545eat_ws();
3546break;
3547 case Done:
3548d->systemId = string();
3549next();
3550break;
3551}
3552// no input is read after this
3553switch ( state ) {
3554 case Sys:
3555if( !parseOk ) {
3556 d->error = XMLERR_UNEXPECTEDCHARACTER;
3557 goto parseError;
3558}
3559break;
3560 case Pub:
3561if( !parseOk ) {
3562 d->error = XMLERR_UNEXPECTEDCHARACTER;
3563 goto parseError;
3564}
3565break;
3566 case PDone:
3567if ( allowPublicID ) {
3568 d->publicId = string();
3569 return TRUE;
3570} else {
3571 d->error = XMLERR_UNEXPECTEDCHARACTER;
3572 goto parseError;
3573}
3574break;
3575 case Done:
3576return TRUE;
3577 case -1:
3578// Error
3579d->error = XMLERR_UNEXPECTEDCHARACTER;
3580goto parseError;
3581}
3582
3583 }
3584
3585 return TRUE;
3586
3587parseError:
3588 reportParseError();
3589 return FALSE;
3590}
3591
3592/*!
3593 Parse a markupdecl [29].
3594*/
3595bool QXmlSimpleReader::parseMarkupdecl()
3596{
3597 const signed char Init = 0;
3598 const signed char Lt = 1; // < was read
3599 const signed char Em = 2; // ! was read
3600 const signed char CE = 3; // E was read
3601 const signed char Qm = 4; // ? was read
3602 const signed char Dash = 5; // - was read
3603 const signed char CA = 6; // A was read
3604 const signed char CEL = 7; // EL was read
3605 const signed char CEN = 8; // EN was read
3606 const signed char CN = 9; // N was read
3607 const signed char Done = 10;
3608
3609 const signed char InpLt = 0; // <
3610 const signed char InpQm = 1; // ?
3611 const signed char InpEm = 2; // !
3612 const signed char InpDash = 3; // -
3613 const signed char InpA = 4; // A
3614 const signed char InpE = 5; // E
3615 const signed char InpL = 6; // L
3616 const signed char InpN = 7; // N
3617 const signed char InpUnknown = 8;
3618
3619 // use some kind of state machine for parsing
3620 static signed char table[4][9] = {
3621 /* InpLt InpQm InpEm InpDash InpA InpE InpL InpN InpUnknown */
3622{ Lt, -1, -1, -1, -1, -1, -1, -1, -1 }, // Init
3623{ -1, Qm, Em, -1, -1, -1, -1, -1, -1 }, // Lt
3624{ -1, -1, -1, Dash, CA, CE, -1, CN, -1 }, // Em
3625{ -1, -1, -1, -1, -1, -1, CEL, CEN, -1 } // CE
3626 };
3627 signed char state = Init;
3628 signed char input;
3629 bool parseOk = TRUE;
3630
3631 while ( TRUE ) {
3632
3633// get input
3634if ( atEnd() ) {
3635 d->error = XMLERR_UNEXPECTEDEOF;
3636 goto parseError;
3637}
3638if ( c == '<' ) {
3639 input = InpLt;
3640} else if ( c == '?' ) {
3641 input = InpQm;
3642} else if ( c == '!' ) {
3643 input = InpEm;
3644} else if ( c == '-' ) {
3645 input = InpDash;
3646} else if ( c == 'A' ) {
3647 input = InpA;
3648} else if ( c == 'E' ) {
3649 input = InpE;
3650} else if ( c == 'L' ) {
3651 input = InpL;
3652} else if ( c == 'N' ) {
3653 input = InpN;
3654} else {
3655 input = InpUnknown;
3656}
3657
3658// set state according to input
3659state = table[state][input];
3660
3661// do some actions according to state
3662switch ( state ) {
3663 case Lt:
3664next();
3665break;
3666 case Em:
3667next();
3668break;
3669 case CE:
3670next();
3671break;
3672 case Qm:
3673parseOk = parsePI();
3674break;
3675 case Dash:
3676parseOk = parseComment();
3677break;
3678 case CA:
3679parseOk = parseAttlistDecl();
3680break;
3681 case CEL:
3682parseOk = parseElementDecl();
3683break;
3684 case CEN:
3685parseOk = parseEntityDecl();
3686break;
3687 case CN:
3688parseOk = parseNotationDecl();
3689break;
3690}
3691// no input is read after this
3692switch ( state ) {
3693 case Qm:
3694if ( !parseOk ) {
3695 d->error = XMLERR_ERRORPARSINGPI;
3696 goto parseError;
3697}
3698if ( contentHnd ) {
3699 if ( !contentHnd->processingInstruction(name(),string()) ) {
3700d->error = contentHnd->errorString();
3701goto parseError;
3702 }
3703}
3704return TRUE;
3705 case Dash:
3706if ( !parseOk ) {
3707 d->error = XMLERR_ERRORPARSINGCOMMENT;
3708 goto parseError;
3709}
3710if ( lexicalHnd ) {
3711 if ( !lexicalHnd->comment( string() ) ) {
3712d->error = lexicalHnd->errorString();
3713goto parseError;
3714 }
3715}
3716return TRUE;
3717 case CA:
3718if ( !parseOk ) {
3719 d->error = XMLERR_ERRORPARSINGATTLISTDECL;
3720 goto parseError;
3721}
3722return TRUE;
3723 case CEL:
3724if ( !parseOk ) {
3725 d->error = XMLERR_ERRORPARSINGELEMENTDECL;
3726 goto parseError;
3727}
3728return TRUE;
3729 case CEN:
3730if ( !parseOk ) {
3731 d->error = XMLERR_ERRORPARSINGENTITYDECL;
3732 goto parseError;
3733}
3734return TRUE;
3735 case CN:
3736if ( !parseOk ) {
3737 d->error = XMLERR_ERRORPARSINGNOTATIONDECL;
3738 goto parseError;
3739}
3740return TRUE;
3741 case Done:
3742return TRUE;
3743 case -1:
3744// Error
3745d->error = XMLERR_LETTEREXPECTED;
3746goto parseError;
3747}
3748
3749 }
3750
3751 return TRUE;
3752
3753parseError:
3754 reportParseError();
3755 return FALSE;
3756}
3757
3758/*!
3759 Parse a PEReference [69]
3760*/
3761bool QXmlSimpleReader::parsePEReference( EntityRecognitionContext context )
3762{
3763 const signed char Init = 0;
3764 const signed char Next = 1;
3765 const signed char Name = 2;
3766 const signed char Done = 3;
3767
3768 const signed char InpSemi = 0; // ;
3769 const signed char InpPer = 1; // %
3770 const signed char InpUnknown = 2;
3771
3772 // use some kind of state machine for parsing
3773 static signed char table[3][3] = {
3774 /* InpSemi InpPer InpUnknown */
3775{ -1, Next, -1 }, // Init
3776{ -1, -1, Name }, // Next
3777{ Done, -1, -1 } // Name
3778 };
3779 signed char state = Init;
3780 signed char input;
3781 bool parseOk = TRUE;
3782
3783 while ( TRUE ) {
3784
3785// get input
3786if ( atEnd() ) {
3787 d->error = XMLERR_UNEXPECTEDEOF;
3788 goto parseError;
3789}
3790if ( c == ';' ) {
3791 input = InpSemi;
3792} else if ( c == '%' ) {
3793 input = InpPer;
3794} else {
3795 input = InpUnknown;
3796}
3797
3798// set state according to input
3799state = table[state][input];
3800
3801// do some actions according to state
3802switch ( state ) {
3803 case Next:
3804next();
3805break;
3806 case Name:
3807parseOk = parseName( TRUE );
3808break;
3809 case Done:
3810next();
3811break;
3812}
3813// no input is read after this
3814switch ( state ) {
3815 case Name:
3816if ( !parseOk ) {
3817 d->error = XMLERR_ERRORPARSINGNAME;
3818 goto parseError;
3819}
3820if ( d->parameterEntities.find( ref() ) == d->parameterEntities.end() ) {
3821 // ### skip it???
3822 if ( contentHnd ) {
3823if ( !contentHnd->skippedEntity( QString("%") + ref() ) ) {
3824 d->error = contentHnd->errorString();
3825 goto parseError;
3826}
3827 }
3828} else {
3829 if ( context == InEntityValue ) {
3830// Included in literal
3831xmlRef = d->parameterEntities.find( ref() )
3832 .data().replace( QRegExp("\""), "&quot;" ).replace( QRegExp("'"), "&apos;" )
3833 + xmlRef;
3834 } else if ( context == InDTD ) {
3835// Included as PE
3836xmlRef = QString(" ") +
3837 d->parameterEntities.find( ref() ).data() +
3838 QString(" ") + xmlRef;
3839 }
3840}
3841break;
3842 case Done:
3843return TRUE;
3844 case -1:
3845// Error
3846d->error = XMLERR_LETTEREXPECTED;
3847goto parseError;
3848}
3849
3850 }
3851
3852 return TRUE;
3853
3854parseError:
3855 reportParseError();
3856 return FALSE;
3857}
3858
3859/*!
3860 Parse a AttlistDecl [52].
3861
3862 Precondition: the beginning '<!' is already read and the head
3863 stands on the 'A' of '<!ATTLIST'
3864*/
3865bool QXmlSimpleReader::parseAttlistDecl()
3866{
3867 const signed char Init = 0;
3868 const signed char Attlist = 1; // parse the string "ATTLIST"
3869 const signed char Ws = 2; // whitespace read
3870 const signed char Name = 3; // parse name
3871 const signed char Ws1 = 4; // whitespace read
3872 const signed char Attdef = 5; // parse the AttDef
3873 const signed char Ws2 = 6; // whitespace read
3874 const signed char Atttype = 7; // parse the AttType
3875 const signed char Ws3 = 8; // whitespace read
3876 const signed char DDecH = 9; // DefaultDecl with #
3877 const signed char DefReq = 10; // parse the string "REQUIRED"
3878 const signed char DefImp = 11; // parse the string "IMPLIED"
3879 const signed char DefFix = 12; // parse the string "FIXED"
3880 const signed char Attval = 13; // parse the AttValue
3881 const signed char Ws4 = 14; // whitespace read
3882 const signed char Done = 15;
3883
3884 const signed char InpWs = 0; // white space
3885 const signed char InpGt = 1; // >
3886 const signed char InpHash = 2; // #
3887 const signed char InpA = 3; // A
3888 const signed char InpI = 4; // I
3889 const signed char InpF = 5; // F
3890 const signed char InpR = 6; // R
3891 const signed char InpUnknown = 7;
3892
3893 // use some kind of state machine for parsing
3894 static signed char table[15][8] = {
3895 /* InpWs InpGt InpHash InpA InpI InpF InpR InpUnknown */
3896{ -1, -1, -1, Attlist, -1, -1, -1, -1 }, // Init
3897{ Ws, -1, -1, -1, -1, -1, -1, -1 }, // Attlist
3898{ -1, -1, -1, Name, Name, Name, Name, Name }, // Ws
3899{ Ws1, Done, Attdef, Attdef, Attdef, Attdef, Attdef, Attdef }, // Name
3900{ -1, Done, Attdef, Attdef, Attdef, Attdef, Attdef, Attdef }, // Ws1
3901{ Ws2, -1, -1, -1, -1, -1, -1, -1 }, // Attdef
3902{ -1, Atttype, Atttype, Atttype, Atttype, Atttype, Atttype, Atttype }, // Ws2
3903{ Ws3, -1, -1, -1, -1, -1, -1, -1 }, // Attype
3904{ -1, Attval, DDecH, Attval, Attval, Attval, Attval, Attval }, // Ws3
3905{ -1, -1, -1, -1, DefImp, DefFix, DefReq, -1 }, // DDecH
3906{ Ws4, Ws4, -1, -1, -1, -1, -1, -1 }, // DefReq
3907{ Ws4, Ws4, -1, -1, -1, -1, -1, -1 }, // DefImp
3908{ Ws3, -1, -1, -1, -1, -1, -1, -1 }, // DefFix
3909{ Ws4, Ws4, -1, -1, -1, -1, -1, -1 }, // Attval
3910{ -1, Done, Attdef, Attdef, Attdef, Attdef, Attdef, Attdef } // Ws4
3911 };
3912 signed char state = Init;
3913 signed char input;
3914 bool parseOk = TRUE;
3915
3916 while ( TRUE ) {
3917
3918// get input
3919if ( atEnd() ) {
3920 d->error = XMLERR_UNEXPECTEDEOF;
3921 goto parseError;
3922}
3923if ( is_S(c) ) {
3924 input = InpWs;
3925} else if ( c == '>' ) {
3926 input = InpGt;
3927} else if ( c == '#' ) {
3928 input = InpHash;
3929} else if ( c == 'A' ) {
3930 input = InpA;
3931} else if ( c == 'I' ) {
3932 input = InpI;
3933} else if ( c == 'F' ) {
3934 input = InpF;
3935} else if ( c == 'R' ) {
3936 input = InpR;
3937} else {
3938 input = InpUnknown;
3939}
3940
3941// set state according to input
3942state = table[state][input];
3943
3944// do some actions according to state
3945switch ( state ) {
3946 case Attlist:
3947parseOk = parseString( "ATTLIST" );
3948break;
3949 case Ws:
3950 case Ws1:
3951 case Ws2:
3952 case Ws3:
3953eat_ws();
3954break;
3955 case Name:
3956parseOk = parseName();
3957break;
3958 case Attdef:
3959parseOk = parseName();
3960break;
3961 case Atttype:
3962parseOk = parseAttType();
3963break;
3964 case DDecH:
3965next();
3966break;
3967 case DefReq:
3968parseOk = parseString( "REQUIRED" );
3969break;
3970 case DefImp:
3971parseOk = parseString( "IMPLIED" );
3972break;
3973 case DefFix:
3974parseOk = parseString( "FIXED" );
3975break;
3976 case Attval:
3977parseOk = parseAttValue();
3978break;
3979 case Ws4:
3980if ( declHnd ) {
3981 // TODO: not all values are computed yet...
3982 if ( !declHnd->attributeDecl( d->attDeclEName, d->attDeclAName, "", "", "" ) ) {
3983d->error = declHnd->errorString();
3984goto parseError;
3985 }
3986}
3987eat_ws();
3988break;
3989 case Done:
3990next();
3991break;
3992}
3993// no input is read after this
3994switch ( state ) {
3995 case Attlist:
3996if( !parseOk ) {
3997 d->error = XMLERR_UNEXPECTEDCHARACTER;
3998 goto parseError;
3999}
4000break;
4001 case Name:
4002if ( !parseOk ) {
4003 d->error = XMLERR_ERRORPARSINGNAME;
4004 goto parseError;
4005}
4006d->attDeclEName = name();
4007break;
4008 case Attdef:
4009if ( !parseOk ) {
4010 d->error = XMLERR_ERRORPARSINGNAME;
4011 goto parseError;
4012}
4013d->attDeclAName = name();
4014break;
4015 case Atttype:
4016if ( !parseOk ) {
4017 d->error = XMLERR_ERRORPARSINGATTTYPE;
4018 goto parseError;
4019}
4020break;
4021 case DefReq:
4022if( !parseOk ) {
4023 d->error = XMLERR_UNEXPECTEDCHARACTER;
4024 goto parseError;
4025}
4026break;
4027 case DefImp:
4028if( !parseOk ) {
4029 d->error = XMLERR_UNEXPECTEDCHARACTER;
4030 goto parseError;
4031}
4032break;
4033 case DefFix:
4034if( !parseOk ) {
4035 d->error = XMLERR_UNEXPECTEDCHARACTER;
4036 goto parseError;
4037}
4038break;
4039 case Attval:
4040if ( !parseOk ) {
4041 d->error = XMLERR_ERRORPARSINGATTVALUE;
4042 goto parseError;
4043}
4044break;
4045 case Done:
4046return TRUE;
4047 case -1:
4048// Error
4049d->error = XMLERR_LETTEREXPECTED;
4050goto parseError;
4051}
4052
4053 }
4054
4055 return TRUE;
4056
4057parseError:
4058 reportParseError();
4059 return FALSE;
4060}
4061
4062/*!
4063 Parse a AttType [54]
4064*/
4065bool QXmlSimpleReader::parseAttType()
4066{
4067 const signed char Init = 0;
4068 const signed char ST = 1; // StringType
4069 const signed char TTI = 2; // TokenizedType starting with 'I'
4070 const signed char TTI2 = 3; // TokenizedType helpstate
4071 const signed char TTI3 = 4; // TokenizedType helpstate
4072 const signed char TTE = 5; // TokenizedType starting with 'E'
4073 const signed char TTEY = 6; // TokenizedType starting with 'ENTITY'
4074 const signed char TTEI = 7; // TokenizedType starting with 'ENTITI'
4075 const signed char N = 8; // N read (TokenizedType or Notation)
4076 const signed char TTNM = 9; // TokenizedType starting with 'NM'
4077 const signed char TTNM2 = 10; // TokenizedType helpstate
4078 const signed char NO = 11; // Notation
4079 const signed char NO2 = 12; // Notation helpstate
4080 const signed char NO3 = 13; // Notation helpstate
4081 const signed char NOName = 14; // Notation, read name
4082 const signed char NO4 = 15; // Notation helpstate
4083 const signed char EN = 16; // Enumeration
4084 const signed char ENNmt = 17; // Enumeration, read Nmtoken
4085 const signed char EN2 = 18; // Enumeration helpstate
4086 const signed char ADone = 19; // almost done (make next and accept)
4087 const signed char Done = 20;
4088
4089 const signed char InpWs = 0; // whitespace
4090 const signed char InpOp = 1; // (
4091 const signed char InpCp = 2; // )
4092 const signed char InpPipe = 3; // |
4093 const signed char InpC = 4; // C
4094 const signed char InpE = 5; // E
4095 const signed char InpI = 6; // I
4096 const signed char InpM = 7; // M
4097 const signed char InpN = 8; // N
4098 const signed char InpO = 9; // O
4099 const signed char InpR = 10; // R
4100 const signed char InpS = 11; // S
4101 const signed char InpY = 12; // Y
4102 const signed char InpUnknown = 13;
4103
4104 // use some kind of state machine for parsing
4105 static signed char table[19][14] = {
4106 /* InpWs InpOp InpCp InpPipe InpC InpE InpI InpM InpN InpO InpR InpS InpY InpUnknown */
4107{ -1, EN, -1, -1, ST, TTE, TTI, -1, N, -1, -1, -1, -1, -1 }, // Init
4108{ Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // ST
4109{ Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, TTI2, Done, Done, Done }, // TTI
4110{ Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, TTI3, Done, Done }, // TTI2
4111{ Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTI3
4112{ -1, -1, -1, -1, -1, -1, TTEI, -1, -1, -1, -1, -1, TTEY, -1 }, // TTE
4113{ Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTEY
4114{ Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTEI
4115{ -1, -1, -1, -1, -1, -1, -1, TTNM, -1, NO, -1, -1, -1, -1 }, // N
4116{ Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, TTNM2, Done, Done }, // TTNM
4117{ Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done, Done }, // TTNM2
4118{ NO2, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NO
4119{ -1, NO3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NO2
4120{ NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName, NOName }, // NO3
4121{ NO4, -1, ADone, NO3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NOName
4122{ -1, -1, ADone, NO3, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // NO4
4123{ -1, -1, ENNmt, -1, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt, ENNmt }, // EN
4124{ EN2, -1, ADone, EN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, // ENNmt
4125{ -1, -1, ADone, EN, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } // EN2
4126 };
4127 signed char state = Init;
4128 signed char input;
4129 bool parseOk = TRUE;
4130
4131 while ( TRUE ) {
4132
4133// get input
4134if ( atEnd() ) {
4135 d->error = XMLERR_UNEXPECTEDEOF;
4136 goto parseError;
4137}
4138if ( is_S(c) ) {
4139 input = InpWs;
4140} else if ( c == '(' ) {
4141 input = InpOp;
4142} else if ( c == ')' ) {
4143 input = InpCp;
4144} else if ( c == '|' ) {
4145 input = InpPipe;
4146} else if ( c == 'C' ) {
4147 input = InpC;
4148} else if ( c == 'E' ) {
4149 input = InpE;
4150} else if ( c == 'I' ) {
4151 input = InpI;
4152} else if ( c == 'M' ) {
4153 input = InpM;
4154} else if ( c == 'N' ) {
4155 input = InpN;
4156} else if ( c == 'O' ) {
4157 input = InpO;
4158} else if ( c == 'R' ) {
4159 input = InpR;
4160} else if ( c == 'S' ) {
4161 input = InpS;
4162} else if ( c == 'Y' ) {
4163 input = InpY;
4164} else {
4165 input = InpUnknown;
4166}
4167
4168// set state according to input
4169state = table[state][input];
4170
4171// do some actions according to state
4172switch ( state ) {
4173 case ST:
4174parseOk = parseString( "CDATA" );
4175break;
4176 case TTI:
4177parseOk = parseString( "ID" );
4178break;
4179 case TTI2:
4180parseOk = parseString( "REF" );
4181break;
4182 case TTI3:
4183next(); // S
4184break;
4185 case TTE:
4186parseOk = parseString( "ENTIT" );
4187break;
4188 case TTEY:
4189next(); // Y
4190break;
4191 case TTEI:
4192parseOk = parseString( "IES" );
4193break;
4194 case N:
4195next(); // N
4196break;
4197 case TTNM:
4198parseOk = parseString( "MTOKEN" );
4199break;
4200 case TTNM2:
4201next(); // S
4202break;
4203 case NO:
4204parseOk = parseString( "OTATION" );
4205break;
4206 case NO2:
4207eat_ws();
4208break;
4209 case NO3:
4210next_eat_ws();
4211break;
4212 case NOName:
4213parseOk = parseName();
4214break;
4215 case NO4:
4216eat_ws();
4217break;
4218 case EN:
4219next_eat_ws();
4220break;
4221 case ENNmt:
4222parseOk = parseNmtoken();
4223break;
4224 case EN2:
4225eat_ws();
4226break;
4227 case ADone:
4228next();
4229break;
4230}
4231// no input is read after this
4232switch ( state ) {
4233 case ST:
4234if( !parseOk ) {
4235 d->error = XMLERR_UNEXPECTEDCHARACTER;
4236 goto parseError;
4237}
4238break;
4239 case TTI:
4240if( !parseOk ) {
4241 d->error = XMLERR_UNEXPECTEDCHARACTER;
4242 goto parseError;
4243}
4244break;
4245 case TTI2:
4246if( !parseOk ) {
4247 d->error = XMLERR_UNEXPECTEDCHARACTER;
4248 goto parseError;
4249}
4250break;
4251 case TTE:
4252if( !parseOk ) {
4253 d->error = XMLERR_UNEXPECTEDCHARACTER;
4254 goto parseError;
4255}
4256break;
4257 case TTEI:
4258if( !parseOk ) {
4259 d->error = XMLERR_UNEXPECTEDCHARACTER;
4260 goto parseError;
4261}
4262break;
4263 case TTNM:
4264if( !parseOk ) {
4265 d->error = XMLERR_UNEXPECTEDCHARACTER;
4266 goto parseError;
4267}
4268break;
4269 case NO:
4270if( !parseOk ) {
4271 d->error = XMLERR_UNEXPECTEDCHARACTER;
4272 goto parseError;
4273}
4274break;
4275 case NOName:
4276if ( !parseOk ) {
4277 d->error = XMLERR_ERRORPARSINGNAME;
4278 goto parseError;
4279}
4280break;
4281 case ENNmt:
4282if ( !parseOk ) {
4283 d->error = XMLERR_ERRORPARSINGNMTOKEN;
4284 goto parseError;
4285}
4286break;
4287 case ADone:
4288return TRUE;
4289 case Done:
4290return TRUE;
4291 case -1:
4292// Error
4293d->error = XMLERR_LETTEREXPECTED;
4294goto parseError;
4295}
4296
4297 }
4298
4299 return TRUE;
4300
4301parseError:
4302 reportParseError();
4303 return FALSE;
4304}
4305
4306/*!
4307 Parse a AttValue [10]
4308
4309 Precondition: the head stands on the beginning " or '
4310
4311 If this function was successful, the head stands on the first
4312 character after the closing " or ' and the value of the attribute
4313 is in string().
4314*/
4315bool QXmlSimpleReader::parseAttValue()
4316{
4317 bool tmp;
4318
4319 const signed char Init = 0;
4320 const signed char Dq = 1; // double quotes were read
4321 const signed char DqRef = 2; // read references in double quotes
4322 const signed char DqC = 3; // signed character read in double quotes
4323 const signed char Sq = 4; // single quotes were read
4324 const signed char SqRef = 5; // read references in single quotes
4325 const signed char SqC = 6; // signed character read in single quotes
4326 const signed char Done = 7;
4327
4328 const signed char InpDq = 0; // "
4329 const signed char InpSq = 1; // '
4330 const signed char InpAmp = 2; // &
4331 const signed char InpLt = 3; // <
4332 const signed char InpUnknown = 4;
4333
4334 // use some kind of state machine for parsing
4335 static signed char table[7][5] = {
4336 /* InpDq InpSq InpAmp InpLt InpUnknown */
4337{ Dq, Sq, -1, -1, -1 }, // Init
4338{ Done, DqC, DqRef, -1, DqC }, // Dq
4339{ Done, DqC, DqRef, -1, DqC }, // DqRef
4340{ Done, DqC, DqRef, -1, DqC }, // DqC
4341{ SqC, Done, SqRef, -1, SqC }, // Sq
4342{ SqC, Done, SqRef, -1, SqC }, // SqRef
4343{ SqC, Done, SqRef, -1, SqC } // SqRef
4344 };
4345 signed char state = Init;
4346 signed char input;
4347 bool parseOk = TRUE;
4348
4349 while ( TRUE ) {
4350
4351// get input
4352if ( atEnd() ) {
4353 d->error = XMLERR_UNEXPECTEDEOF;
4354 goto parseError;
4355}
4356if ( c == '"' ) {
4357 input = InpDq;
4358} else if ( c == '\'' ) {
4359 input = InpSq;
4360} else if ( c == '&' ) {
4361 input = InpAmp;
4362} else if ( c == '<' ) {
4363 input = InpLt;
4364} else {
4365 input = InpUnknown;
4366}
4367
4368// set state according to input
4369state = table[state][input];
4370
4371// do some actions according to state
4372switch ( state ) {
4373 case Dq:
4374 case Sq:
4375stringClear();
4376next();
4377break;
4378 case DqRef:
4379 case SqRef:
4380parseOk = parseReference( tmp, InAttributeValue );
4381break;
4382 case DqC:
4383 case SqC:
4384stringAddC();
4385next();
4386break;
4387 case Done:
4388next();
4389break;
4390}
4391// no input is read after this
4392switch ( state ) {
4393 case DqRef:
4394 case SqRef:
4395if ( !parseOk ) {
4396 d->error = XMLERR_ERRORPARSINGREFERENCE;
4397 goto parseError;
4398}
4399break;
4400 case Done:
4401return TRUE;
4402 case -1:
4403// Error
4404d->error = XMLERR_UNEXPECTEDCHARACTER;
4405goto parseError;
4406}
4407
4408 }
4409
4410 return TRUE;
4411
4412parseError:
4413 reportParseError();
4414 return FALSE;
4415}
4416
4417/*!
4418 Parse a elementdecl [45].
4419
4420 Precondition: the beginning '<!E' is already read and the head
4421 stands on the 'L' of '<!ELEMENT'
4422*/
4423bool QXmlSimpleReader::parseElementDecl()
4424{
4425 const signed char Init = 0;
4426 const signed char Elem = 1; // parse the beginning string
4427 const signed char Ws1 = 2; // whitespace required
4428 const signed char Nam = 3; // parse Name
4429 const signed char Ws2 = 4; // whitespace required
4430 const signed char Empty = 5; // read EMPTY
4431 const signed char Any = 6; // read ANY
4432 const signed char Cont = 7; // read contentspec (except ANY or EMPTY)
4433 const signed char Mix = 8; // read Mixed
4434 const signed char Mix2 = 9; //
4435 const signed char Mix3 = 10; //
4436 const signed char MixN1 = 11; //
4437 const signed char MixN2 = 12; //
4438 const signed char MixN3 = 13; //
4439 const signed char MixN4 = 14; //
4440 const signed char Cp = 15; // parse cp
4441 const signed char Cp2 = 16; //
4442 const signed char WsD = 17; // eat whitespace before Done
4443 const signed char Done = 18;
4444
4445 const signed char InpWs = 0;
4446 const signed char InpGt = 1; // >
4447 const signed char InpPipe = 2; // |
4448 const signed char InpOp = 3; // (
4449 const signed char InpCp = 4; // )
4450 const signed char InpHash = 5; // #
4451 const signed char InpQm = 6; // ?
4452 const signed char InpAst = 7; // *
4453 const signed char InpPlus = 8; // +
4454 const signed char InpA = 9; // A
4455 const signed char InpE = 10; // E