1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#ifndef QDBUSPENDINGREPLY_H
6#define QDBUSPENDINGREPLY_H
7
8#include <QtDBus/qtdbusglobal.h>
9#include <QtDBus/qdbusargument.h>
10#include <QtDBus/qdbuspendingcall.h>
11
12#ifndef QT_NO_DBUS
13
14class tst_QDBusPendingReply;
15
16QT_BEGIN_NAMESPACE
17
18
19class Q_DBUS_EXPORT QDBusPendingReplyBase : public QDBusPendingCall
20{
21protected:
22 QDBusPendingReplyBase();
23#if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
24 ~QDBusPendingReplyBase();
25 QDBusPendingReplyBase(const QDBusPendingReplyBase &) = default;
26 QDBusPendingReplyBase &operator=(const QDBusPendingReplyBase &) = default;
27 QDBusPendingReplyBase(QDBusPendingReplyBase &&) noexcept = default;
28 QDBusPendingReplyBase &operator=(QDBusPendingReplyBase &&) noexcept = default;
29#endif
30
31 void assign(const QDBusPendingCall &call);
32 void assign(const QDBusMessage &message);
33
34 QVariant argumentAt(int index) const;
35 void setMetaTypes(int count, const QMetaType *metaTypes);
36};
37
38namespace QDBusPendingReplyTypes {
39 template<int Index, typename T, typename... Types>
40 struct Select
41 {
42 typedef Select<Index - 1, Types...> Next;
43 typedef typename Next::Type Type;
44 };
45 template<typename T, typename... Types>
46 struct Select<0, T, Types...>
47 {
48 typedef T Type;
49 };
50
51 template<typename T> inline QMetaType metaTypeFor()
52 { return QMetaType::fromType<T>(); }
53 // specialize for QVariant, allowing it to be used in place of QDBusVariant
54 template<> inline QMetaType metaTypeFor<QVariant>()
55 { return QMetaType::fromType<QDBusVariant>(); }
56}
57
58
59template<typename... Types>
60class QDBusPendingReply : public QDBusPendingReplyBase
61{
62 friend class ::tst_QDBusPendingReply;
63 template<int Index> using Select = QDBusPendingReplyTypes::Select<Index, Types...>;
64public:
65 enum { Count = std::is_same_v<typename Select<0>::Type, void> ? 0 : sizeof...(Types) };
66
67 inline constexpr int count() const { return Count; }
68
69
70 inline QDBusPendingReply() = default;
71 inline QDBusPendingReply(const QDBusPendingReply &other)
72 : QDBusPendingReplyBase(other)
73 { }
74 QDBusPendingReply(QDBusPendingReply &&other) noexcept = default;
75 inline Q_IMPLICIT QDBusPendingReply(const QDBusPendingCall &call) // required by qdbusxml2cpp-generated code
76 { *this = call; }
77 inline Q_IMPLICIT QDBusPendingReply(const QDBusMessage &message)
78 { *this = message; }
79
80 inline QDBusPendingReply &operator=(const QDBusPendingReply &other)
81 { assign(other); return *this; }
82 QDBusPendingReply &operator=(QDBusPendingReply &&other) noexcept = default;
83 inline QDBusPendingReply &operator=(const QDBusPendingCall &call)
84 { assign(call); return *this; }
85 inline QDBusPendingReply &operator=(const QDBusMessage &message)
86 { assign(message); return *this; }
87
88 using QDBusPendingReplyBase::argumentAt;
89 template<int Index> inline
90 typename Select<Index>::Type argumentAt() const
91 {
92 static_assert(Index >= 0 && Index < Count, "Index out of bounds");
93 typedef typename Select<Index>::Type ResultType;
94 return qdbus_cast<ResultType>(argumentAt(Index));
95 }
96
97#if defined(Q_QDOC)
98 bool isFinished() const;
99 void waitForFinished();
100 QVariant argumentAt(int index) const;
101
102 bool isValid() const;
103 bool isError() const;
104 QDBusError error() const;
105 QDBusMessage reply() const;
106#endif
107
108 inline typename Select<0>::Type value() const
109 {
110 return argumentAt<0>();
111 }
112
113 inline operator typename Select<0>::Type() const
114 {
115 return argumentAt<0>();
116 }
117
118private:
119 inline void calculateMetaTypes()
120 {
121 if (!d) return;
122 if constexpr (Count == 0) {
123 setMetaTypes(count: 0, metaTypes: nullptr);
124 } else {
125 std::array<QMetaType, Count> typeIds = { QDBusPendingReplyTypes::metaTypeFor<Types>()... };
126 setMetaTypes(count: Count, metaTypes: typeIds.data());
127 }
128 }
129
130 inline void assign(const QDBusPendingCall &call)
131 {
132 QDBusPendingReplyBase::assign(call);
133 calculateMetaTypes();
134 }
135
136 inline void assign(const QDBusMessage &message)
137 {
138 QDBusPendingReplyBase::assign(message);
139 calculateMetaTypes();
140 }
141};
142
143template<>
144class QDBusPendingReply<> : public QDBusPendingReplyBase
145{
146 friend class ::tst_QDBusPendingReply;
147public:
148 enum { Count = 0 };
149 inline int count() const { return Count; }
150
151 inline QDBusPendingReply() = default;
152 inline QDBusPendingReply(const QDBusPendingReply &other)
153 : QDBusPendingReplyBase(other)
154 { }
155 QDBusPendingReply(QDBusPendingReply &&other) noexcept = default;
156 inline Q_IMPLICIT QDBusPendingReply(const QDBusPendingCall &call) // required by qdbusxml2cpp-generated code
157 { *this = call; }
158 inline Q_IMPLICIT QDBusPendingReply(const QDBusMessage &message)
159 { *this = message; }
160
161 inline QDBusPendingReply &operator=(const QDBusPendingReply &other)
162 { assign(call: other); return *this; }
163 QDBusPendingReply &operator=(QDBusPendingReply &&other) noexcept = default;
164 inline QDBusPendingReply &operator=(const QDBusPendingCall &call)
165 { assign(call); return *this; }
166 inline QDBusPendingReply &operator=(const QDBusMessage &message)
167 { assign(message); return *this; }
168
169private:
170 inline void assign(const QDBusPendingCall &call)
171 {
172 QDBusPendingReplyBase::assign(call);
173 if (d)
174 setMetaTypes(count: 0, metaTypes: nullptr);
175 }
176
177 inline void assign(const QDBusMessage &message)
178 {
179 QDBusPendingReplyBase::assign(message);
180 if (d)
181 setMetaTypes(count: 0, metaTypes: nullptr);
182 }
183
184};
185
186QT_END_NAMESPACE
187
188#endif // QT_NO_DBUS
189#endif
190

source code of qtbase/src/dbus/qdbuspendingreply.h