From 058d993611b697e7cb25536535ba679d1fc347d6 Mon Sep 17 00:00:00 2001 From: Ievgenii Meshcheriakov Date: Tue, 27 Jun 2023 14:07:37 +0200 Subject: [PATCH] QDBusXmlParser: Make parser functions members of the class Also make QXmlStreamReader instance and the current interface members of the class. This reduces amount of arguments that need to be passed arounds. Task-number: QTBUG-2597 Change-Id: Iebd2db98a34019923b7a4fe198cc081cd010c8a3 Reviewed-by: Qt CI Bot Reviewed-by: Thiago Macieira --- src/dbus/qdbusxmlparser.cpp | 257 ++++++++++++++++++------------------ src/dbus/qdbusxmlparser_p.h | 13 ++ 2 files changed, 141 insertions(+), 129 deletions(-) diff --git a/src/dbus/qdbusxmlparser.cpp b/src/dbus/qdbusxmlparser.cpp index 509ca6e77c..4685fe4ac4 100644 --- a/src/dbus/qdbusxmlparser.cpp +++ b/src/dbus/qdbusxmlparser.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include #ifndef QT_NO_DBUS @@ -20,9 +19,11 @@ Q_LOGGING_CATEGORY(dbusParser, "dbus.parser", QtWarningMsg) #define qDBusParserError(...) qCDebug(dbusParser, ##__VA_ARGS__) -static bool parseArg(const QXmlStreamAttributes &attributes, QDBusIntrospection::Argument &argData, - QDBusIntrospection::Interface *ifaceData) +bool QDBusXmlParser::parseArg(const QXmlStreamAttributes &attributes, + QDBusIntrospection::Argument &argData) { + Q_ASSERT(m_currentInterface); + const QString argType = attributes.value("type"_L1).toString(); bool ok = QDBusUtil::isValidSingleSignature(argType); @@ -34,25 +35,26 @@ static bool parseArg(const QXmlStreamAttributes &attributes, QDBusIntrospection: argData.name = attributes.value("name"_L1).toString(); argData.type = argType; - ifaceData->introspection += " introspection += " introspection += " direction=\""_L1 + direction + u'"'; + m_currentInterface->introspection += " direction=\""_L1 + direction + u'"'; } - ifaceData->introspection += " type=\""_L1 + argData.type + u'"'; + m_currentInterface->introspection += " type=\""_L1 + argData.type + u'"'; if (!argData.name.isEmpty()) - ifaceData->introspection += " name=\""_L1 + argData.name + u'"'; - ifaceData->introspection += "/>\n"_L1; + m_currentInterface->introspection += " name=\""_L1 + argData.name + u'"'; + m_currentInterface->introspection += "/>\n"_L1; return ok; } -static bool parseAnnotation(const QXmlStreamReader &xml, QDBusIntrospection::Annotations &annotations, - QDBusIntrospection::Interface *ifaceData, bool interfaceAnnotation = false) +bool QDBusXmlParser::parseAnnotation(QDBusIntrospection::Annotations &annotations, + bool interfaceAnnotation) { - Q_ASSERT(xml.isStartElement() && xml.name() == "annotation"_L1); + Q_ASSERT(m_currentInterface); + Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "annotation"_L1); - const QXmlStreamAttributes attributes = xml.attributes(); + const QXmlStreamAttributes attributes = m_xml.attributes(); const QString name = attributes.value("name"_L1).toString(); if (!QDBusUtil::isValidInterfaceName(name)) { @@ -63,22 +65,22 @@ static bool parseAnnotation(const QXmlStreamReader &xml, QDBusIntrospection::Ann const QString value = attributes.value("value"_L1).toString(); annotations.insert(name, value); if (!interfaceAnnotation) - ifaceData->introspection += " "_L1; - ifaceData->introspection += " \n"_L1; + m_currentInterface->introspection += " "_L1; + m_currentInterface->introspection += " \n"_L1; return true; } -static bool parseProperty(QXmlStreamReader &xml, QDBusIntrospection::Property &propertyData, - QDBusIntrospection::Interface *ifaceData) +bool QDBusXmlParser::parseProperty(QDBusIntrospection::Property &propertyData) { - Q_ASSERT(xml.isStartElement() && xml.name() == "property"_L1); + Q_ASSERT(m_currentInterface); + Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "property"_L1); - QXmlStreamAttributes attributes = xml.attributes(); + QXmlStreamAttributes attributes = m_xml.attributes(); const QString propertyName = attributes.value("name"_L1).toString(); if (!QDBusUtil::isValidMemberName(propertyName)) { qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", - qPrintable(propertyName), qPrintable(ifaceData->name)); - xml.skipCurrentElement(); + qPrintable(propertyName), qPrintable(m_currentInterface->name)); + m_xml.skipCurrentElement(); return false; } @@ -89,7 +91,7 @@ static bool parseProperty(QXmlStreamReader &xml, QDBusIntrospection::Property &p if (!QDBusUtil::isValidSingleSignature(propertyData.type)) { // cannot be! qDBusParserError("Invalid D-BUS type signature '%s' found in property '%s.%s' while parsing introspection", - qPrintable(propertyData.type), qPrintable(ifaceData->name), + qPrintable(propertyData.type), qPrintable(m_currentInterface->name), qPrintable(propertyName)); } @@ -102,84 +104,84 @@ static bool parseProperty(QXmlStreamReader &xml, QDBusIntrospection::Property &p propertyData.access = QDBusIntrospection::Property::ReadWrite; else { qDBusParserError("Invalid D-BUS property access '%s' found in property '%s.%s' while parsing introspection", - qPrintable(access), qPrintable(ifaceData->name), + qPrintable(access), qPrintable(m_currentInterface->name), qPrintable(propertyName)); return false; // invalid one! } - ifaceData->introspection += " introspection += " introspection += "/>\n"_L1; + if (!m_xml.readNextStartElement()) { + m_currentInterface->introspection += "/>\n"_L1; } else { - ifaceData->introspection += ">\n"_L1; + m_currentInterface->introspection += ">\n"_L1; do { - if (xml.name() == "annotation"_L1) { - parseAnnotation(xml, propertyData.annotations, ifaceData); - } else if (xml.prefix().isEmpty()) { - qDBusParserError() << "Unknown element" << xml.name() << "while checking for annotations"; + if (m_xml.name() == "annotation"_L1) { + parseAnnotation(propertyData.annotations); + } else if (m_xml.prefix().isEmpty()) { + qDBusParserError() << "Unknown element" << m_xml.name() << "while checking for annotations"; } - xml.skipCurrentElement(); - } while (xml.readNextStartElement()); + m_xml.skipCurrentElement(); + } while (m_xml.readNextStartElement()); - ifaceData->introspection += " \n"_L1; + m_currentInterface->introspection += " \n"_L1; } - if (!xml.isEndElement() || xml.name() != "property"_L1) { - qDBusParserError() << "Invalid property specification" << xml.tokenString() << xml.name(); + if (!m_xml.isEndElement() || m_xml.name() != "property"_L1) { + qDBusParserError() << "Invalid property specification" << m_xml.tokenString() << m_xml.name(); return false; } return true; } -static bool parseMethod(QXmlStreamReader &xml, QDBusIntrospection::Method &methodData, - QDBusIntrospection::Interface *ifaceData) +bool QDBusXmlParser::parseMethod(QDBusIntrospection::Method &methodData) { - Q_ASSERT(xml.isStartElement() && xml.name() == "method"_L1); + Q_ASSERT(m_currentInterface); + Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "method"_L1); - const QXmlStreamAttributes attributes = xml.attributes(); + const QXmlStreamAttributes attributes = m_xml.attributes(); const QString methodName = attributes.value("name"_L1).toString(); if (!QDBusUtil::isValidMemberName(methodName)) { qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", - qPrintable(methodName), qPrintable(ifaceData->name)); + qPrintable(methodName), qPrintable(m_currentInterface->name)); return false; } methodData.name = methodName; - ifaceData->introspection += " introspection += " introspection += "/>\n"_L1; + if (!m_xml.readNextStartElement()) { + m_currentInterface->introspection += "/>\n"_L1; } else { - ifaceData->introspection += ">\n"_L1; + m_currentInterface->introspection += ">\n"_L1; do { - if (xml.name() == "annotation"_L1) { - parseAnnotation(xml, annotations, ifaceData); - } else if (xml.name() == "arg"_L1) { - const QXmlStreamAttributes attributes = xml.attributes(); + if (m_xml.name() == "annotation"_L1) { + parseAnnotation(annotations); + } else if (m_xml.name() == "arg"_L1) { + const QXmlStreamAttributes attributes = m_xml.attributes(); const QString direction = attributes.value("direction"_L1).toString(); QDBusIntrospection::Argument argument; if (!attributes.hasAttribute("direction"_L1) || direction == "in"_L1) { - parseArg(attributes, argument, ifaceData); + parseArg(attributes, argument); inArguments << argument; } else if (direction == "out"_L1) { - parseArg(attributes, argument, ifaceData); + parseArg(attributes, argument); outArguments << argument; } - } else if (xml.prefix().isEmpty()) { - qDBusParserError() << "Unknown element" << xml.name() << "while checking for method arguments"; + } else if (m_xml.prefix().isEmpty()) { + qDBusParserError() << "Unknown element" << m_xml.name() << "while checking for method arguments"; } - xml.skipCurrentElement(); - } while (xml.readNextStartElement()); + m_xml.skipCurrentElement(); + } while (m_xml.readNextStartElement()); - ifaceData->introspection += " \n"_L1; + m_currentInterface->introspection += " \n"_L1; } methodData.inputArgs = inArguments; @@ -189,50 +191,49 @@ static bool parseMethod(QXmlStreamReader &xml, QDBusIntrospection::Method &metho return true; } - -static bool parseSignal(QXmlStreamReader &xml, QDBusIntrospection::Signal &signalData, - QDBusIntrospection::Interface *ifaceData) +bool QDBusXmlParser::parseSignal(QDBusIntrospection::Signal &signalData) { - Q_ASSERT(xml.isStartElement() && xml.name() == "signal"_L1); + Q_ASSERT(m_currentInterface); + Q_ASSERT(m_xml.isStartElement() && m_xml.name() == "signal"_L1); - const QXmlStreamAttributes attributes = xml.attributes(); + const QXmlStreamAttributes attributes = m_xml.attributes(); const QString signalName = attributes.value("name"_L1).toString(); if (!QDBusUtil::isValidMemberName(signalName)) { qDBusParserError("Invalid D-BUS member name '%s' found in interface '%s' while parsing introspection", - qPrintable(signalName), qPrintable(ifaceData->name)); + qPrintable(signalName), qPrintable(m_currentInterface->name)); return false; } signalData.name = signalName; - ifaceData->introspection += " introspection += " introspection += "/>\n"_L1; + if (!m_xml.readNextStartElement()) { + m_currentInterface->introspection += "/>\n"_L1; } else { - ifaceData->introspection += ">\n"_L1; + m_currentInterface->introspection += ">\n"_L1; do { - if (xml.name() == "annotation"_L1) { - parseAnnotation(xml, annotations, ifaceData); - } else if (xml.name() == "arg"_L1) { - const QXmlStreamAttributes attributes = xml.attributes(); + if (m_xml.name() == "annotation"_L1) { + parseAnnotation(annotations); + } else if (m_xml.name() == "arg"_L1) { + const QXmlStreamAttributes attributes = m_xml.attributes(); QDBusIntrospection::Argument argument; if (!attributes.hasAttribute("direction"_L1) || attributes.value("direction"_L1) == "out"_L1) { - parseArg(attributes, argument, ifaceData); + parseArg(attributes, argument); arguments << argument; } } else { - qDBusParserError() << "Unknown element" << xml.name() << "while checking for signal arguments"; + qDBusParserError() << "Unknown element" << m_xml.name() << "while checking for signal arguments"; } - xml.skipCurrentElement(); - } while (xml.readNextStartElement()); + m_xml.skipCurrentElement(); + } while (m_xml.readNextStartElement()); - ifaceData->introspection += " \n"_L1; + m_currentInterface->introspection += " \n"_L1; } signalData.outputArgs = arguments; @@ -241,61 +242,64 @@ static bool parseSignal(QXmlStreamReader &xml, QDBusIntrospection::Signal &signa return true; } -static void readInterface(QXmlStreamReader &xml, QDBusIntrospection::Object *objData, - QDBusIntrospection::Interfaces *interfaces) +void QDBusXmlParser::readInterface() { - const QString ifaceName = xml.attributes().value("name"_L1).toString(); + Q_ASSERT(!m_currentInterface); + + const QString ifaceName = m_xml.attributes().value("name"_L1).toString(); if (!QDBusUtil::isValidInterfaceName(ifaceName)) { qDBusParserError("Invalid D-BUS interface name '%s' found while parsing introspection", qPrintable(ifaceName)); return; } - objData->interfaces.append(ifaceName); + m_object->interfaces.append(ifaceName); - QDBusIntrospection::Interface *ifaceData = new QDBusIntrospection::Interface; - ifaceData->name = ifaceName; - ifaceData->introspection += " \n"_L1; + m_currentInterface = std::make_unique(); + m_currentInterface->name = ifaceName; + m_currentInterface->introspection += " \n"_L1; - while (xml.readNextStartElement()) { - if (xml.name() == "method"_L1) { + while (m_xml.readNextStartElement()) { + if (m_xml.name() == "method"_L1) { QDBusIntrospection::Method methodData; - if (parseMethod(xml, methodData, ifaceData)) - ifaceData->methods.insert(methodData.name, methodData); - } else if (xml.name() == "signal"_L1) { + if (parseMethod(methodData)) + m_currentInterface->methods.insert(methodData.name, methodData); + } else if (m_xml.name() == "signal"_L1) { QDBusIntrospection::Signal signalData; - if (parseSignal(xml, signalData, ifaceData)) - ifaceData->signals_.insert(signalData.name, signalData); - } else if (xml.name() == "property"_L1) { + if (parseSignal(signalData)) + m_currentInterface->signals_.insert(signalData.name, signalData); + } else if (m_xml.name() == "property"_L1) { QDBusIntrospection::Property propertyData; - if (parseProperty(xml, propertyData, ifaceData)) - ifaceData->properties.insert(propertyData.name, propertyData); - } else if (xml.name() == "annotation"_L1) { - parseAnnotation(xml, ifaceData->annotations, ifaceData, true); - xml.skipCurrentElement(); // skip over annotation object + if (parseProperty(propertyData)) + m_currentInterface->properties.insert(propertyData.name, propertyData); + } else if (m_xml.name() == "annotation"_L1) { + parseAnnotation(m_currentInterface->annotations, true); + m_xml.skipCurrentElement(); // skip over annotation object } else { - if (xml.prefix().isEmpty()) { - qDBusParserError() << "Unknown element while parsing interface" << xml.name(); + if (m_xml.prefix().isEmpty()) { + qDBusParserError() << "Unknown element while parsing interface" << m_xml.name(); } - xml.skipCurrentElement(); + m_xml.skipCurrentElement(); } } - ifaceData->introspection += " "_L1; + m_currentInterface->introspection += " "_L1; - interfaces->insert(ifaceName, QSharedDataPointer(ifaceData)); + m_interfaces.insert( + ifaceName, + QSharedDataPointer(m_currentInterface.release())); - if (!xml.isEndElement() || xml.name() != "interface"_L1) { + if (!m_xml.isEndElement() || m_xml.name() != "interface"_L1) { qDBusParserError() << "Invalid Interface specification"; } } -static void readNode(const QXmlStreamReader &xml, QDBusIntrospection::Object *objData, int nodeLevel) +void QDBusXmlParser::readNode(int nodeLevel) { - const QString objName = xml.attributes().value("name"_L1).toString(); - const QString fullName = objData->path.endsWith(u'/') - ? (objData->path + objName) - : QString(objData->path + u'/' + objName); + const QString objName = m_xml.attributes().value("name"_L1).toString(); + const QString fullName = m_object->path.endsWith(u'/') + ? (m_object->path + objName) + : QString(m_object->path + u'/' + objName); if (!QDBusUtil::isValidObjectPath(fullName)) { qDBusParserError("Invalid D-BUS object path '%s' found while parsing introspection", qPrintable(fullName)); @@ -303,43 +307,38 @@ static void readNode(const QXmlStreamReader &xml, QDBusIntrospection::Object *ob } if (nodeLevel > 0) - objData->childObjects.append(objName); + m_object->childObjects.append(objName); } -QDBusXmlParser::QDBusXmlParser(const QString& service, const QString& path, - const QString& xmlData) - : m_service(service), m_path(path), m_object(new QDBusIntrospection::Object) +QDBusXmlParser::QDBusXmlParser(const QString &service, const QString &path, const QString &xmlData) + : m_service(service), m_path(path), m_object(new QDBusIntrospection::Object), m_xml(xmlData) { -// qDBusParserError() << "parsing" << xmlData; - m_object->service = m_service; m_object->path = m_path; - QXmlStreamReader xml(xmlData); - int nodeLevel = -1; - while (!xml.atEnd()) { - xml.readNext(); + while (!m_xml.atEnd()) { + m_xml.readNext(); - switch (xml.tokenType()) { + switch (m_xml.tokenType()) { case QXmlStreamReader::StartElement: - if (xml.name() == "node"_L1) { - readNode(xml, m_object, ++nodeLevel); - } else if (xml.name() == "interface"_L1) { - readInterface(xml, m_object, &m_interfaces); + if (m_xml.name() == "node"_L1) { + readNode(++nodeLevel); + } else if (m_xml.name() == "interface"_L1) { + readInterface(); } else { - if (xml.prefix().isEmpty()) { - qDBusParserError() << "skipping unknown element" << xml.name(); + if (m_xml.prefix().isEmpty()) { + qDBusParserError() << "skipping unknown element" << m_xml.name(); } - xml.skipCurrentElement(); + m_xml.skipCurrentElement(); } break; case QXmlStreamReader::EndElement: - if (xml.name() == "node"_L1) { + if (m_xml.name() == "node"_L1) { --nodeLevel; } else { - qDBusParserError() << "Invalid Node declaration" << xml.name(); + qDBusParserError() << "Invalid Node declaration" << m_xml.name(); } break; case QXmlStreamReader::StartDocument: @@ -352,17 +351,17 @@ QDBusXmlParser::QDBusXmlParser(const QString& service, const QString& path, break; case QXmlStreamReader::Characters: // ignore whitespace - if (xml.isWhitespace()) + if (m_xml.isWhitespace()) break; Q_FALLTHROUGH(); default: - qDBusParserError() << "unknown token" << xml.name() << xml.tokenString(); + qDBusParserError() << "unknown token" << m_xml.name() << m_xml.tokenString(); break; } } - if (xml.hasError()) { - qDBusParserError() << "xml error" << xml.errorString() << "doc" << xmlData; + if (m_xml.hasError()) { + qDBusParserError() << "xml error" << m_xml.errorString() << "doc" << xmlData; } } diff --git a/src/dbus/qdbusxmlparser_p.h b/src/dbus/qdbusxmlparser_p.h index db3b289a2a..d91223a70c 100644 --- a/src/dbus/qdbusxmlparser_p.h +++ b/src/dbus/qdbusxmlparser_p.h @@ -18,6 +18,7 @@ #include #include #include +#include #include "qdbusintrospection_p.h" #ifndef QT_NO_DBUS @@ -34,7 +35,9 @@ class QDBusXmlParser QString m_service; QString m_path; QSharedDataPointer m_object; + std::unique_ptr m_currentInterface; QDBusIntrospection::Interfaces m_interfaces; + QXmlStreamReader m_xml; public: QDBusXmlParser(const QString& service, const QString& path, @@ -42,6 +45,16 @@ public: inline QDBusIntrospection::Interfaces interfaces() const { return m_interfaces; } inline QSharedDataPointer object() const { return m_object; } + +private: + void readNode(int nodeLevel); + void readInterface(); + bool parseSignal(QDBusIntrospection::Signal &signalData); + bool parseMethod(QDBusIntrospection::Method &methodData); + bool parseProperty(QDBusIntrospection::Property &propertyData); + bool parseAnnotation(QDBusIntrospection::Annotations &annotations, + bool interfaceAnnotation = false); + bool parseArg(const QXmlStreamAttributes &attributes, QDBusIntrospection::Argument &argData); }; QT_END_NAMESPACE