1// Copyright (C) 2024 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#include <QtProtobuf/qprotobufregistration.h>
5
6#include <QtProtobuf/private/qprotobufregistration_p.h>
7#include <QtProtobuf/qtprotobuftypes.h>
8
9#include <QtCore/qmutex.h>
10#include <QtCore/qmetatype.h>
11#include <QtCore/qreadwritelock.h>
12
13#include <mutex>
14
15QT_BEGIN_NAMESPACE
16
17/*!
18 \relates QtProtobuf
19 \fn template<typename T, QtProtobuf::if_protobuf_message<T> = true> inline void qRegisterProtobufType()
20
21 Registers a Protobuf type \e T.
22 This function is normally called by generated code.
23*/
24
25/*!
26 \relates QtProtobuf
27 \fn template<typename K, typename V, QtProtobuf::if_protobuf_map<K, V> = true> inline void qRegisterProtobufMapType();
28
29 Registers a Protobuf map type \c K and \c V.
30 \c V must be a QProtobufMessage.
31 This function is normally called by generated code.
32*/
33
34/*!
35 \relates QtProtobuf
36 \fn template <typename T, typename std::enable_if_t<std::is_enum<T>::value, bool> = true> inline void qRegisterProtobufEnumType();
37
38 Registers serializers for enumeration type \c T in QtProtobuf global
39 serializers registry.
40
41 This function is normally called by generated code.
42*/
43
44namespace {
45std::vector<QtProtobuf::RegisterFunction> &registerFunctions()
46{
47 // no need for implicit sharing etc, so stick with std::vector
48 static std::vector<QtProtobuf::RegisterFunction> registrationList;
49 return registrationList;
50}
51
52template<typename T>
53void registerBasicConverters()
54{
55 QMetaType::registerConverter<int32_t, T>(T::fromType);
56 QMetaType::registerConverter<T, int32_t>(T::toType);
57 QMetaType::registerConverter<int64_t, T>(T::fromType);
58 QMetaType::registerConverter<T, int64_t>(T::toType);
59 QMetaType::registerConverter<uint32_t, T>(T::fromType);
60 QMetaType::registerConverter<T, uint32_t>(T::toType);
61 QMetaType::registerConverter<uint64_t, T>(T::fromType);
62 QMetaType::registerConverter<T, uint64_t>(T::toType);
63 if constexpr (!std::is_same_v<long long, int64_t>) {
64 QMetaType::registerConverter<long long, T>(T::fromType);
65 QMetaType::registerConverter<T, long long>(T::toType);
66 QMetaType::registerConverter<unsigned long long, T>(T::fromType);
67 QMetaType::registerConverter<T, unsigned long long>(T::toType);
68 }
69 QMetaType::registerConverter<double, T>(T::fromType);
70 QMetaType::registerConverter<T, double>(T::toType);
71 QMetaType::registerConverter<T, QString>(T::toString);
72}
73
74static void qRegisterBaseTypes()
75{
76 [[maybe_unused]] // definitely unused
77 static bool registered = [] {
78 qRegisterMetaType<QtProtobuf::int32>();
79 qRegisterMetaType<QtProtobuf::int64>();
80 qRegisterMetaType<QtProtobuf::uint32>();
81 qRegisterMetaType<QtProtobuf::uint64>();
82 qRegisterMetaType<QtProtobuf::sint32>();
83 qRegisterMetaType<QtProtobuf::sint64>();
84 qRegisterMetaType<QtProtobuf::fixed32>();
85 qRegisterMetaType<QtProtobuf::fixed64>();
86 qRegisterMetaType<QtProtobuf::sfixed32>();
87 qRegisterMetaType<QtProtobuf::sfixed64>();
88 qRegisterMetaType<QtProtobuf::boolean>();
89
90 qRegisterMetaType<QtProtobuf::int32List>();
91 qRegisterMetaType<QtProtobuf::int64List>();
92 qRegisterMetaType<QtProtobuf::uint32List>();
93 qRegisterMetaType<QtProtobuf::uint64List>();
94 qRegisterMetaType<QtProtobuf::sint32List>();
95 qRegisterMetaType<QtProtobuf::sint64List>();
96 qRegisterMetaType<QtProtobuf::fixed32List>();
97 qRegisterMetaType<QtProtobuf::fixed64List>();
98 qRegisterMetaType<QtProtobuf::sfixed32List>();
99 qRegisterMetaType<QtProtobuf::sfixed64List>();
100
101 qRegisterMetaType<QtProtobuf::doubleList>();
102 qRegisterMetaType<QtProtobuf::floatList>();
103 qRegisterMetaType<QtProtobuf::boolList>();
104
105 registerBasicConverters<QtProtobuf::int32>();
106 registerBasicConverters<QtProtobuf::int64>();
107 registerBasicConverters<QtProtobuf::sfixed32>();
108 registerBasicConverters<QtProtobuf::sfixed64>();
109 registerBasicConverters<QtProtobuf::fixed32>();
110 registerBasicConverters<QtProtobuf::fixed64>();
111 return true;
112 }();
113}
114
115/*
116 \internal
117 \brief The HandlersRegistry is a container to store mapping between metatype
118 identifier and serialization handlers.
119*/
120struct HandlersRegistry
121{
122 void registerHandler(QMetaType type, QtProtobufPrivate::Serializer serializer,
123 QtProtobufPrivate::Deserializer deserializer)
124 {
125 QWriteLocker locker(&m_lock);
126 m_registry[type] = { .serializer: serializer, .deserializer: deserializer };
127 }
128
129 QtProtobufPrivate::SerializationHandler findHandler(QMetaType type)
130 {
131 QReadLocker locker(&m_lock);
132 auto it = m_registry.constFind(key: type);
133 if (it != m_registry.constEnd())
134 return it.value();
135 return {};
136 }
137
138private:
139 QReadWriteLock m_lock;
140 QHash<QMetaType, QtProtobufPrivate::SerializationHandler> m_registry;
141};
142Q_GLOBAL_STATIC(HandlersRegistry, handlersRegistry)
143
144
145Q_CONSTINIT QBasicMutex registerMutex;
146}
147
148void QtProtobufPrivate::registerHandler(QMetaType type, Serializer serializer,
149 Deserializer deserializer)
150{
151 handlersRegistry->registerHandler(type, serializer, deserializer);
152}
153
154QtProtobufPrivate::SerializationHandler QtProtobufPrivate::findHandler(QMetaType type)
155{
156 if (!handlersRegistry.exists())
157 return {};
158 return handlersRegistry->findHandler(type);
159}
160
161namespace QtProtobuf {
162
163ProtoTypeRegistrar::ProtoTypeRegistrar(QtProtobuf::RegisterFunction initializer)
164{
165 std::scoped_lock lock(registerMutex);
166 registerFunctions().push_back(x: initializer);
167}
168
169}
170
171/*!
172 \relates QtProtobuf
173 Calling this function registers all, currently known, protobuf types with
174 the serializer registry.
175
176 \note Only since Qt 6.6.3 version you don't have to call this function manually,
177 as it is called automatically. For earlier versions it's better to call it
178 before serialization/deserialization attempt.
179*/
180void qRegisterProtobufTypes()
181{
182 qRegisterBaseTypes();
183
184 std::scoped_lock lock(registerMutex);
185 std::vector<QtProtobuf::RegisterFunction> registrationList;
186 registrationList.swap(x&: registerFunctions());
187
188 for (QtProtobuf::RegisterFunction registerFunc : registrationList)
189 registerFunc();
190}
191
192/*!
193 \class template <typename T, QtProtobuf::if_protobuf_message<T> = true> class QtProtobufPrivate::ListIterator
194 \internal
195*/
196
197/*!
198 \class template <typename K, typename V, QtProtobuf::if_protobuf_map<K, V> = true> class QtProtobufPrivate::MapIterator
199 \internal
200*/
201
202/*!
203 \struct QtProtobufPrivate::SerializationHandler
204 \internal
205 \brief SerializationHandlers contains set of objects that are required for
206 class serialization/deserialization.
207*/
208
209QT_END_NAMESPACE
210

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtgrpc/src/protobuf/qprotobufregistration.cpp