1// Copyright (C) 2022 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
4#ifndef QPROTOBUFMESSAGE_H
5#define QPROTOBUFMESSAGE_H
6
7#include <QtProtobuf/qtprotobufexports.h>
8
9#include <QtCore/qanystringview.h>
10#include <QtCore/qbytearray.h>
11#include <QtCore/qbytearrayview.h>
12#include <QtCore/qlist.h>
13#include <QtCore/qmetaobject.h>
14#include <QtCore/qshareddata.h>
15#include <QtCore/qtmetamacros.h>
16
17QT_BEGIN_NAMESPACE
18
19class QAbstractProtobufSerializer;
20struct QMetaObject;
21class QVariant;
22
23class QProtobufMessage;
24struct QProtobufMessageDeleter {
25 Q_PROTOBUF_EXPORT void operator()(QProtobufMessage *ptr) const noexcept;
26};
27using QProtobufMessagePointer = std::unique_ptr<QProtobufMessage, QProtobufMessageDeleter>;
28
29namespace QtProtobufPrivate {
30struct QProtobufPropertyOrdering;
31}
32
33class QProtobufMessagePrivate;
34QT_DECLARE_QESDP_SPECIALIZATION_DTOR(QProtobufMessagePrivate)
35
36class QProtobufMessage
37{
38 Q_GADGET_EXPORT(Q_PROTOBUF_EXPORT)
39public:
40 Q_PROTOBUF_EXPORT QVariant property(QAnyStringView propertyName) const;
41 Q_PROTOBUF_EXPORT bool setProperty(QAnyStringView propertyName, const QVariant &value);
42 Q_PROTOBUF_EXPORT bool setProperty(QAnyStringView propertyName, QVariant &&value);
43
44 [[nodiscard]]
45 Q_PROTOBUF_EXPORT static QProtobufMessagePointer constructByName(const QString &messageType);
46
47 Q_PROTOBUF_EXPORT QList<qint32> unknownFieldNumbers() const;
48 Q_PROTOBUF_EXPORT QList<QByteArray> unknownFieldData(qint32 field) const;
49
50 Q_PROTOBUF_EXPORT QByteArray serialize(QAbstractProtobufSerializer *serializer) const;
51 Q_PROTOBUF_EXPORT bool deserialize(QAbstractProtobufSerializer *serializer,
52 QByteArrayView data);
53
54 Q_PROTOBUF_EXPORT const QtProtobufPrivate::QProtobufPropertyOrdering *propertyOrdering() const;
55
56protected:
57 Q_PROTOBUF_EXPORT
58 explicit QProtobufMessage(const QMetaObject *metaObject,
59 const QtProtobufPrivate::QProtobufPropertyOrdering *ordering);
60 Q_PROTOBUF_EXPORT explicit QProtobufMessage(QProtobufMessagePrivate &dd);
61
62 Q_PROTOBUF_EXPORT ~QProtobufMessage();
63 Q_PROTOBUF_EXPORT QProtobufMessage(const QProtobufMessage &other);
64 Q_PROTOBUF_EXPORT QProtobufMessage &operator=(const QProtobufMessage &other);
65 QProtobufMessage(QProtobufMessage &&other) noexcept = default;
66 QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_PURE_SWAP(QProtobufMessage)
67
68 void swap(QProtobufMessage &other) noexcept
69 {
70 d_ptr.swap(other&: other.d_ptr);
71 }
72private:
73 friend Q_PROTOBUF_EXPORT bool comparesEqual(const QProtobufMessage &lhs,
74 const QProtobufMessage &rhs) noexcept;
75 Q_DECLARE_EQUALITY_COMPARABLE(QProtobufMessage);
76
77 friend struct QProtobufMessageDeleter;
78
79 Q_DECLARE_PRIVATE(QProtobufMessage)
80
81protected:
82 QExplicitlySharedDataPointer<QProtobufMessagePrivate> d_ptr;
83};
84
85class QProtobufMapEntryBasePrivate;
86class QProtobufMapEntryBase : public QProtobufMessage
87{
88 Q_GADGET_EXPORT(Q_PROTOBUF_EXPORT)
89 friend QMetaObject *buildMetaObject(QMetaType, QMetaType);
90 using StaticMetaCallFn = void (*)(QObject *, QMetaObject::Call, int, void **);
91
92protected:
93 Q_PROTOBUF_EXPORT explicit QProtobufMapEntryBase(QMetaType key, QMetaType value,
94 StaticMetaCallFn metaCall);
95 Q_PROTOBUF_EXPORT ~QProtobufMapEntryBase();
96
97private:
98 Q_DECLARE_PRIVATE(QProtobufMapEntryBase)
99 Q_DISABLE_COPY_MOVE(QProtobufMapEntryBase)
100};
101
102template <typename Key, typename Value>
103class QProtobufMapEntry : public QProtobufMapEntryBase
104{
105 static void metaCall(QObject *object, QMetaObject::Call call, int index, void **args)
106 {
107 static constexpr bool needsHasValue = ResolveType<Value>::NeedsHasFunction;
108
109 QProtobufMapEntry *entry = reinterpret_cast<QProtobufMapEntry *>(object);
110 if (call == QMetaObject::ReadProperty) {
111 if (index == 0)
112 *reinterpret_cast<KeyType *>(args[0]) = entry->key();
113 if (index == 1)
114 *reinterpret_cast<ValueType *>(args[0]) = entry->value();
115 if constexpr (needsHasValue) {
116 if (index == 2)
117 *reinterpret_cast<bool *>(args[0]) = entry->hasValue();
118 }
119 } else if (call == QMetaObject::WriteProperty) {
120 if (index == 0) {
121 entry->setKey(*reinterpret_cast<KeyType *>(args[0]));
122 } else if (index == 1 || index == 2 ) {
123 entry->setValue(*reinterpret_cast<ValueType *>(args[0]));
124 }
125 }
126 }
127
128 template <typename T, typename = void>
129 struct ResolveType {
130 using type = std::remove_const_t<T>;
131 static constexpr bool NeedsHasFunction = false;
132 };
133 template<typename T>
134 struct ResolveType<T, std::enable_if_t<std::is_base_of_v<QProtobufMessage, T>>> {
135 using type = std::conditional_t<std::is_const_v<T>, T const *, T *>;
136 static constexpr bool NeedsHasFunction = true;
137 };
138
139public:
140 using KeyType = Key;
141 using ValueType = typename ResolveType<Value>::type;
142
143 QProtobufMapEntry()
144 : QProtobufMapEntryBase(QMetaType::fromType<KeyType>(), QMetaType::fromType<ValueType>(),
145 &QProtobufMapEntry::metaCall)
146 {
147 }
148 ~QProtobufMapEntry() {
149 if constexpr (std::is_pointer_v<ValueType>) {
150 if (m_ownsValue)
151 delete m_value;
152 }
153 }
154
155 const KeyType &key() const &
156 {
157 return m_key;
158 }
159 KeyType key() &&
160 {
161 return std::move(m_key);
162 }
163
164 const ValueType &value() const &
165 {
166 ensureValue();
167 return m_value;
168 }
169 ValueType value() &&
170 {
171 ensureValue();
172 m_ownsValue = false;
173 return std::move(m_value);
174 }
175 bool hasValue() const
176 {
177 if constexpr (ResolveType<Value>::NeedsHasFunction)
178 return m_value != nullptr;
179 return true;
180 }
181
182 void setKey(const KeyType &key)
183 {
184 m_key = key;
185 }
186 void setKey(KeyType &&key)
187 {
188 m_key = std::move(key);
189 }
190 void setValue(const ValueType &value)
191 {
192 if (m_value == value)
193 return;
194 cleanupValue();
195 m_value = value;
196 }
197 void setValue(ValueType &&value)
198 {
199 if (m_value == value)
200 return;
201 cleanupValue();
202 m_value = std::move(value);
203 }
204
205private:
206 void ensureValue() const
207 {
208 if constexpr (std::is_pointer_v<ValueType>) {
209 if (!m_value) {
210 m_value = new Value;
211 m_ownsValue = true;
212 }
213 }
214 }
215
216 void cleanupValue() const
217 {
218 if constexpr (std::is_pointer_v<ValueType>) {
219 if (m_ownsValue) {
220 delete m_value;
221 m_value = nullptr;
222 m_ownsValue = false;
223 }
224 }
225 }
226
227 mutable KeyType m_key{};
228 mutable ValueType m_value{};
229 mutable bool m_ownsValue = false;
230
231 Q_DISABLE_COPY_MOVE(QProtobufMapEntry)
232};
233
234QT_END_NAMESPACE
235
236#endif // QPROTOBUFMESSAGE_H
237

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtgrpc/src/protobuf/qprotobufmessage.h