7#include <QtCore/qmap.h>
8#include <QtCore/qvariant.h>
9#include <QtCore/qtextstream.h>
10#include <QtCore/qdebug.h>
20#define qDBusParserWarning(format, ...) \
23 m_reporter->warning(m_currentLocation, format "\n", ##__VA_ARGS__); \
25 qCDebug(dbusParser, "Warning: " format, ##__VA_ARGS__); \
28#define qDBusParserError(format, ...) \
31 m_reporter->error(m_currentLocation, format "\n", ##__VA_ARGS__); \
33 qCDebug(dbusParser, "Error: " format, ##__VA_ARGS__); \
45 qDBusParserError(
"Invalid D-Bus type signature '%s' found while parsing introspection",
50 argData.
type = argType;
52 m_currentInterface->introspection +=
" <arg"_L1;
55 m_currentInterface->introspection +=
" direction=\""_L1 +
direction + u
'"';
57 m_currentInterface->introspection +=
" type=\""_L1 + argData.
type + u
'"';
59 m_currentInterface->introspection +=
" name=\""_L1 + argData.
name + u
'"';
60 m_currentInterface->introspection +=
"/>\n"_L1;
66 bool interfaceAnnotation)
69 Q_ASSERT(m_xml.isStartElement() && m_xml.name() ==
"annotation"_L1);
72 annotation.
location = m_currentLocation;
78 qDBusParserError(
"Invalid D-Bus annotation '%s' found while parsing introspection",
83 annotations.
insert(annotation.
name, annotation);
84 if (!interfaceAnnotation)
85 m_currentInterface->introspection +=
" "_L1;
86 m_currentInterface->introspection +=
" <annotation value=\""_L1
94 Q_ASSERT(m_xml.isStartElement() && m_xml.name() ==
"property"_L1);
99 qDBusParserError(
"Invalid D-Bus member name '%s' found in interface '%s' while parsing "
102 m_xml.skipCurrentElement();
107 propertyData.
name = propertyName;
112 qDBusParserError(
"Invalid D-Bus type signature '%s' found in property '%s.%s' while "
113 "parsing introspection",
121 else if (
access ==
"write"_L1)
123 else if (
access ==
"readwrite"_L1)
126 qDBusParserError(
"Invalid D-Bus property access '%s' found in property '%s.%s' while "
127 "parsing introspection",
133 m_currentInterface->introspection +=
" <property access=\""_L1 +
access +
"\" type=\""_L1 + propertyData.
type +
"\" name=\""_L1 + propertyName + u
'"';
135 if (!readNextStartElement()) {
136 m_currentInterface->introspection +=
"/>\n"_L1;
138 m_currentInterface->introspection +=
">\n"_L1;
141 if (m_xml.name() ==
"annotation"_L1) {
143 }
else if (m_xml.prefix().isEmpty()) {
147 m_xml.skipCurrentElement();
148 }
while (readNextStartElement());
150 m_currentInterface->introspection +=
" </property>\n"_L1;
153 if (!m_xml.isEndElement() || m_xml.name() !=
"property"_L1) {
164 Q_ASSERT(m_xml.isStartElement() && m_xml.name() ==
"method"_L1);
169 qDBusParserError(
"Invalid D-Bus member name '%s' found in interface '%s' while parsing "
176 m_currentInterface->introspection +=
" <method name=\""_L1 +
methodName + u
'"';
182 if (!readNextStartElement()) {
183 m_currentInterface->introspection +=
"/>\n"_L1;
185 m_currentInterface->introspection +=
">\n"_L1;
188 if (m_xml.name() ==
"annotation"_L1) {
189 parseAnnotation(annotations);
190 }
else if (m_xml.name() ==
"arg"_L1) {
194 argument.location = m_currentLocation;
202 }
else if (m_xml.prefix().isEmpty()) {
206 m_xml.skipCurrentElement();
207 }
while (readNextStartElement());
209 m_currentInterface->introspection +=
" </method>\n"_L1;
222 Q_ASSERT(m_xml.isStartElement() && m_xml.name() ==
"signal"_L1);
228 qDBusParserError(
"Invalid D-Bus member name '%s' found in interface '%s' while parsing "
234 signalData.
name = signalName;
235 m_currentInterface->introspection +=
" <signal name=\""_L1 + signalName + u
'"';
240 if (!readNextStartElement()) {
241 m_currentInterface->introspection +=
"/>\n"_L1;
243 m_currentInterface->introspection +=
">\n"_L1;
246 if (m_xml.name() ==
"annotation"_L1) {
247 parseAnnotation(annotations);
248 }
else if (m_xml.name() ==
"arg"_L1) {
251 argument.location = m_currentLocation;
253 attributes.
value(
"direction"_L1) ==
"out"_L1) {
261 m_xml.skipCurrentElement();
262 }
while (readNextStartElement());
264 m_currentInterface->introspection +=
" </signal>\n"_L1;
273void QDBusXmlParser::readInterface()
277 const QString ifaceName = m_xml.attributes().value(
"name"_L1).toString();
279 qDBusParserError(
"Invalid D-Bus interface name '%s' found while parsing introspection",
286 m_currentInterface = std::make_unique<QDBusIntrospection::Interface>();
287 m_currentInterface->location = m_currentLocation;
288 m_currentInterface->name = ifaceName;
289 m_currentInterface->introspection +=
" <interface name=\""_L1 + ifaceName +
"\">\n"_L1;
291 while (readNextStartElement()) {
292 if (m_xml.name() ==
"method"_L1) {
294 methodData.
location = m_currentLocation;
295 if (parseMethod(methodData))
296 m_currentInterface->methods.insert(methodData.
name, methodData);
297 }
else if (m_xml.name() ==
"signal"_L1) {
299 signalData.
location = m_currentLocation;
300 if (parseSignal(signalData))
301 m_currentInterface->signals_.insert(signalData.
name, signalData);
302 }
else if (m_xml.name() ==
"property"_L1) {
304 propertyData.
location = m_currentLocation;
305 if (parseProperty(propertyData))
306 m_currentInterface->properties.insert(propertyData.
name, propertyData);
307 }
else if (m_xml.name() ==
"annotation"_L1) {
308 parseAnnotation(m_currentInterface->annotations,
true);
309 m_xml.skipCurrentElement();
311 if (m_xml.prefix().isEmpty()) {
315 m_xml.skipCurrentElement();
319 m_currentInterface->introspection +=
" </interface>"_L1;
325 if (!m_xml.isEndElement() || m_xml.name() !=
"interface"_L1) {
330void QDBusXmlParser::readNode(
int nodeLevel)
332 const QString objName = m_xml.attributes().value(
"name"_L1).toString();
339 qDBusParserError(
"Invalid D-Bus object path '%s' found while parsing introspection",
347 m_object->
location = m_currentLocation;
350void QDBusXmlParser::updateCurrentLocation()
358bool QDBusXmlParser::readNextStartElement()
360 updateCurrentLocation();
362 while (m_xml.readNext() != QXmlStreamReader::Invalid) {
363 if (m_xml.isEndElement())
365 else if (m_xml.isStartElement())
367 updateCurrentLocation();
374 : m_service(service),
381 m_object->
path = m_path;
385 while (!m_xml.atEnd()) {
386 updateCurrentLocation();
389 switch (m_xml.tokenType()) {
390 case QXmlStreamReader::StartElement:
391 if (m_xml.name() ==
"node"_L1) {
392 readNode(++nodeLevel);
393 }
else if (m_xml.name() ==
"interface"_L1) {
396 if (m_xml.prefix().isEmpty()) {
400 m_xml.skipCurrentElement();
403 case QXmlStreamReader::EndElement:
404 if (m_xml.name() ==
"node"_L1) {
411 case QXmlStreamReader::StartDocument:
412 case QXmlStreamReader::EndDocument:
413 case QXmlStreamReader::DTD:
416 case QXmlStreamReader::Comment:
419 case QXmlStreamReader::Characters:
421 if (m_xml.isWhitespace())
430 if (m_xml.hasError())
QDBusXmlParser(const QString &service, const QString &path, const QString &xmlData, QDBusIntrospection::DiagnosticsReporter *reporter=nullptr)
iterator insert(const Key &key, const T &value)
QString toString() const
Returns a deep copy of this string view's data as a QString.
\macro QT_RESTRICTED_CAST_FROM_ASCII
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
QString toHtmlEscaped() const
bool hasAttribute(QAnyStringView qualifiedName) const
Q_CORE_EXPORT QStringView value(QAnyStringView namespaceUri, QAnyStringView name) const noexcept
QList< QVariant > arguments
bool isValidMemberName(QStringView memberName)
Returns true if memberName is a valid member name.
bool isValidInterfaceName(const QString &ifaceName)
Returns true if this is ifaceName is a valid interface name.
bool isValidObjectPath(const QString &path)
Returns true if path is valid object path.
bool isValidSingleSignature(const QString &signature)
Returns true if signature is a valid D-Bus type signature for exactly one full type.
Combined button and popup list for selecting options.
static QString methodName(const QDBusIntrospection::Method &method)
#define qDBusParserError(format,...)
#define qDBusParserWarning(format,...)
#define Q_LOGGING_CATEGORY(name,...)
GLsizei const GLchar *const * path
#define qPrintable(string)