4848
4949#include < memory>
5050
51- #include < QtXml>
51+ #include < QFile>
52+ #include < QTextStream>
53+ #include < QXmlStreamReader>
5254#include < qcompilerdetection.h> // Q_FALLTHROUGH
5355
54- /* This file needs to be rewritten as documented here:
55- *
56- * See: https://doc.qt.io/qt-6/xml-changes-qt6.html
57- *
58- * The rewrite may be backward compatible to Qt4.3 APIs because the base
59- * facilites (QXmlStreamReader) used to relace the 'SAX' parser were apparently
60- * available then. Use of Xml5Compat is a work round until such a rewrite has
61- * been done.
62- */
63- #if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
64- # if defined(__GNUC__)
65- # pragma GCC warning "Qt6: implement Qt6 compatible XML reading"
66- # endif
67- # include < QtCore5Compat/QXmlDefaultHandler>
68- #endif
69-
7056QString strings_Object = QLatin1String(" Object" );
7157QString strings_String = QLatin1String(" String" );
7258QString strings_Thread = QLatin1String(" Thread" );
@@ -150,9 +136,48 @@ class StackElement
150136 } value;
151137};
152138
153- class Handler : public QXmlDefaultHandler
139+ class Handler
154140{
155141public:
142+ class Attributes
143+ {
144+ public:
145+ Attributes () = default ;
146+ explicit Attributes (const QXmlStreamAttributes &attributes)
147+ : m_attributes(attributes) {}
148+
149+ int length () const { return m_attributes.size (); }
150+
151+ QString localName (int index) const
152+ {
153+ return m_attributes.at (index).name ().toString ();
154+ }
155+
156+ QString value (int index) const
157+ {
158+ return m_attributes.at (index).value ().toString ();
159+ }
160+
161+ QString value (const QString &qualifiedName) const
162+ {
163+ return m_attributes.hasAttribute (qualifiedName)
164+ ? m_attributes.value (qualifiedName).toString ()
165+ : QString ();
166+ }
167+
168+ int index (const QString &qualifiedName) const
169+ {
170+ for (int i = 0 ; i < m_attributes.size (); ++i) {
171+ if (m_attributes.at (i).name ().toString () == qualifiedName)
172+ return i;
173+ }
174+ return -1 ;
175+ }
176+
177+ private:
178+ QXmlStreamAttributes m_attributes;
179+ };
180+
156181 Handler (TypeDatabase *database, unsigned int qtVersion, bool generate)
157182 : m_database(database)
158183 , m_generate(generate ? TypeEntry::GenerateAll : TypeEntry::GenerateForSubclass)
@@ -197,25 +222,23 @@ class Handler : public QXmlDefaultHandler
197222 tagNames[" reference-count" ] = StackElement::ReferenceCount;
198223 }
199224
225+ bool parse (QXmlStreamReader &reader);
200226 bool startDocument () { m_nestingLevel = 0 ; m_disabledLevel = -1 ; return true ; }
201227 bool startElement (const QString &namespaceURI, const QString &localName,
202- const QString &qName, const QXmlAttributes &atts);
228+ const QString &qName, const Attributes &atts);
203229 bool endElement (const QString &namespaceURI, const QString &localName, const QString &qName);
204230
205231 QString errorString () const { return m_error; }
206- bool error (const QXmlParseException &exception);
207- bool fatalError (const QXmlParseException &exception);
208- bool warning (const QXmlParseException &exception);
209232
210233 bool characters (const QString &ch);
211234
212235private:
213- void fetchAttributeValues (const QString &name, const QXmlAttributes &atts,
236+ void fetchAttributeValues (const QString &name, const Attributes &atts,
214237 QHash<QString, QString> *acceptedAttributes);
215238
216- bool importFileElement (const QXmlAttributes &atts);
239+ bool importFileElement (const Attributes &atts);
217240 bool convertBoolean (const QString &, const QString &, bool );
218- bool qtVersionMatches (const QXmlAttributes & atts, bool & ok);
241+ bool qtVersionMatches (const Attributes & atts, bool & ok);
219242
220243 TypeDatabase *m_database;
221244 StackElement* current;
@@ -237,31 +260,55 @@ class Handler : public QXmlDefaultHandler
237260 int m_disabledLevel{}; // if this is != 0, elements should be ignored
238261};
239262
240- bool Handler::error ( const QXmlParseException &e )
263+ bool Handler::parse (QXmlStreamReader &reader )
241264{
242- qWarning () << " Error: line=" << e.lineNumber ()
243- << " , column=" << e.columnNumber ()
244- << " , message=" << e.message () << " \n " ;
245- return false ;
246- }
265+ if (!startDocument ())
266+ return false ;
247267
248- bool Handler::fatalError (const QXmlParseException &e)
249- {
250- qWarning () << " Fatal error: line=" << e.lineNumber ()
251- << " , column=" << e.columnNumber ()
252- << " , message=" << e.message () << " \n " ;
253- return false ;
254- }
268+ while (!reader.atEnd ()) {
269+ const auto token = reader.readNext ();
270+ switch (token) {
271+ case QXmlStreamReader::StartElement: {
272+ Attributes attributes (reader.attributes ());
273+ if (!startElement (reader.namespaceUri ().toString (),
274+ reader.name ().toString (),
275+ reader.qualifiedName ().toString (),
276+ attributes)) {
277+ return false ;
278+ }
279+ break ;
280+ }
281+ case QXmlStreamReader::EndElement:
282+ if (!endElement (reader.namespaceUri ().toString (),
283+ reader.name ().toString (),
284+ reader.qualifiedName ().toString ())) {
285+ return false ;
286+ }
287+ break ;
288+ case QXmlStreamReader::Characters:
289+ case QXmlStreamReader::EntityReference:
290+ if (!characters (reader.text ().toString ())) {
291+ return false ;
292+ }
293+ break ;
294+ default :
295+ break ;
296+ }
297+ }
255298
256- bool Handler::warning (const QXmlParseException &e)
257- {
258- qWarning () << " Warning: line=" << e.lineNumber ()
259- << " , column=" << e.columnNumber ()
260- << " , message=" << e.message () << " \n " ;
261- return false ;
299+ if (reader.hasError ()) {
300+ m_error = QStringLiteral (" Parse error at line %1, column %2: %3" )
301+ .arg (reader.lineNumber ())
302+ .arg (reader.columnNumber ())
303+ .arg (reader.errorString ());
304+ qWarning () << m_error;
305+ return false ;
306+ }
307+
308+ return true ;
262309}
263310
264- void Handler::fetchAttributeValues (const QString &name, const QXmlAttributes &atts,
311+ void Handler::fetchAttributeValues (const QString &name, const Attributes &atts,
265312 QHash<QString, QString> *acceptedAttributes)
266313{
267314 Q_ASSERT (acceptedAttributes != 0 );
@@ -358,6 +405,9 @@ bool Handler::endElement(const QString &, const QString &localName, const QStrin
358405
359406bool Handler::characters (const QString &ch)
360407{
408+ if (!current)
409+ return true ;
410+
361411 if (current->type == StackElement::Template){
362412 current->value .templateEntry ->addCode (ch);
363413 return true ;
@@ -398,7 +448,7 @@ bool Handler::characters(const QString &ch)
398448 return true ;
399449}
400450
401- bool Handler::importFileElement (const QXmlAttributes &atts)
451+ bool Handler::importFileElement (const Attributes &atts)
402452{
403453 QString fileName = atts.value (" name" );
404454 if (fileName.isEmpty ()){
@@ -470,7 +520,7 @@ bool Handler::convertBoolean(const QString &_value, const QString &attributeName
470520 }
471521}
472522
473- bool Handler::qtVersionMatches (const QXmlAttributes & atts, bool & ok)
523+ bool Handler::qtVersionMatches (const Attributes & atts, bool & ok)
474524{
475525 ok = true ;
476526 int beforeIndex = atts.index (" before-version" );
@@ -501,7 +551,7 @@ bool Handler::qtVersionMatches(const QXmlAttributes& atts, bool& ok)
501551}
502552
503553bool Handler::startElement (const QString &, const QString &n,
504- const QString &, const QXmlAttributes &atts)
554+ const QString &, const Attributes &atts)
505555{
506556 QString tagName = n.toLower ();
507557 m_nestingLevel++;
@@ -1601,17 +1651,19 @@ bool TypeDatabase::parseFile(const QString &filename, unsigned int qtVersion, bo
16011651 QFile file (filename);
16021652
16031653 Q_ASSERT (file.exists ());
1604- QXmlInputSource source (&file);
1654+ if (!file.open (QIODevice::ReadOnly | QIODevice::Text)) {
1655+ ReportHandler::warning (QString::fromLatin1 (" Could not open typesystem file: '%1'" ).arg (filename));
1656+ return false ;
1657+ }
16051658
16061659 int count = m_entries.size ();
16071660
1608- QXmlSimpleReader reader;
16091661 Handler handler (this , qtVersion, generate);
1662+ QXmlStreamReader reader (&file);
16101663
1611- reader.setContentHandler (&handler);
1612- reader.setErrorHandler (&handler);
1613-
1614- bool ok = reader.parse (&source, false );
1664+ bool ok = handler.parse (reader);
1665+ if (!ok && !handler.errorString ().isEmpty ())
1666+ ReportHandler::warning (handler.errorString ());
16151667
16161668 int newCount = m_entries.size ();
16171669
0 commit comments